summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-26 09:15:08 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-26 09:15:08 +0200
commit155c2e55948dc179a45458d856808f7105878d1f (patch)
tree341c33054cc06d9d407b98797c96a5f7f880dcad
parent9a915291c3e76dd6cbaea92910ed9cfe3398062d (diff)
downloadcolitur-155c2e55948dc179a45458d856808f7105878d1f.tar.gz
colitur-155c2e55948dc179a45458d856808f7105878d1f.zip
feat(of): Lectionary_of -- reading-cycle arithmetic and the lectionary chain
Task 4 of Phases 3-5: the last Rite.t field OF still needed, `readings`. The cycle rules are CODE, cited to OLM (Ordo Lectionum Missae) 1981 Praenotanda -- verified against the real page image (docs/research/of/olm-1981.pdf pp.32-33/"XXXII-XXXIII"), not the document's own unreliable OCR text layer, per the design spec's own caveat. n. 66 (with its footnote 102's worked example, 1980=C/1981=A/ 1982=B/1983=C) gives the three-year Sunday cycle; n. 69 point 4 gives the two-year weekday cycle, Year I in odd label years, Year II in even. Both derive the "label year" the same way: one more than the civil year Advent I opened in, per n. 66's footnote 102 itself ("nempe a prima hebdomada Adventus, quae cadit in anno civili praecedente") -- so the cycle turns at Advent I, not 1 January, exactly where the task brief said to get it right. The design spec's own citation for the weekday rule, "Praenotanda n. 649", does not survive a direct check against the primary source (search finds "649" only in unrelated index/page-number entries); corrected here to n. 69, the paragraph the rule's own Latin text actually sits under, confirmed by the page image's own printed margin number. The data is bootstrapped from lectio's of-lectionary.ini (988 keys, niedziela.pl, harvest 2020-2025) by tools/bootstrap_lectionary_of.ml -- OCaml, not the brief's own suggested .py: tools/bootstrap_lectionary .ml already established this exact shape for EF, including a real safety net ([assert_reachable], sweeping Rite_of.Temporal_of.temporal AND the real merged sanctoral layer directly) that a second-language reimplementation would either duplicate or lose. Handles two real data anomalies found while building it: one malformed ini line (a Polish Septuagint-numbering annotation for Sirach 3, "Syr 3,2-6.12-14" against OLM/CEI/USA's shared Nova Vulgata, matching the design spec's own sec5 finding); and two Sunday-cycle-labelled bases (Annunciation, Immaculate Conception) where a scraping-year artifact left one of three cycle letters carrying a different day's Mass entirely -- resolved by a general, mechanical 2-of-3 majority rule, not a per-saint hand edit, and logged. Coverage measured in both directions, per the brief's own Step 1: - 1 of 365 days in civil year 2026 (25 December, the Christmas DAY Mass) has no Temporal_of-slug match anywhere in lectio's 988 keys -- only the Vigil is present. Named in the data file's own header. - 0 of 438 distinct lectio bases map to no colitur slug, after 19 are deliberately excluded (late-Advent/Christmas-season DATE-keyed duplicates lectio also carries in a WEEKDAY-keyed form colitur's own slugs actually match -- Lectionary.t has no date-keyed lookup at all, so the date-keyed family is transcription-inert, not silently dropped: named explicitly, not a residual). Lectionary_of.readings is three steps (no Commons indirection, unlike EF -- out of this task's scope): the observed celebration's own embedded citations; else, for a real sanctoral winner, its own slug looked up directly (flat, then both cycle letters); else the day's own temporal slug, same lookup. No preceding-Sunday fallback: OF's own two-year cycle assigns every Ordinary Time weekday its own reading by design, and no OF norm was found instructing otherwise. Tests (test/test_lectionary_of.ml, 12 cases): a cycle-arithmetic table straddling Advent 1980/1981/1982/2025 inside single civil years, reproducing OLM n.66's own worked example directly; SHA-256 pins on both the emitted file and lectio's own source (embedded in the provenance header); a pinned, NAMED 2026 coverage result (364 resolve, exactly {25 December} does not -- never a bare count); two resolution- chain spot checks (a plain ferial, and a saint's day beating the ferial it would otherwise fall on); and a real subprocess test that a missing lectio source file fails the generator loudly, non-zero exit, no output written -- the exact bug Task 1's own generator shipped and needed a review round to fix. dune test: exit 0, 856 tests. make check (COLITUR_EXHAUSTIVE_SWEEP=1, full 1583-9999 sweep): exit 0, 862 tests, ~342s, both run unpiped in the foreground. git diff --stat v1.0.0..HEAD -- lib/rites/rite_ef/ lib/kernel/ data/ef/ still empty.
-rw-r--r--data/of/lectionary.sexp2317
-rw-r--r--lib/rites/rite_of/lectionary_of.ml107
-rw-r--r--lib/rites/rite_of/lectionary_of.mli136
-rw-r--r--test/dune2
-rw-r--r--test/test_colitur.ml1
-rw-r--r--test/test_lectionary_of.ml372
-rw-r--r--tools/bootstrap_lectionary_of.ml827
-rw-r--r--tools/dune15
8 files changed, 3777 insertions, 0 deletions
diff --git a/data/of/lectionary.sexp b/data/of/lectionary.sexp
new file mode 100644
index 0000000..4f43f12
--- /dev/null
+++ b/data/of/lectionary.sexp
@@ -0,0 +1,2317 @@
+; data/of/lectionary.sexp -- OF (2002) temporal + sanctoral lectionary
+; (Epistle + Gospel citations, never scripture text), bootstrapped from
+; lectio.
+;
+; LINEAGE, stated loudly because it constrains what this file can show
+; (design spec 2026-08-24-colitur-of-rite-module-design.md sec4.4/sec5):
+; this is a POLISH VERNACULAR pastoral lectionary (niedziela.pl,
+; harvested 2020-2025 by lectio's own scripts/genlect-of.go), NOT the
+; Latin OLM (Ordo Lectionum Missae) 1981 itself, and its citations are
+; ENGLISH-CANONICAL, not OLM's Vulgate numbering. It CANNOT show any
+; divergence between niedziela.pl's own pastoral choices and OLM's own
+; text -- three such divergences are already confirmed against the real
+; OLM page images (design spec sec4.4): Holy Family Year A's second-
+; reading short form, Trinity Sunday's Dan 3:56, and the Baptism of the
+; Lord's Mc 9:6 vs "Mark 9:7". Nor can it show OLM's short/long-form
+; reading alternatives, which niedziela.pl does not distinguish. This is
+; ALSO a SEPARATE lineage from lectio's own OF CALENDAR data
+; (data/of/calendar-2002.sexp, roman-calendar.ini, upstream
+; calapi.inadiutorium.cz) -- lectio is two unrelated upstreams glued
+; together by one downstream project, not one witness, and neither is
+; the typical edition.
+;
+; Generator: tools/bootstrap_lectionary_of.ml -- do not hand-edit;
+; re-run against the same lectio snapshot (its SHA-256 is pinned below;
+; a MISSING source file is fatal, checked before any read is attempted --
+; see this generator's own [parse_ini]) and commit the diff instead.
+; Every emitted key is asserted, at generation time, to be a slug
+; Rite_of.Temporal_of actually computes OR a slug the real merged
+; sanctoral layer (data/of/calendar-2002.sexp + all 13 decree overlays)
+; actually carries -- see [assert_reachable].
+;
+; Source: ../lectio/internal/caldata/of-lectionary.ini
+; SHA-256: f0b527aef58b93e6ccdfbeafe52b340ed2a9d7d72805bf5083e3da04b080123c
+; 988 ini sections (988 expected) -> 438 resolved (base, cycle-shape) pairs -> 419 colitur slugs mapped, 19 ini bases deliberately excluded (date-
+; keyed duplicates/late-Advent, no colitur date-keyed lookup exists --
+; see [excluded_bases]), 0 ini bases genuinely unmapped (no pattern, no
+; override, no matching sanctoral slug) -> 754 emitted lectionary entries.
+;
+; COVERAGE, BOTH DIRECTIONS (Step 1 of this task's own brief):
+; (1) Temporal-day gap: of the 365 days of civil year 2026, 1 produce a
+; Rite_of.Temporal_of slug with NO entry in this file (tried flat,
+; then both the Sunday- and weekday-cycle letter suffixes -- the
+; same order Lectionary_of.readings itself tries). Those are days
+; with no readings via the temporal-slug path (a sanctoral proper
+; on the same civil day, where one exists, is Lectionary_of's own
+; separate first chance). Named set below.
+; (2) Unmapped lectio keys: 0 ini base names (of 988 sections, 438
+; distinct bases) map to no colitur slug at all -- data being
+; silently dropped if unreported. Named below.
+; Regenerate with:
+; eval $(opam env) && dune exec tools/bootstrap_lectionary_of.exe -- ../lectio/internal/caldata/of-lectionary.ini data/of/lectionary.sexp
+; Unmapped lectio bases (0):
+; Temporal_of slugs (2004-2051) with no lectionary entry (1, informational --
+; most are the Christmas-season/late-Advent date-vs-weekday gap named above):
+; of-nativity
+((all-saints
+ (((part First) (reference "Revelation 7:2-4,9-14"))
+ ((part Gospel) (reference "Mat 5:1-12"))))
+ (all-souls
+ (((part First) (reference "Job 19:1,23-27"))
+ ((part Gospel) (reference "Luke 23:44-46,50,52-53"))))
+ (andrew-the-apostle
+ (((part First) (reference "Isaiah 49:1-6"))
+ ((part Gospel) (reference "Mat 4:18-22"))))
+ (annunciation-of-the-lord
+ (((part First) (reference "Isaiah 7:10-14;8:10"))
+ ((part Gospel) (reference "Luke 1:26-38"))))
+ (assumption-of-the-blessed-virgin-mary
+ (((part First) (reference "1 Chronicles 15:3-4,15-16;16:1-2"))
+ ((part Gospel) (reference "Luke 11:27-28"))))
+ (bartholomew-the-apostle
+ (((part First) (reference "Revelation 21:9-14"))
+ ((part Gospel) (reference "John 1:45-51"))))
+ (birth-of-saint-john-the-baptist
+ (((part First) (reference "Jeremiah 1:4-10"))
+ ((part Gospel) (reference "Luke 1:5-17"))))
+ (birth-of-the-blessed-virgin-mary
+ (((part First) (reference "Micah 5:1-4"))
+ ((part Gospel) (reference "Mat 1:18-23"))))
+ (chair-of-saint-peter-apostle
+ (((part First) (reference "1 Peter 5:1-4"))
+ ((part Gospel) (reference "Mat 16:13-19"))))
+ (dedication-of-the-lateran-basilica
+ (((part First) (reference "Ezekiel 47:1-2,8-9,12"))
+ ((part Gospel) (reference "John 2:13-22"))))
+ (holy-innocents-martyrs
+ (((part First) (reference "1 John 1:5-2:2"))
+ ((part Gospel) (reference "Mat 2:13-18"))))
+ (immaculate-conception-of-the-blessed-virgin-mary
+ (((part First) (reference "Genesis 3:9-15,20"))
+ ((part Gospel) (reference "Luke 1:26-38"))))
+ (james-apostle
+ (((part First) (reference "2 Corinthians 4:7-15"))
+ ((part Gospel) (reference "Mat 20:20-28"))))
+ (john-the-apostle-and-evangelist
+ (((part First) (reference "1 John 1:1-4"))
+ ((part Gospel) (reference "John 20:2-8"))))
+ (joseph-husband-of-the-blessed-virgin-mary
+ (((part First) (reference "2 Samuel 7:4-5,12-14,16"))
+ ((part Gospel) (reference "Luke 2:41-51"))))
+ (lawrence-deacon-and-martyr
+ (((part First) (reference "2 Corinthians 9:6-10"))
+ ((part Gospel) (reference "John 12:24-26"))))
+ (luke-the-evangelist
+ (((part First) (reference "2 Timothy 4:10-17"))
+ ((part Gospel) (reference "Luke 10:1-9"))))
+ (mark-the-evangelist
+ (((part First) (reference "1 Peter 5:5-14"))
+ ((part Gospel) (reference "Mark 16:15-20"))))
+ (mary-magdalene
+ (((part First) (reference "Song of Solomon 8:6-7"))
+ ((part Gospel) (reference "John 20:1,11-18"))))
+ (matthew-the-evangelist-apostle-evangelist
+ (((part First) (reference "Ephesians 4:1-7,11-13"))
+ ((part Gospel) (reference "Mat 9:9-13"))))
+ (matthias-the-apostle
+ (((part First) (reference "Acts 1:15-17,20-26"))
+ ((part Gospel) (reference "John 15:9-17"))))
+ (of-advent-1-friday
+ (((part First) (reference "Isaiah 29:17-24"))
+ ((part Gospel) (reference "Matthew 9:27-31"))))
+ (of-advent-1-monday
+ (((part First) (reference "Isaiah 2:1-5"))
+ ((part Gospel) (reference "Matthew 8:5-11"))))
+ (of-advent-1-saturday
+ (((part First) (reference "Isaiah 30:19-21,23-26"))
+ ((part Gospel) (reference "Matthew 9:35-10:1,5a,6-8"))))
+ (of-advent-1-thursday
+ (((part First) (reference "Isaiah 26:1-6"))
+ ((part Gospel) (reference "Matthew 7:21,24-27"))))
+ (of-advent-1-tuesday
+ (((part First) (reference "Isaiah 11:1-10"))
+ ((part Gospel) (reference "Luke 10:21-24"))))
+ (of-advent-1-wednesday
+ (((part First) (reference "Isaiah 25:6-10a"))
+ ((part Gospel) (reference "Matthew 15:29-37"))))
+ (of-advent-2-friday
+ (((part First) (reference "Isaiah 48:17-19"))
+ ((part Gospel) (reference "Matthew 11:16-19"))))
+ (of-advent-2-monday
+ (((part First) (reference "Isaiah 35:1-10"))
+ ((part Gospel) (reference "Luke 5:17-26"))))
+ (of-advent-2-saturday
+ (((part First) (reference "Sirach 48:1-4,9-11"))
+ ((part Gospel) (reference "Matthew 17:9a,10-135"))))
+ (of-advent-2-thursday
+ (((part First) (reference "Isaiah 41:13-20"))
+ ((part Gospel) (reference "Matthew 11:11-15"))))
+ (of-advent-2-tuesday
+ (((part First) (reference "Isaiah 40:1-11"))
+ ((part Gospel) (reference "Matthew 18:12-14"))))
+ (of-advent-2-wednesday
+ (((part First) (reference "Isaiah 40:25-31"))
+ ((part Gospel) (reference "Matthew 11:28-30"))))
+ (of-advent-3-friday
+ (((part First) (reference "Isaiah 56:1-3a,6-8"))
+ ((part Gospel) (reference "John 5:33-36"))))
+ (of-advent-3-monday
+ (((part First) (reference "Numbers 24:2-7,15-17a"))
+ ((part Gospel) (reference "Matthew 21:23-27"))))
+ (of-advent-3-saturday-i
+ (((part First) (reference "1 Samuel 1:24-28"))
+ ((part Gospel) (reference "Luke 1:46-56"))))
+ (of-advent-3-saturday-ii
+ (((part First) (reference "Song of Solomon 2:8-14"))
+ ((part Gospel) (reference "Luke 1:39-45"))))
+ (of-advent-3-thursday
+ (((part First) (reference "Isaiah 54:1-10"))
+ ((part Gospel) (reference "Luke 7:24-30"))))
+ (of-advent-3-tuesday
+ (((part First) (reference "Zephaniah 3:1-2,9-13"))
+ ((part Gospel) (reference "Matthew 21:28-32"))))
+ (of-advent-3-wednesday
+ (((part First) (reference "Isaiah 45:6c-8,18,21c-25"))
+ ((part Gospel) (reference "Luke 7:18b-23"))))
+ (of-advent-4-friday-i
+ (((part First) (reference "Malachi 3:1-4;4:5-6"))
+ ((part Gospel) (reference "Luke 1:57-66"))))
+ (of-advent-4-friday-ii
+ (((part First) (reference "2 Samuel 7:1-5,8-12,14,16"))
+ ((part Gospel) (reference "Luke 1:67-79"))))
+ (of-advent-4-monday-i
+ (((part First) (reference "2 Samuel 7:1-5,8-12,14,16"))
+ ((part Gospel) (reference "Luke 1:67-79"))))
+ (of-advent-4-monday-ii
+ (((part First) (reference "Malachi 3:1-4;4:5-6"))
+ ((part Gospel) (reference "Luke 1:57-66"))))
+ (of-advent-4-thursday-i
+ (((part First) (reference "2 Samuel 7:1-5,8-12,14,16"))
+ ((part Gospel) (reference "Luke 1:67-79"))))
+ (of-advent-4-thursday-ii
+ (((part First) (reference "Malachi 3:1-4;4:5-6"))
+ ((part Gospel) (reference "Luke 1:57-66"))))
+ (of-advent-4-tuesday-i
+ (((part First) (reference "1 Samuel 1:24-28"))
+ ((part Gospel) (reference "Luke 1:46-56"))))
+ (of-advent-4-tuesday-ii
+ (((part First) (reference "2 Samuel 7:1-5,8-12,14,16"))
+ ((part Gospel) (reference "Luke 1:67-79"))))
+ (of-advent-4-wednesday-i
+ (((part First) (reference "Malachi 3:1-4;4:5-6"))
+ ((part Gospel) (reference "Luke 1:57-66"))))
+ (of-advent-4-wednesday-ii
+ (((part First) (reference "1 Samuel 1:24-28"))
+ ((part Gospel) (reference "Luke 1:46-56"))))
+ (of-advent-sunday-1-a
+ (((part First) (reference "Isaiah 2:1-5"))
+ ((part Gospel) (reference "Matthew 24:37-44"))))
+ (of-advent-sunday-1-b
+ (((part First) (reference "Isaiah 63:16b-17,19b;64:2-7"))
+ ((part Gospel) (reference "Mark 13:33-37"))))
+ (of-advent-sunday-1-c
+ (((part First) (reference "Jeremiah 33:14-16"))
+ ((part Gospel) (reference "Luke 21:25-28,34-36"))))
+ (of-advent-sunday-2-a
+ (((part First) (reference "Isaiah 11:1-10"))
+ ((part Gospel) (reference "Matthew 3:1-12"))))
+ (of-advent-sunday-2-b
+ (((part First) (reference "Isaiah 40:1-5,9-11"))
+ ((part Gospel) (reference "Mark 1:1-8"))))
+ (of-advent-sunday-2-c
+ (((part First) (reference "Baruch 5:1-9"))
+ ((part Gospel) (reference "Luke 3:1-6"))))
+ (of-advent-sunday-3-a
+ (((part First) (reference "Isaiah 35:1-6a,10"))
+ ((part Gospel) (reference "Matthew 11:2-11"))))
+ (of-advent-sunday-3-b
+ (((part First) (reference "Isaiah 61:1-2a,10-11"))
+ ((part Gospel) (reference "John 1:6-8,19-28"))))
+ (of-advent-sunday-3-c
+ (((part First) (reference "Zephaniah 3:14-18a"))
+ ((part Gospel) (reference "Luke 3:10-18"))))
+ (of-advent-sunday-4-a
+ (((part First) (reference "Isaiah 7:10-14"))
+ ((part Gospel) (reference "Matthew 1:18-24"))))
+ (of-advent-sunday-4-b
+ (((part First) (reference "2 Samuel 7:1-5,8b-12,14a,16"))
+ ((part Gospel) (reference "Luke 1:26-38"))))
+ (of-advent-sunday-4-c
+ (((part First) (reference "Micah 5:1-4a"))
+ ((part Gospel) (reference "Luke 1:39-45"))))
+ (of-ascension-a
+ (((part First) (reference "The Acts 1:1-11"))
+ ((part Gospel) (reference "Matthew 28:16-20"))))
+ (of-ascension-b
+ (((part First) (reference "The Acts 1:1-11"))
+ ((part Gospel) (reference "Mark 16:15-20"))))
+ (of-ascension-c
+ (((part First) (reference "The Acts 1:1-11"))
+ ((part Gospel) (reference "Luke 24:46-53"))))
+ (of-ash-wednesday
+ (((part First) (reference "Joel 2:12-18"))
+ ((part Gospel) (reference "Matthew 6:1-6,16-18"))))
+ (of-baptism-of-the-lord-a
+ (((part First) (reference "Isaiah 42:1-4,6-7"))
+ ((part Gospel) (reference "Matthew 3:13-17"))))
+ (of-baptism-of-the-lord-b
+ (((part First) (reference "Isaiah 55:1-11"))
+ ((part Gospel) (reference "Mark 1:7-11"))))
+ (of-baptism-of-the-lord-c
+ (((part First) (reference "Isaiah 40:1-5,9-11"))
+ ((part Gospel) (reference "Luke 3:15-16,21-22"))))
+ (of-christ-the-king-a
+ (((part First) (reference "Ezekiel 34:11-12,15-17"))
+ ((part Gospel) (reference "Matthew 25:31-46"))))
+ (of-christ-the-king-b
+ (((part First) (reference "Daniel 7:13-14"))
+ ((part Gospel) (reference "John 18:33b-37"))))
+ (of-christ-the-king-c
+ (((part First) (reference "2 Samuel 5:1-3"))
+ ((part Gospel) (reference "Luke 23:35-43"))))
+ (of-christmas-0-friday-ii
+ (((part First) (reference "1 John 2:18-21"))
+ ((part Gospel) (reference "John 1:1-5,9-14"))))
+ (of-christmas-0-monday-i
+ (((part First) (reference "1 John 2:18-21"))
+ ((part Gospel) (reference "John 1:1-5,9-14"))))
+ (of-christmas-0-monday-ii
+ (((part First) (reference "1 John 2:12-17"))
+ ((part Gospel) (reference "Luke 2:36-40"))))
+ (of-christmas-0-saturday-i
+ (((part First) (reference "1 John 2:3-11"))
+ ((part Gospel) (reference "Luke 2:22-35"))))
+ (of-christmas-0-saturday-ii
+ (((part First) (reference "1 John 2:12-17"))
+ ((part Gospel) (reference "Luke 2:36-40"))))
+ (of-christmas-0-thursday-i
+ (((part First) (reference "1 John 2:18-21"))
+ ((part Gospel) (reference "John 1:1-5,9-14"))))
+ (of-christmas-0-thursday-ii
+ (((part First) (reference "1 John 2:12-17"))
+ ((part Gospel) (reference "Luke 2:36-40"))))
+ (of-christmas-0-tuesday-i
+ (((part First) (reference "1 John 2:3-11"))
+ ((part Gospel) (reference "Luke 2:22-35"))))
+ (of-christmas-0-tuesday-ii
+ (((part First) (reference "1 John 2:18-21"))
+ ((part Gospel) (reference "John 1:1-5,9-14"))))
+ (of-christmas-0-wednesday-i
+ (((part First) (reference "1 John 2:12-17"))
+ ((part Gospel) (reference "Luke 2:36-40"))))
+ (of-christmas-0-wednesday-ii
+ (((part First) (reference "1 John 2:3-11"))
+ ((part Gospel) (reference "Luke 2:22-35"))))
+ (of-christmas-1-friday-i
+ (((part First) (reference "1 John 3:7-10"))
+ ((part Gospel) (reference "John 1:35-42"))))
+ (of-christmas-1-friday-ii
+ (((part First) (reference "1 John 3:11-21"))
+ ((part Gospel) (reference "John 1:43-51"))))
+ (of-christmas-1-monday-i
+ (((part First) (reference "1 John 3:22-4:6"))
+ ((part Gospel) (reference "Mat 4:12-17,23-25"))))
+ (of-christmas-1-monday-ii
+ (((part First) (reference "1 John 2:29-3:6"))
+ ((part Gospel) (reference "John 1:29-34"))))
+ (of-christmas-1-saturday-i
+ (((part First) (reference "1 John 3:11-21"))
+ ((part Gospel) (reference "John 1:43-51"))))
+ (of-christmas-1-saturday-ii
+ (((part First) (reference "1 John 3:7-10"))
+ ((part Gospel) (reference "John 1:35-42"))))
+ (of-christmas-1-thursday-i
+ (((part First) (reference "1 John 2:29-3:6"))
+ ((part Gospel) (reference "John 1:29-34"))))
+ (of-christmas-1-thursday-ii
+ (((part First) (reference "1 John 3:7-10"))
+ ((part Gospel) (reference "John 1:35-42"))))
+ (of-christmas-1-tuesday-i
+ (((part First) (reference "1 John 4:7-10"))
+ ((part Gospel) (reference "Mark 6:34-44"))))
+ (of-christmas-1-tuesday-ii
+ (((part First) (reference "1 John 3:22-4:6"))
+ ((part Gospel) (reference "Mat 4:12-17,23-25"))))
+ (of-christmas-1-wednesday-i
+ (((part First) (reference "1 John 4:11-18"))
+ ((part Gospel) (reference "Mark 6:45-52"))))
+ (of-christmas-1-wednesday-ii
+ (((part First) (reference "1 John 2:29-3:6"))
+ ((part Gospel) (reference "John 1:29-34"))))
+ (of-christmas-2-friday
+ (((part First) (reference "1 John 5:5-13"))
+ ((part Gospel) (reference "Luke 5:12-16"))))
+ (of-christmas-2-monday
+ (((part First) (reference "1 John 3:22-4:6"))
+ ((part Gospel) (reference "Matthew 4:12-17,23-25"))))
+ (of-christmas-2-saturday
+ (((part First) (reference "1 John 5:14-21"))
+ ((part Gospel) (reference "John 3:22-30"))))
+ (of-christmas-2-thursday
+ (((part First) (reference "1 John 4:19-5:4"))
+ ((part Gospel) (reference "Luke 4:14-22a"))))
+ (of-christmas-2-tuesday
+ (((part First) (reference "1 John 4:7-10"))
+ ((part Gospel) (reference "Mark 6:34-44"))))
+ (of-christmas-2-wednesday
+ (((part First) (reference "1 John 4:11-18"))
+ ((part Gospel) (reference "Mark 6:45-52"))))
+ (of-christmas-sunday-2
+ (((part First) (reference "Sirach 24:1-4,12-16"))
+ ((part Gospel) (reference "John 1:1-18"))))
+ (of-corpus-christi-a
+ (((part First) (reference "Deuteronomy 8:2-3,14b-16a"))
+ ((part Gospel) (reference "John 6:51-58"))))
+ (of-corpus-christi-b
+ (((part First) (reference "Exodus 24:3-8"))
+ ((part Gospel) (reference "Mark 14:12-16,22-26"))))
+ (of-corpus-christi-c
+ (((part First) (reference "Genesis 14:18-20"))
+ ((part Gospel) (reference "Luke 9:11b-17"))))
+ (of-easter-2-friday
+ (((part First) (reference "The Acts 5:34-42"))
+ ((part Gospel) (reference "John 6:1-15"))))
+ (of-easter-2-monday
+ (((part First) (reference "The Acts 4:23-31"))
+ ((part Gospel) (reference "John 3:1-8"))))
+ (of-easter-2-saturday
+ (((part First) (reference "The Acts 6:1-7"))
+ ((part Gospel) (reference "John 6:16-21"))))
+ (of-easter-2-thursday
+ (((part First) (reference "The Acts 5:27-33"))
+ ((part Gospel) (reference "John 3:31-36"))))
+ (of-easter-2-tuesday
+ (((part First) (reference "The Acts 4:32-37"))
+ ((part Gospel) (reference "John 3:7b-15"))))
+ (of-easter-2-wednesday
+ (((part First) (reference "The Acts 5:17-26"))
+ ((part Gospel) (reference "John 3:16-21"))))
+ (of-easter-3-friday
+ (((part First) (reference "The Acts 9:1-20"))
+ ((part Gospel) (reference "John 6:52-59"))))
+ (of-easter-3-monday
+ (((part First) (reference "The Acts 6:8-15"))
+ ((part Gospel) (reference "John 6:22-29"))))
+ (of-easter-3-saturday
+ (((part First) (reference "The Acts 9:31-42"))
+ ((part Gospel) (reference "John 6:60-69"))))
+ (of-easter-3-thursday
+ (((part First) (reference "The Acts 8:26-40"))
+ ((part Gospel) (reference "John 6:44-51"))))
+ (of-easter-3-tuesday
+ (((part First) (reference "The Acts 7:51-8:1a"))
+ ((part Gospel) (reference "John 6:30-35"))))
+ (of-easter-3-wednesday
+ (((part First) (reference "The Acts 8:1b-8"))
+ ((part Gospel) (reference "John 6:35-40"))))
+ (of-easter-4-friday
+ (((part First) (reference "The Acts 13:26-33"))
+ ((part Gospel) (reference "John 14:1-6"))))
+ (of-easter-4-monday
+ (((part First) (reference "The Acts 11:1-18"))
+ ((part Gospel) (reference "John 10:1-10"))))
+ (of-easter-4-saturday
+ (((part First) (reference "The Acts 13:44-52"))
+ ((part Gospel) (reference "John 14:7-14"))))
+ (of-easter-4-thursday
+ (((part First) (reference "The Acts 13:13-25"))
+ ((part Gospel) (reference "John 13:16-20"))))
+ (of-easter-4-tuesday
+ (((part First) (reference "The Acts 11:19-26"))
+ ((part Gospel) (reference "John 10:22-30"))))
+ (of-easter-4-wednesday
+ (((part First) (reference "The Acts 12:24-13:5a"))
+ ((part Gospel) (reference "John 12:44-50"))))
+ (of-easter-5-friday
+ (((part First) (reference "The Acts 15:22-31"))
+ ((part Gospel) (reference "John 15:12-17"))))
+ (of-easter-5-monday
+ (((part First) (reference "The Acts 14:5-18"))
+ ((part Gospel) (reference "John 14:21-26"))))
+ (of-easter-5-saturday
+ (((part First) (reference "The Acts 16:1-10"))
+ ((part Gospel) (reference "John 15:18-21"))))
+ (of-easter-5-thursday
+ (((part First) (reference "The Acts 15:7-21"))
+ ((part Gospel) (reference "John 15:9-11"))))
+ (of-easter-5-tuesday
+ (((part First) (reference "The Acts 14:19-28"))
+ ((part Gospel) (reference "John 14:27-31a"))))
+ (of-easter-5-wednesday
+ (((part First) (reference "The Acts 15:1-6"))
+ ((part Gospel) (reference "John 15:1-8"))))
+ (of-easter-6-friday
+ (((part First) (reference "The Acts 18:9-18"))
+ ((part Gospel) (reference "John 16:20-23"))))
+ (of-easter-6-monday
+ (((part First) (reference "The Acts 16:11-15"))
+ ((part Gospel) (reference "John 15:26-16:4a"))))
+ (of-easter-6-saturday
+ (((part First) (reference "The Acts 18:23-28"))
+ ((part Gospel) (reference "John 16:23b-28"))))
+ (of-easter-6-tuesday
+ (((part First) (reference "The Acts 16:22-34"))
+ ((part Gospel) (reference "John 16:5-11"))))
+ (of-easter-6-wednesday
+ (((part First) (reference "The Acts 17:15,22-18:1"))
+ ((part Gospel) (reference "John 16:12-15"))))
+ (of-easter-7-friday
+ (((part First) (reference "The Acts 25:13b-21"))
+ ((part Gospel) (reference "John 21:15-19"))))
+ (of-easter-7-monday
+ (((part First) (reference "The Acts 19:1-8"))
+ ((part Gospel) (reference "John 16:29-33"))))
+ (of-easter-7-saturday
+ (((part First) (reference "The Acts 28:16-20,30-31"))
+ ((part Gospel) (reference "John 21:20-25"))))
+ (of-easter-7-thursday
+ (((part First) (reference "The Acts 22:30;23:6-11"))
+ ((part Gospel) (reference "John 17:20-26"))))
+ (of-easter-7-tuesday
+ (((part First) (reference "The Acts 20:17-27"))
+ ((part Gospel) (reference "John 17:1-11a"))))
+ (of-easter-7-wednesday
+ (((part First) (reference "The Acts 20:28-38"))
+ ((part Gospel) (reference "John 17:11b-19"))))
+ (of-easter-octave-day-2
+ (((part First) (reference "Acts 2:14,22-32"))
+ ((part Gospel) (reference "Mat 28:8-15"))))
+ (of-easter-octave-day-3
+ (((part First) (reference "Acts 2:36-41"))
+ ((part Gospel) (reference "John 20:11-18"))))
+ (of-easter-octave-day-4
+ (((part First) (reference "Acts 3:1-10"))
+ ((part Gospel) (reference "Luke 24:13-35"))))
+ (of-easter-octave-day-5
+ (((part First) (reference "Acts 3:11-26"))
+ ((part Gospel) (reference "Luke 24:35-48"))))
+ (of-easter-octave-day-6
+ (((part First) (reference "Acts 4:1-12"))
+ ((part Gospel) (reference "John 21:1-14"))))
+ (of-easter-octave-day-7
+ (((part First) (reference "Acts 4:13-21"))
+ ((part Gospel) (reference "Mark 16:9-15"))))
+ (of-easter-sunday
+ (((part First) (reference "The Acts 10:34a,37-43"))
+ ((part Gospel) (reference "John 20:1-9"))))
+ (of-easter-sunday-2-a
+ (((part First) (reference "The Acts 2:42-47"))
+ ((part Gospel) (reference "John 20:19-31"))))
+ (of-easter-sunday-2-b
+ (((part First) (reference "The Acts 4:32-35"))
+ ((part Gospel) (reference "John 20:19-31"))))
+ (of-easter-sunday-2-c
+ (((part First) (reference "The Acts 5:12-16"))
+ ((part Gospel) (reference "John 20:19-31"))))
+ (of-easter-sunday-3-a
+ (((part First) (reference "The Acts 2:14,22-33"))
+ ((part Gospel) (reference "Luke 24:13-35"))))
+ (of-easter-sunday-3-b
+ (((part First) (reference "The Acts 3:13-15,17-19"))
+ ((part Gospel) (reference "Luke 24:35-48"))))
+ (of-easter-sunday-3-c
+ (((part First) (reference "The Acts 5:27-32,40b-41"))
+ ((part Gospel) (reference "John 21:1-19"))))
+ (of-easter-sunday-4-a
+ (((part First) (reference "The Acts 2:14a,36-41"))
+ ((part Gospel) (reference "John 10:1-10"))))
+ (of-easter-sunday-4-b
+ (((part First) (reference "The Acts 4:8-12"))
+ ((part Gospel) (reference "John 10:11-18"))))
+ (of-easter-sunday-4-c
+ (((part First) (reference "The Acts 13:14,43-52"))
+ ((part Gospel) (reference "John 10:27-30"))))
+ (of-easter-sunday-5-a
+ (((part First) (reference "The Acts 6:1-7"))
+ ((part Gospel) (reference "John 14:1-12"))))
+ (of-easter-sunday-5-b
+ (((part First) (reference "The Acts 9:26-31"))
+ ((part Gospel) (reference "John 15:1-8"))))
+ (of-easter-sunday-5-c
+ (((part First) (reference "The Acts 14:21-27"))
+ ((part Gospel) (reference "John 13:31-33a,34-35"))))
+ (of-easter-sunday-6-a
+ (((part First) (reference "The Acts 8:5-8,14-17"))
+ ((part Gospel) (reference "John 14:15-21"))))
+ (of-easter-sunday-6-b
+ (((part First) (reference "The Acts 10:25-26,34-35,44-48"))
+ ((part Gospel) (reference "John 15:9-17"))))
+ (of-easter-sunday-6-c
+ (((part First) (reference "The Acts 15:1-2,22-29"))
+ ((part Gospel) (reference "John 14:23-29"))))
+ (of-easter-sunday-7-a
+ (((part First) (reference "The Acts 1:12-14"))
+ ((part Gospel) (reference "John 17:1-11a"))))
+ (of-easter-sunday-7-b
+ (((part First) (reference "The Acts 1:15-17,20a,20c-26"))
+ ((part Gospel) (reference "John 17:11b-19"))))
+ (of-easter-sunday-7-c
+ (((part First) (reference "The Acts 7:55-60"))
+ ((part Gospel) (reference "John 17:20-26"))))
+ (of-epiphany
+ (((part First) (reference "Isaiah 60:1-6"))
+ ((part Gospel) (reference "Matthew 2:1-12"))))
+ (of-holy-family-a
+ (((part First) (reference "Sirach 3:3-7,14-17a"))
+ ((part Gospel) (reference "Matthew 2:13-15,19-23"))))
+ (of-holy-family-b
+ (((part First) (reference "Genesis 15:1-6;21:1-3"))
+ ((part Gospel) (reference "Luke 2:22-40"))))
+ (of-holy-family-c
+ (((part First) (reference "1 Samuel 1:20-22,24-28"))
+ ((part Gospel) (reference "Luke 2:41-52"))))
+ (of-lent-1-friday
+ (((part First) (reference "Ezekiel 18:21-28"))
+ ((part Gospel) (reference "Matthew 5:20-26"))))
+ (of-lent-1-monday
+ (((part First) (reference "Leviticus 19:1-2,11-18"))
+ ((part Gospel) (reference "Matthew 25:31-46"))))
+ (of-lent-1-saturday
+ (((part First) (reference "Deuteronomy 26:16-19"))
+ ((part Gospel) (reference "Matthew 5:43-48"))))
+ (of-lent-1-thursday
+ (((part First) (reference "Esther 14:1-13"))
+ ((part Gospel) (reference "Matthew 7:7-12"))))
+ (of-lent-1-tuesday
+ (((part First) (reference "Isaiah 55:10-11"))
+ ((part Gospel) (reference "Matthew 6:7-15"))))
+ (of-lent-1-wednesday
+ (((part First) (reference "Jonah 3:1-10"))
+ ((part Gospel) (reference "Luke 11:29-32"))))
+ (of-lent-2-friday
+ (((part First) (reference "Genesis 37:3-4,12-13a,17b-28a"))
+ ((part Gospel) (reference "Matthew 21:33-43,45-46"))))
+ (of-lent-2-monday
+ (((part First) (reference "Daniel 9:4b-10"))
+ ((part Gospel) (reference "Luke 6:36-38"))))
+ (of-lent-2-saturday
+ (((part First) (reference "Micah 7:14-15,18-20"))
+ ((part Gospel) (reference "Luke 15:1-3,11-32"))))
+ (of-lent-2-thursday
+ (((part First) (reference "Jeremiah 17:5-10"))
+ ((part Gospel) (reference "Luke 16:19-31"))))
+ (of-lent-2-tuesday
+ (((part First) (reference "Isaiah 1:10,16-20"))
+ ((part Gospel) (reference "Matthew 23:1-12"))))
+ (of-lent-2-wednesday
+ (((part First) (reference "Jeremiah 18:18-20"))
+ ((part Gospel) (reference "Matthew 20:17-28"))))
+ (of-lent-3-friday
+ (((part First) (reference "Hosea 14:2-10"))
+ ((part Gospel) (reference "Mark 12:28b-34"))))
+ (of-lent-3-monday
+ (((part First) (reference "2 Kings 5:1-15a"))
+ ((part Gospel) (reference "Luke 4:24-30"))))
+ (of-lent-3-saturday
+ (((part First) (reference "Hosea 6:1-6"))
+ ((part Gospel) (reference "Luke 18:9-14"))))
+ (of-lent-3-thursday
+ (((part First) (reference "Jeremiah 7:23-28"))
+ ((part Gospel) (reference "Luke 11:14-23"))))
+ (of-lent-3-tuesday
+ (((part First) (reference "Daniel 3:25,34-43"))
+ ((part Gospel) (reference "Matthew 18:21-35"))))
+ (of-lent-3-wednesday
+ (((part First) (reference "Deuteronomy 4:1,5-9"))
+ ((part Gospel) (reference "Matthew 5:17-19"))))
+ (of-lent-4-friday
+ (((part First) (reference "Wisdom 2:1a,12-22"))
+ ((part Gospel) (reference "John 7:1-2,10,25-30"))))
+ (of-lent-4-monday
+ (((part First) (reference "Isaiah 65:17-21"))
+ ((part Gospel) (reference "John 4:43-54"))))
+ (of-lent-4-saturday
+ (((part First) (reference "Jeremiah 11:18-20"))
+ ((part Gospel) (reference "John 7:40-53"))))
+ (of-lent-4-thursday
+ (((part First) (reference "Exodus 32:7-14"))
+ ((part Gospel) (reference "John 5:31-47"))))
+ (of-lent-4-tuesday
+ (((part First) (reference "Ezekiel 47:1-9,12"))
+ ((part Gospel) (reference "John 5:1-3a,5-16"))))
+ (of-lent-4-wednesday
+ (((part First) (reference "Isaiah 49:8-15"))
+ ((part Gospel) (reference "John 5:17-30"))))
+ (of-lent-5-friday
+ (((part First) (reference "Jeremiah 20:10-13"))
+ ((part Gospel) (reference "John 10:31-42"))))
+ (of-lent-5-monday
+ (((part First) (reference "Daniel 13:1-9,15-17,19-30,33-62"))
+ ((part Gospel) (reference "John 8:1-11"))))
+ (of-lent-5-saturday
+ (((part First) (reference "Ezekiel 37:21-28"))
+ ((part Gospel) (reference "John 11:45-56"))))
+ (of-lent-5-thursday
+ (((part First) (reference "Genesis 17:3-9"))
+ ((part Gospel) (reference "John 8:51-59"))))
+ (of-lent-5-tuesday
+ (((part First) (reference "Numbers 21:4-9"))
+ ((part Gospel) (reference "John 8:21-30"))))
+ (of-lent-5-wednesday
+ (((part First) (reference "Daniel 3:14-20,91-92,95"))
+ ((part Gospel) (reference "John 8:31-42"))))
+ (of-lent-6-friday
+ (((part First) (reference "Isaiah 52:13-53:12"))
+ ((part Gospel) (reference "John 18:1-19:42"))))
+ (of-lent-6-monday
+ (((part First) (reference "Isaiah 42:1-7"))
+ ((part Gospel) (reference "John 12:1-11"))))
+ (of-lent-6-saturday
+ (((part First) (reference "Genesis 1:1-2:2"))
+ ((part Gospel) (reference "Mat 28:1-10"))))
+ (of-lent-6-thursday
+ (((part First) (reference "Isaiah 61:1-3,6,8-9"))
+ ((part Gospel) (reference "Luke 4:16-21"))))
+ (of-lent-6-tuesday
+ (((part First) (reference "Isaiah 49:1-6"))
+ ((part Gospel) (reference "John 13:21-33,36-38"))))
+ (of-lent-6-wednesday
+ (((part First) (reference "Isaiah 50:4-9"))
+ ((part Gospel) (reference "Mat 26:14-25"))))
+ (of-lent-after-ashes-friday
+ (((part First) (reference "Isaiah 58:1-9a"))
+ ((part Gospel) (reference "Matthew 9:14-15"))))
+ (of-lent-after-ashes-saturday
+ (((part First) (reference "Isaiah 58:9b-14"))
+ ((part Gospel) (reference "Luke 5:27-32"))))
+ (of-lent-after-ashes-thursday
+ (((part First) (reference "Deuteronomy 30:15-20"))
+ ((part Gospel) (reference "Luke 9:22-25"))))
+ (of-lent-sunday-1-a
+ (((part First) (reference "Genesis 2:7-9;3:1-7"))
+ ((part Gospel) (reference "Matthew 4:1-11"))))
+ (of-lent-sunday-1-b
+ (((part First) (reference "Genesis 9:8-15"))
+ ((part Gospel) (reference "Mark 1:12-15"))))
+ (of-lent-sunday-1-c
+ (((part First) (reference "Deuteronomy 26:4-10"))
+ ((part Gospel) (reference "Luke 4:1-13"))))
+ (of-lent-sunday-2-a
+ (((part First) (reference "Genesis 12:1-4a"))
+ ((part Gospel) (reference "Matthew 17:1-9"))))
+ (of-lent-sunday-2-b
+ (((part First) (reference "Genesis 22:1-2,9a,10-13,15-18"))
+ ((part Gospel) (reference "Mark 9:2-10"))))
+ (of-lent-sunday-2-c
+ (((part First) (reference "Genesis 15:5-12,17-18"))
+ ((part Gospel) (reference "Luke 9:28b-36"))))
+ (of-lent-sunday-3-a
+ (((part First) (reference "Exodus 17:3-7"))
+ ((part Gospel) (reference "John 4:5-42"))))
+ (of-lent-sunday-3-b
+ (((part First) (reference "Exodus 20:1-17"))
+ ((part Gospel) (reference "John 2:13-25"))))
+ (of-lent-sunday-3-c
+ (((part First) (reference "Exodus 3:1-8a,13-15"))
+ ((part Gospel) (reference "Luke 13:1-9"))))
+ (of-lent-sunday-4-a
+ (((part First) (reference "1 Samuel 16:1b,6-7,10-13a"))
+ ((part Gospel) (reference "John 9:1-41"))))
+ (of-lent-sunday-4-b
+ (((part First) (reference "2 Chronicles 36:14-16,19-23"))
+ ((part Gospel) (reference "John 3:14-21"))))
+ (of-lent-sunday-4-c
+ (((part First) (reference "Joshua 5:9a,10-12"))
+ ((part Gospel) (reference "Luke 15:1-3,11-32"))))
+ (of-lent-sunday-5-a
+ (((part First) (reference "Ezekiel 37:12-14"))
+ ((part Gospel) (reference "John 11:1-45"))))
+ (of-lent-sunday-5-b
+ (((part First) (reference "Jeremiah 31:31-34"))
+ ((part Gospel) (reference "John 12:20-33"))))
+ (of-lent-sunday-5-c
+ (((part First) (reference "Isaiah 43:16-21"))
+ ((part Gospel) (reference "John 8:1-11"))))
+ (of-mary-mother-of-god
+ (((part First) (reference "Numbers 6:22-27"))
+ ((part Gospel) (reference "Luke 2:16-21"))))
+ (of-nativity-vigil
+ (((part First) (reference "Isaiah 62:1-5"))
+ ((part Gospel) (reference "Mat 1:18-25"))))
+ (of-ordinary-time-1-friday-i
+ (((part First) (reference "Hebrews 4:1-5,11"))
+ ((part Gospel) (reference "Mark 2:1-12"))))
+ (of-ordinary-time-1-friday-ii
+ (((part First) (reference "1 Samuel 8:4-7,10-22a"))
+ ((part Gospel) (reference "Mark 2:1-12"))))
+ (of-ordinary-time-1-monday-i
+ (((part First) (reference "Hebrews 1:1-6"))
+ ((part Gospel) (reference "Mark 1:14-20"))))
+ (of-ordinary-time-1-monday-ii
+ (((part First) (reference "1 Samuel 1:1-8"))
+ ((part Gospel) (reference "Mark 1:14-22"))))
+ (of-ordinary-time-1-saturday-i
+ (((part First) (reference "Hebrews 4:12-16"))
+ ((part Gospel) (reference "Mark 2:13-17"))))
+ (of-ordinary-time-1-saturday-ii
+ (((part First) (reference "1 Samuel 9:1-4,17-19;10:1"))
+ ((part Gospel) (reference "Mark 2:13-17"))))
+ (of-ordinary-time-1-thursday-i
+ (((part First) (reference "Hebrews 3:7-14"))
+ ((part Gospel) (reference "Mark 1:40-45"))))
+ (of-ordinary-time-1-thursday-ii
+ (((part First) (reference "1 Samuel 4:1-11"))
+ ((part Gospel) (reference "Mark 1:40-45"))))
+ (of-ordinary-time-1-tuesday-i
+ (((part First) (reference "Hebrews 2:5-12"))
+ ((part Gospel) (reference "Mark 1:21-28"))))
+ (of-ordinary-time-1-tuesday-ii
+ (((part First) (reference "1 Samuel 1:9-22"))
+ ((part Gospel) (reference "Mark 1:21-28"))))
+ (of-ordinary-time-1-wednesday-i
+ (((part First) (reference "Hebrews 2:14-18"))
+ ((part Gospel) (reference "Mark 1:29-39"))))
+ (of-ordinary-time-1-wednesday-ii
+ (((part First) (reference "1 Samuel 3:1-10,19-22"))
+ ((part Gospel) (reference "Mark 1:29-39"))))
+ (of-ordinary-time-10-friday-i
+ (((part First) (reference "2 Corinthians 4:7-15"))
+ ((part Gospel) (reference "Matthew 5:27-32"))))
+ (of-ordinary-time-10-friday-ii
+ (((part First) (reference "1 Kings 19:9a,11-16"))
+ ((part Gospel) (reference "Matthew 5:27-32"))))
+ (of-ordinary-time-10-monday-i
+ (((part First) (reference "2 Corinthians 1:1-7"))
+ ((part Gospel) (reference "Matthew 5:1-12"))))
+ (of-ordinary-time-10-monday-ii
+ (((part First) (reference "1 Kings 17:1-6"))
+ ((part Gospel) (reference "Matthew 5:1-12"))))
+ (of-ordinary-time-10-saturday-i
+ (((part First) (reference "2 Corinthians 5:14-21"))
+ ((part Gospel) (reference "Matthew 5:33-37"))))
+ (of-ordinary-time-10-saturday-ii
+ (((part First) (reference "1 Kings 19:19-21"))
+ ((part Gospel) (reference "Matthew 5:33-37"))))
+ (of-ordinary-time-10-thursday-i
+ (((part First) (reference "2 Corinthians 3:15-4:1,3-6"))
+ ((part Gospel) (reference "Matthew 5:20-26"))))
+ (of-ordinary-time-10-thursday-ii
+ (((part First) (reference "1 Kings 18:41-46"))
+ ((part Gospel) (reference "Matthew 5:20-26"))))
+ (of-ordinary-time-10-tuesday-i
+ (((part First) (reference "2 Corinthians 1:18-22"))
+ ((part Gospel) (reference "Matthew 5:13-16"))))
+ (of-ordinary-time-10-tuesday-ii
+ (((part First) (reference "1 Kings 17:7-16"))
+ ((part Gospel) (reference "Matthew 5:13-16"))))
+ (of-ordinary-time-10-wednesday-i
+ (((part First) (reference "2 Corinthians 3:4-11"))
+ ((part Gospel) (reference "Matthew 5:17-19"))))
+ (of-ordinary-time-10-wednesday-ii
+ (((part First) (reference "1 Kings 18:20-39"))
+ ((part Gospel) (reference "Matthew 5:17-19"))))
+ (of-ordinary-time-11-friday-i
+ (((part First) (reference "2 Corinthians 11:18,21-30"))
+ ((part Gospel) (reference "Matthew 6:19-23"))))
+ (of-ordinary-time-11-friday-ii
+ (((part First) (reference "2 Kings 11:1-4,9-18,20"))
+ ((part Gospel) (reference "Matthew 6:19-23"))))
+ (of-ordinary-time-11-monday-i
+ (((part First) (reference "2 Corinthians 6:1-10"))
+ ((part Gospel) (reference "Matthew 5:38-42"))))
+ (of-ordinary-time-11-monday-ii
+ (((part First) (reference "1 Kings 21:1-16"))
+ ((part Gospel) (reference "Matthew 5:38-42"))))
+ (of-ordinary-time-11-saturday-i
+ (((part First) (reference "2 Corinthians 12:1-10"))
+ ((part Gospel) (reference "Matthew 6:24-34"))))
+ (of-ordinary-time-11-saturday-ii
+ (((part First) (reference "2 Chronicles 24:17-25"))
+ ((part Gospel) (reference "Matthew 6:24-34"))))
+ (of-ordinary-time-11-thursday-i
+ (((part First) (reference "2 Corinthians 11:1-11"))
+ ((part Gospel) (reference "Matthew 6:7-15"))))
+ (of-ordinary-time-11-thursday-ii
+ (((part First) (reference "Sirach 48:1-14"))
+ ((part Gospel) (reference "Matthew 6:7-15"))))
+ (of-ordinary-time-11-tuesday-i
+ (((part First) (reference "2 Corinthians 8:1-9"))
+ ((part Gospel) (reference "Matthew 5:43-48"))))
+ (of-ordinary-time-11-tuesday-ii
+ (((part First) (reference "1 Kings 21:17-29"))
+ ((part Gospel) (reference "Matthew 5:43-48"))))
+ (of-ordinary-time-11-wednesday-i
+ (((part First) (reference "2 Corinthians 9:6-11"))
+ ((part Gospel) (reference "Matthew 6:1-6,16-18"))))
+ (of-ordinary-time-11-wednesday-ii
+ (((part First) (reference "2 Kings 2:1,6-14"))
+ ((part Gospel) (reference "Matthew 6:1-6,16-18"))))
+ (of-ordinary-time-12-friday-i
+ (((part First) (reference "Genesis 17:1,9-10,15-22"))
+ ((part Gospel) (reference "Matthew 8:1-4"))))
+ (of-ordinary-time-12-friday-ii
+ (((part First) (reference "2 Kings 25:1-12"))
+ ((part Gospel) (reference "Matthew 8:1-4"))))
+ (of-ordinary-time-12-monday-i
+ (((part First) (reference "Genesis 12:1-9"))
+ ((part Gospel) (reference "Matthew 7:1-5"))))
+ (of-ordinary-time-12-monday-ii
+ (((part First) (reference "2 Kings 17:5-8,13-15a,18"))
+ ((part Gospel) (reference "Matthew 7:1-5"))))
+ (of-ordinary-time-12-saturday-i
+ (((part First) (reference "Genesis 18:1-15"))
+ ((part Gospel) (reference "Matthew 8:5-17"))))
+ (of-ordinary-time-12-saturday-ii
+ (((part First) (reference "Lamentations 2:2,10-14,18-19"))
+ ((part Gospel) (reference "Matthew 8:5-17"))))
+ (of-ordinary-time-12-thursday-i
+ (((part First) (reference "Genesis 16:1-12,15-16"))
+ ((part Gospel) (reference "Matthew 7:21-29"))))
+ (of-ordinary-time-12-thursday-ii
+ (((part First) (reference "2 Kings 24:8-17"))
+ ((part Gospel) (reference "Matthew 7:21-29"))))
+ (of-ordinary-time-12-tuesday-i
+ (((part First) (reference "Genesis 13:2,5-18"))
+ ((part Gospel) (reference "Matthew 7:6,12-14"))))
+ (of-ordinary-time-12-tuesday-ii
+ (((part First) (reference "2 Kings 19:9b-11,14-21,31-35a,36"))
+ ((part Gospel) (reference "Matthew 7:6,12-14"))))
+ (of-ordinary-time-12-wednesday-i
+ (((part First) (reference "Genesis 15:1-12,17-18"))
+ ((part Gospel) (reference "Matthew 7:15-20"))))
+ (of-ordinary-time-12-wednesday-ii
+ (((part First) (reference "2 Kings 22:8-13;23:1-3"))
+ ((part Gospel) (reference "Matthew 7:15-22"))))
+ (of-ordinary-time-13-friday-i
+ (((part First) (reference "Genesis 23:1-4,19;24:1-8,62-67"))
+ ((part Gospel) (reference "Matthew 9:9-13"))))
+ (of-ordinary-time-13-friday-ii
+ (((part First) (reference "Amos 8:4-6,9-12"))
+ ((part Gospel) (reference "Matthew 9:9-13"))))
+ (of-ordinary-time-13-monday-i
+ (((part First) (reference "Genesis 18:16-33"))
+ ((part Gospel) (reference "Matthew 8:18-22"))))
+ (of-ordinary-time-13-monday-ii
+ (((part First) (reference "Amos 2:6-10,13-16"))
+ ((part Gospel) (reference "Matthew 8:18-22"))))
+ (of-ordinary-time-13-saturday-i
+ (((part First) (reference "Genesis 27:1-5,15-29"))
+ ((part Gospel) (reference "Matthew 9:14-17"))))
+ (of-ordinary-time-13-saturday-ii
+ (((part First) (reference "Amos 9:11-15"))
+ ((part Gospel) (reference "Matthew 9:14-17"))))
+ (of-ordinary-time-13-thursday-i
+ (((part First) (reference "Genesis 22:1b-19"))
+ ((part Gospel) (reference "Matthew 9:1-8"))))
+ (of-ordinary-time-13-thursday-ii
+ (((part First) (reference "Amos 7:10-17"))
+ ((part Gospel) (reference "Matthew 9:1-8"))))
+ (of-ordinary-time-13-tuesday-i
+ (((part First) (reference "Genesis 19:15-29"))
+ ((part Gospel) (reference "Matthew 8:23-27"))))
+ (of-ordinary-time-13-tuesday-ii
+ (((part First) (reference "Amos 3:1-8;4:11-12"))
+ ((part Gospel) (reference "Matthew 8:23-27"))))
+ (of-ordinary-time-13-wednesday-i
+ (((part First) (reference "Genesis 21:5,8-20a"))
+ ((part Gospel) (reference "Matthew 8:28-34"))))
+ (of-ordinary-time-13-wednesday-ii
+ (((part First) (reference "Amos 5:14-15,21-24"))
+ ((part Gospel) (reference "Matthew 8:28-34"))))
+ (of-ordinary-time-14-friday-i
+ (((part First) (reference "Genesis 46:1-7,28-30"))
+ ((part Gospel) (reference "Matthew 10:16-23"))))
+ (of-ordinary-time-14-friday-ii
+ (((part First) (reference "Hosea 14:2-10"))
+ ((part Gospel) (reference "Matthew 10:16-23"))))
+ (of-ordinary-time-14-monday-i
+ (((part First) (reference "Genesis 28:10-22a"))
+ ((part Gospel) (reference "Matthew 9:18-26"))))
+ (of-ordinary-time-14-monday-ii
+ (((part First) (reference "Hosea 2:16,17c-18,21-22"))
+ ((part Gospel) (reference "Matthew 9:18-26"))))
+ (of-ordinary-time-14-saturday-i
+ (((part First) (reference "Genesis 49:29-32;50:15-26a"))
+ ((part Gospel) (reference "Matthew 10:24-33"))))
+ (of-ordinary-time-14-saturday-ii
+ (((part First) (reference "Isaiah 6:1-8"))
+ ((part Gospel) (reference "Matthew 10:24-33"))))
+ (of-ordinary-time-14-thursday-i
+ (((part First) (reference "Genesis 44:18-21,23b-29;45:1-5"))
+ ((part Gospel) (reference "Matthew 10:7-15"))))
+ (of-ordinary-time-14-thursday-ii
+ (((part First) (reference "Hosea 11:1-4,8e-9"))
+ ((part Gospel) (reference "Matthew 10:7-15"))))
+ (of-ordinary-time-14-tuesday-i
+ (((part First) (reference "Genesis 32:23-33"))
+ ((part Gospel) (reference "Matthew 9:32-38"))))
+ (of-ordinary-time-14-tuesday-ii
+ (((part First) (reference "Hosea 8:4-7,11-13"))
+ ((part Gospel) (reference "Matthew 9:32-38"))))
+ (of-ordinary-time-14-wednesday-i
+ (((part First) (reference "Genesis 41:55-57;42:5-7a,17-24a"))
+ ((part Gospel) (reference "Matthew 10:1-7"))))
+ (of-ordinary-time-14-wednesday-ii
+ (((part First) (reference "Hosea 10:1-3,7-8,12"))
+ ((part Gospel) (reference "Matthew 10:1-7"))))
+ (of-ordinary-time-15-friday-i
+ (((part First) (reference "Exodus 11:10-12:14"))
+ ((part Gospel) (reference "Matthew 12:1-8"))))
+ (of-ordinary-time-15-friday-ii
+ (((part First) (reference "Isaiah 38:1-6,21-22,7-8"))
+ ((part Gospel) (reference "Matthew 12:1-8"))))
+ (of-ordinary-time-15-monday-i
+ (((part First) (reference "Exodus 1:8-14,22"))
+ ((part Gospel) (reference "Matthew 10:34-11:1"))))
+ (of-ordinary-time-15-monday-ii
+ (((part First) (reference "Isaiah 1:10-17"))
+ ((part Gospel) (reference "Matthew 10:34-11:1"))))
+ (of-ordinary-time-15-saturday-i
+ (((part First) (reference "Exodus 12:37-42"))
+ ((part Gospel) (reference "Matthew 12:14-21"))))
+ (of-ordinary-time-15-saturday-ii
+ (((part First) (reference "Micah 2:1-5"))
+ ((part Gospel) (reference "Matthew 12:14-21"))))
+ (of-ordinary-time-15-thursday-i
+ (((part First) (reference "Exodus 3:13-20"))
+ ((part Gospel) (reference "Matthew 11:28-30"))))
+ (of-ordinary-time-15-thursday-ii
+ (((part First) (reference "Isaiah 26:7-9,12,16-19"))
+ ((part Gospel) (reference "Matthew 11:28-30"))))
+ (of-ordinary-time-15-tuesday-i
+ (((part First) (reference "Exodus 2:1-15a"))
+ ((part Gospel) (reference "Matthew 11:20-24"))))
+ (of-ordinary-time-15-tuesday-ii
+ (((part First) (reference "Isaiah 7:1-9"))
+ ((part Gospel) (reference "Matthew 11:20-24"))))
+ (of-ordinary-time-15-wednesday-i
+ (((part First) (reference "Exodus 3:1-6,9-12"))
+ ((part Gospel) (reference "Matthew 11:25-27"))))
+ (of-ordinary-time-15-wednesday-ii
+ (((part First) (reference "Isaiah 10:5-7,13b-16"))
+ ((part Gospel) (reference "Matthew 11:25-27"))))
+ (of-ordinary-time-16-friday-i
+ (((part First) (reference "Exodus 20:1-17"))
+ ((part Gospel) (reference "Matthew 13:18-23"))))
+ (of-ordinary-time-16-friday-ii
+ (((part First) (reference "Jeremiah 3:14-17"))
+ ((part Gospel) (reference "Matthew 13:18-23"))))
+ (of-ordinary-time-16-monday-i
+ (((part First) (reference "Exodus 14:5-18"))
+ ((part Gospel) (reference "Matthew 12:38-42"))))
+ (of-ordinary-time-16-monday-ii
+ (((part First) (reference "Micah 6:1-4,6-8"))
+ ((part Gospel) (reference "Matthew 12:38-42"))))
+ (of-ordinary-time-16-saturday-i
+ (((part First) (reference "Exodus 24:3-8"))
+ ((part Gospel) (reference "Matthew 13:24-30"))))
+ (of-ordinary-time-16-saturday-ii
+ (((part First) (reference "Jeremiah 7:1-11"))
+ ((part Gospel) (reference "Matthew 13:24-30"))))
+ (of-ordinary-time-16-thursday-i
+ (((part First) (reference "Exodus 19:1-2,9-11,16-20b"))
+ ((part Gospel) (reference "Matthew 13:10-17"))))
+ (of-ordinary-time-16-thursday-ii
+ (((part First) (reference "Jeremiah 2:1-3,7-8,12-13"))
+ ((part Gospel) (reference "Matthew 13:10-17"))))
+ (of-ordinary-time-16-tuesday-i
+ (((part First) (reference "Exodus 14:21-15:1"))
+ ((part Gospel) (reference "Matthew 12:46-50"))))
+ (of-ordinary-time-16-tuesday-ii
+ (((part First) (reference "Micah 7:14-15,18-22"))
+ ((part Gospel) (reference "Matthew 12:46-50"))))
+ (of-ordinary-time-16-wednesday-i
+ (((part First) (reference "Exodus 16:1-5,9-15"))
+ ((part Gospel) (reference "Matthew 13:1-9"))))
+ (of-ordinary-time-16-wednesday-ii
+ (((part First) (reference "Jeremiah 1:1,4-10"))
+ ((part Gospel) (reference "Matthew 13:1-9"))))
+ (of-ordinary-time-17-friday-i
+ (((part First) (reference "Leviticus 23:1,4-11,15-16,27,34b-37"))
+ ((part Gospel) (reference "Matthew 13:54-58"))))
+ (of-ordinary-time-17-friday-ii
+ (((part First) (reference "Jeremiah 26:1-9"))
+ ((part Gospel) (reference "Matthew 13:54-58"))))
+ (of-ordinary-time-17-monday-i
+ (((part First) (reference "Exodus 32:15-24,30-34"))
+ ((part Gospel) (reference "Matthew 13:31-35"))))
+ (of-ordinary-time-17-monday-ii
+ (((part First) (reference "Jeremiah 13:1-11"))
+ ((part Gospel) (reference "Matthew 13:31-35"))))
+ (of-ordinary-time-17-saturday-i
+ (((part First) (reference "Leviticus 25:1,8-17"))
+ ((part Gospel) (reference "Matthew 14:1-12"))))
+ (of-ordinary-time-17-saturday-ii
+ (((part First) (reference "Jeremiah 26:11-16,24"))
+ ((part Gospel) (reference "Matthew 14:1-12"))))
+ (of-ordinary-time-17-thursday-i
+ (((part First) (reference "Exodus 40:16-21,34-38"))
+ ((part Gospel) (reference "Matthew 13:47-53"))))
+ (of-ordinary-time-17-thursday-ii
+ (((part First) (reference "Jeremiah 18:1-6"))
+ ((part Gospel) (reference "Matthew 13:47-53"))))
+ (of-ordinary-time-17-tuesday-i
+ (((part First) (reference "Exodus 33:7-11;34:5b-9,28"))
+ ((part Gospel) (reference "Matthew 13:36-43"))))
+ (of-ordinary-time-17-tuesday-ii
+ (((part First) (reference "Jeremiah 14:17-22"))
+ ((part Gospel) (reference "Matthew 13:36-43"))))
+ (of-ordinary-time-17-wednesday-i
+ (((part First) (reference "Exodus 34:29-35"))
+ ((part Gospel) (reference "Matthew 13:44-46"))))
+ (of-ordinary-time-17-wednesday-ii
+ (((part First) (reference "Jeremiah 15:10,16-21"))
+ ((part Gospel) (reference "Matthew 13:44-46"))))
+ (of-ordinary-time-18-friday-i
+ (((part First) (reference "Deuteronomy 4:32-40"))
+ ((part Gospel) (reference "Matthew 16:24-28"))))
+ (of-ordinary-time-18-friday-ii
+ (((part First) (reference "Nahum 2:1,3;3:1-3,6-7"))
+ ((part Gospel) (reference "Matthew 16:24-28"))))
+ (of-ordinary-time-18-monday-i
+ (((part First) (reference "Numbers 11:4b-15"))
+ ((part Gospel) (reference "Matthew 14:13-21"))))
+ (of-ordinary-time-18-monday-ii
+ (((part First) (reference "Jeremiah 28:1-17"))
+ ((part Gospel) (reference "Matthew 14:13-21"))))
+ (of-ordinary-time-18-saturday-i
+ (((part First) (reference "Deuteronomy 6:4-13"))
+ ((part Gospel) (reference "Matthew 17:14-20"))))
+ (of-ordinary-time-18-saturday-ii
+ (((part First) (reference "Habakkuk 1:12-2:4"))
+ ((part Gospel) (reference "Matthew 17:14-22"))))
+ (of-ordinary-time-18-thursday-i
+ (((part First) (reference "Numbers 20:1-13"))
+ ((part Gospel) (reference "Matthew 16:13-23"))))
+ (of-ordinary-time-18-thursday-ii
+ (((part First) (reference "Jeremiah 31:31-34"))
+ ((part Gospel) (reference "Matthew 16:13-23"))))
+ (of-ordinary-time-18-tuesday-i
+ (((part First) (reference "Numbers 12:1-13"))
+ ((part Gospel) (reference "Matthew 14:22-36"))))
+ (of-ordinary-time-18-tuesday-ii
+ (((part First) (reference "Jeremiah 30:1-2,12-15,18-22"))
+ ((part Gospel) (reference "Matthew 14:22-36"))))
+ (of-ordinary-time-18-wednesday-i
+ (((part First) (reference "Numbers 13:1-2,25-14:1,26a-29a,34-35"))
+ ((part Gospel) (reference "Matthew 15:21-28"))))
+ (of-ordinary-time-18-wednesday-ii
+ (((part First) (reference "Jeremiah 31:1-7"))
+ ((part Gospel) (reference "Matthew 15:21-28"))))
+ (of-ordinary-time-19-friday-i
+ (((part First) (reference "Joshua 24:1-13"))
+ ((part Gospel) (reference "Matthew 19:3-12"))))
+ (of-ordinary-time-19-friday-ii
+ (((part First) (reference "Ezekiel 16:1-15,60,63"))
+ ((part Gospel) (reference "Matthew 19:3-12"))))
+ (of-ordinary-time-19-monday-i
+ (((part First) (reference "Deuteronomy 10:12-22"))
+ ((part Gospel) (reference "Matthew 17:22-27"))))
+ (of-ordinary-time-19-monday-ii
+ (((part First) (reference "Ezekiel 1:2-5,24-28c"))
+ ((part Gospel) (reference "Matthew 17:22-27"))))
+ (of-ordinary-time-19-saturday-i
+ (((part First) (reference "Joshua 24:14-29"))
+ ((part Gospel) (reference "Matthew 19:13-15"))))
+ (of-ordinary-time-19-saturday-ii
+ (((part First) (reference "Ezekiel 18:1-10,13b,30-32"))
+ ((part Gospel) (reference "Matthew 19:13-15"))))
+ (of-ordinary-time-19-thursday-i
+ (((part First) (reference "Joshua 3:7-10a,11,13-17"))
+ ((part Gospel) (reference "Matthew 18:21-19:1"))))
+ (of-ordinary-time-19-thursday-ii
+ (((part First) (reference "Ezekiel 12:1-12"))
+ ((part Gospel) (reference "Matthew 18:21-19:1"))))
+ (of-ordinary-time-19-tuesday-i
+ (((part First) (reference "Deuteronomy 31:1-8"))
+ ((part Gospel) (reference "Matthew 18:1-5,10,12-14"))))
+ (of-ordinary-time-19-tuesday-ii
+ (((part First) (reference "Ezekiel 2:8-3:4"))
+ ((part Gospel) (reference "Matthew 18:1-5,10,12-14"))))
+ (of-ordinary-time-19-wednesday-i
+ (((part First) (reference "Deuteronomy 34:1-12"))
+ ((part Gospel) (reference "Matthew 18:15-20"))))
+ (of-ordinary-time-19-wednesday-ii
+ (((part First) (reference "Ezekiel 9:1-7;10:18-22"))
+ ((part Gospel) (reference "Matthew 18:15-22"))))
+ (of-ordinary-time-2-friday-i
+ (((part First) (reference "Hebrews 8:6-13"))
+ ((part Gospel) (reference "Mark 3:13-19"))))
+ (of-ordinary-time-2-friday-ii
+ (((part First) (reference "1 Samuel 24:3-21"))
+ ((part Gospel) (reference "Mark 3:13-19"))))
+ (of-ordinary-time-2-monday-i
+ (((part First) (reference "Hebrews 5:1-10"))
+ ((part Gospel) (reference "Mark 2:18-22"))))
+ (of-ordinary-time-2-monday-ii
+ (((part First) (reference "1 Samuel 15:16-23"))
+ ((part Gospel) (reference "Mark 2:18-22"))))
+ (of-ordinary-time-2-saturday-i
+ (((part First) (reference "Hebrews 9:2-3,11-14"))
+ ((part Gospel) (reference "Mark 3:20-21"))))
+ (of-ordinary-time-2-saturday-ii
+ (((part First) (reference "2 Samuel 1:1-4,11-12,19,23-27"))
+ ((part Gospel) (reference "Mark 3:20-21"))))
+ (of-ordinary-time-2-thursday-i
+ (((part First) (reference "Hebrews 7:25-8:6"))
+ ((part Gospel) (reference "Mark 3:7-12"))))
+ (of-ordinary-time-2-thursday-ii
+ (((part First) (reference "1 Samuel 18:6-9;19:1-7"))
+ ((part Gospel) (reference "Mark 3:7-12"))))
+ (of-ordinary-time-2-tuesday-i
+ (((part First) (reference "Hebrews 6:10-20"))
+ ((part Gospel) (reference "Mark 2:23-28"))))
+ (of-ordinary-time-2-tuesday-ii
+ (((part First) (reference "1 Samuel 16:1-13"))
+ ((part Gospel) (reference "Mark 2:23-28"))))
+ (of-ordinary-time-2-wednesday-i
+ (((part First) (reference "Hebrews 7:1-3,15-17"))
+ ((part Gospel) (reference "Mark 3:1-6"))))
+ (of-ordinary-time-2-wednesday-ii
+ (((part First) (reference "1 Samuel 17:32-33,37,40-51"))
+ ((part Gospel) (reference "Mark 3:1-6"))))
+ (of-ordinary-time-20-friday-i
+ (((part First) (reference "Ruth 1:1,3-6,14b-16,22"))
+ ((part Gospel) (reference "Matthew 22:34-40"))))
+ (of-ordinary-time-20-friday-ii
+ (((part First) (reference "Ezekiel 37:1-14"))
+ ((part Gospel) (reference "Matthew 22:34-40"))))
+ (of-ordinary-time-20-monday-i
+ (((part First) (reference "Judges 2:11-19"))
+ ((part Gospel) (reference "Matthew 19:16-22"))))
+ (of-ordinary-time-20-monday-ii
+ (((part First) (reference "Ezekiel 24:15-23"))
+ ((part Gospel) (reference "Matthew 19:16-22"))))
+ (of-ordinary-time-20-saturday-i
+ (((part First) (reference "Ruth 2:1-3,8-11;4:13-17"))
+ ((part Gospel) (reference "Matthew 23:1-12"))))
+ (of-ordinary-time-20-saturday-ii
+ (((part First) (reference "Ezekiel 43:1-7ab"))
+ ((part Gospel) (reference "Matthew 23:1-12"))))
+ (of-ordinary-time-20-thursday-i
+ (((part First) (reference "Judges 11:29-39a"))
+ ((part Gospel) (reference "Matthew 22:1-14"))))
+ (of-ordinary-time-20-thursday-ii
+ (((part First) (reference "Ezekiel 36:23-28"))
+ ((part Gospel) (reference "Matthew 22:1-14"))))
+ (of-ordinary-time-20-tuesday-i
+ (((part First) (reference "Judges 6:11-24a"))
+ ((part Gospel) (reference "Matthew 19:23-30"))))
+ (of-ordinary-time-20-tuesday-ii
+ (((part First) (reference "Ezekiel 28:1-10"))
+ ((part Gospel) (reference "Matthew 19:23-30"))))
+ (of-ordinary-time-20-wednesday-i
+ (((part First) (reference "Judges 9:6-15"))
+ ((part Gospel) (reference "Matthew 20:1-16"))))
+ (of-ordinary-time-20-wednesday-ii
+ (((part First) (reference "Ezekiel 34:1-11"))
+ ((part Gospel) (reference "Matthew 20:1-16"))))
+ (of-ordinary-time-21-friday-i
+ (((part First) (reference "1 Thessalonians 4:1-8"))
+ ((part Gospel) (reference "Matthew 25:1-13"))))
+ (of-ordinary-time-21-friday-ii
+ (((part First) (reference "1 Corinthians 1:17-25"))
+ ((part Gospel) (reference "Matthew 25:1-13"))))
+ (of-ordinary-time-21-monday-i
+ (((part First) (reference "1 Thessalonians 1:1-5,8b-10"))
+ ((part Gospel) (reference "Matthew 23:13-22"))))
+ (of-ordinary-time-21-monday-ii
+ (((part First) (reference "2 Thessalonians 1:1-5,11-12"))
+ ((part Gospel) (reference "Matthew 23:13-22"))))
+ (of-ordinary-time-21-saturday-i
+ (((part First) (reference "1 Thessalonians 4:9-11"))
+ ((part Gospel) (reference "Matthew 25:14-30"))))
+ (of-ordinary-time-21-saturday-ii
+ (((part First) (reference "1 Corinthians 1:26-31"))
+ ((part Gospel) (reference "Matthew 25:14-30"))))
+ (of-ordinary-time-21-thursday-i
+ (((part First) (reference "1 Thessalonians 3:7-13"))
+ ((part Gospel) (reference "Matthew 24:42-51"))))
+ (of-ordinary-time-21-thursday-ii
+ (((part First) (reference "1 Corinthians 1:1-9"))
+ ((part Gospel) (reference "Matthew 24:42-51"))))
+ (of-ordinary-time-21-tuesday-i
+ (((part First) (reference "1 Thessalonians 2:1-8"))
+ ((part Gospel) (reference "Matthew 23:23-26"))))
+ (of-ordinary-time-21-tuesday-ii
+ (((part First) (reference "2 Thessalonians 2:1-3a,14-17"))
+ ((part Gospel) (reference "Matthew 23:23-26"))))
+ (of-ordinary-time-21-wednesday-i
+ (((part First) (reference "1 Thessalonians 2:9-13"))
+ ((part Gospel) (reference "Matthew 23:27-32"))))
+ (of-ordinary-time-21-wednesday-ii
+ (((part First) (reference "2 Thessalonians 3:6-10,16-18"))
+ ((part Gospel) (reference "Matthew 23:27-32"))))
+ (of-ordinary-time-22-friday-i
+ (((part First) (reference "Colossians 1:15-20"))
+ ((part Gospel) (reference "Luke 5:33-39"))))
+ (of-ordinary-time-22-friday-ii
+ (((part First) (reference "1 Corinthians 4:1-5"))
+ ((part Gospel) (reference "Luke 5:33-39"))))
+ (of-ordinary-time-22-monday-i
+ (((part First) (reference "1 Thessalonians 4:13-18"))
+ ((part Gospel) (reference "Luke 4:16-30"))))
+ (of-ordinary-time-22-monday-ii
+ (((part First) (reference "1 Corinthians 2:1-5"))
+ ((part Gospel) (reference "Luke 4:16-30"))))
+ (of-ordinary-time-22-saturday-i
+ (((part First) (reference "Colossians 1:21-23"))
+ ((part Gospel) (reference "Luke 6:1-5"))))
+ (of-ordinary-time-22-saturday-ii
+ (((part First) (reference "1 Corinthians 4:6b-15"))
+ ((part Gospel) (reference "Luke 6:1-5"))))
+ (of-ordinary-time-22-thursday-i
+ (((part First) (reference "Colossians 1:9-14"))
+ ((part Gospel) (reference "Luke 5:1-11"))))
+ (of-ordinary-time-22-thursday-ii
+ (((part First) (reference "1 Corinthians 3:18-23"))
+ ((part Gospel) (reference "Luke 5:1-11"))))
+ (of-ordinary-time-22-tuesday-i
+ (((part First) (reference "1 Thessalonians 5:1-6,9-11"))
+ ((part Gospel) (reference "Luke 4:31-37"))))
+ (of-ordinary-time-22-tuesday-ii
+ (((part First) (reference "1 Corinthians 2:10b-16"))
+ ((part Gospel) (reference "Luke 4:31-37"))))
+ (of-ordinary-time-22-wednesday-i
+ (((part First) (reference "Colossians 1:1-8"))
+ ((part Gospel) (reference "Luke 4:38-44"))))
+ (of-ordinary-time-22-wednesday-ii
+ (((part First) (reference "1 Corinthians 3:1-9"))
+ ((part Gospel) (reference "Luke 4:38-44"))))
+ (of-ordinary-time-23-friday-i
+ (((part First) (reference "1 Timothy 1:1-2,12-14"))
+ ((part Gospel) (reference "Luke 6:39-42"))))
+ (of-ordinary-time-23-friday-ii
+ (((part First) (reference "1 Corinthians 9:16-19,22b-27"))
+ ((part Gospel) (reference "Luke 6:39-42"))))
+ (of-ordinary-time-23-monday-i
+ (((part First) (reference "Colossians 1:24-2:3"))
+ ((part Gospel) (reference "Luke 6:6-11"))))
+ (of-ordinary-time-23-monday-ii
+ (((part First) (reference "1 Corinthians 5:1-8"))
+ ((part Gospel) (reference "Luke 6:6-11"))))
+ (of-ordinary-time-23-saturday-i
+ (((part First) (reference "1 Timothy 1:15-17"))
+ ((part Gospel) (reference "Luke 6:43-49"))))
+ (of-ordinary-time-23-saturday-ii
+ (((part First) (reference "1 Corinthians 10:14-22"))
+ ((part Gospel) (reference "Luke 6:43-49"))))
+ (of-ordinary-time-23-thursday-i
+ (((part First) (reference "Colossians 3:12-17"))
+ ((part Gospel) (reference "Luke 6:27-38"))))
+ (of-ordinary-time-23-thursday-ii
+ (((part First) (reference "1 Corinthians 8:1b-7,11-13"))
+ ((part Gospel) (reference "Luke 6:27-38"))))
+ (of-ordinary-time-23-tuesday-i
+ (((part First) (reference "Colossians 2:6-15"))
+ ((part Gospel) (reference "Luke 6:12-19"))))
+ (of-ordinary-time-23-tuesday-ii
+ (((part First) (reference "1 Corinthians 6:1-11"))
+ ((part Gospel) (reference "Luke 6:12-19"))))
+ (of-ordinary-time-23-wednesday-i
+ (((part First) (reference "Colossians 3:1-11"))
+ ((part Gospel) (reference "Luke 6:20-26"))))
+ (of-ordinary-time-23-wednesday-ii
+ (((part First) (reference "1 Corinthians 7:25-31"))
+ ((part Gospel) (reference "Luke 6:20-26"))))
+ (of-ordinary-time-24-friday-i
+ (((part First) (reference "1 Timothy 6:2c-12"))
+ ((part Gospel) (reference "Luke 8:1-3"))))
+ (of-ordinary-time-24-friday-ii
+ (((part First) (reference "1 Corinthians 15:12-22"))
+ ((part Gospel) (reference "Luke 8:1-3"))))
+ (of-ordinary-time-24-monday-i
+ (((part First) (reference "1 Timothy 2:1-8"))
+ ((part Gospel) (reference "Luke 7:1-10"))))
+ (of-ordinary-time-24-monday-ii
+ (((part First) (reference "1 Corinthians 11:17-26,33"))
+ ((part Gospel) (reference "Luke 7:1-10"))))
+ (of-ordinary-time-24-saturday-i
+ (((part First) (reference "1 Timothy 6:13-16"))
+ ((part Gospel) (reference "Luke 8:4-15"))))
+ (of-ordinary-time-24-saturday-ii
+ (((part First) (reference "1 Corinthians 15:35-37,42-49"))
+ ((part Gospel) (reference "Luke 8:4-15"))))
+ (of-ordinary-time-24-thursday-i
+ (((part First) (reference "1 Timothy 4:12-16"))
+ ((part Gospel) (reference "Luke 7:36-50"))))
+ (of-ordinary-time-24-thursday-ii
+ (((part First) (reference "1 Corinthians 15:1-11"))
+ ((part Gospel) (reference "Luke 7:36-50"))))
+ (of-ordinary-time-24-tuesday-i
+ (((part First) (reference "1 Timothy 3:1-13"))
+ ((part Gospel) (reference "Luke 7:11-17"))))
+ (of-ordinary-time-24-tuesday-ii
+ (((part First) (reference "1 Corinthians 12:12-14,27-31a"))
+ ((part Gospel) (reference "Luke 7:11-17"))))
+ (of-ordinary-time-24-wednesday-i
+ (((part First) (reference "1 Timothy 3:14-16"))
+ ((part Gospel) (reference "Luke 7:31-35"))))
+ (of-ordinary-time-24-wednesday-ii
+ (((part First) (reference "1 Corinthians 12:31-13:13"))
+ ((part Gospel) (reference "Luke 7:31-35"))))
+ (of-ordinary-time-25-friday-i
+ (((part First) (reference "Haggai 2:1-9"))
+ ((part Gospel) (reference "Luke 9:18-22"))))
+ (of-ordinary-time-25-friday-ii
+ (((part First) (reference "Ecclesiastes 3:1-11"))
+ ((part Gospel) (reference "Luke 9:18-22"))))
+ (of-ordinary-time-25-monday-i
+ (((part First) (reference "Ezra 1:1-6"))
+ ((part Gospel) (reference "Luke 8:16-18"))))
+ (of-ordinary-time-25-monday-ii
+ (((part First) (reference "Proverbs 3:27-34"))
+ ((part Gospel) (reference "Luke 8:16-18"))))
+ (of-ordinary-time-25-saturday-i
+ (((part First) (reference "Zechariah 2:1-5,10-11"))
+ ((part Gospel) (reference "Luke 9:43b-45"))))
+ (of-ordinary-time-25-saturday-ii
+ (((part First) (reference "Ecclesiastes 11:9-12:8"))
+ ((part Gospel) (reference "Luke 9:43b-45"))))
+ (of-ordinary-time-25-thursday-i
+ (((part First) (reference "Haggai 1:1-8"))
+ ((part Gospel) (reference "Luke 9:7-9"))))
+ (of-ordinary-time-25-thursday-ii
+ (((part First) (reference "Ecclesiastes 1:2-11"))
+ ((part Gospel) (reference "Luke 9:7-9"))))
+ (of-ordinary-time-25-tuesday-i
+ (((part First) (reference "Ezra 6:7-8,12b,14-20"))
+ ((part Gospel) (reference "Luke 8:19-21"))))
+ (of-ordinary-time-25-tuesday-ii
+ (((part First) (reference "Proverbs 21:1-6,10-13"))
+ ((part Gospel) (reference "Luke 8:19-21"))))
+ (of-ordinary-time-25-wednesday-i
+ (((part First) (reference "Ezra 9:5-9"))
+ ((part Gospel) (reference "Luke 9:1-6"))))
+ (of-ordinary-time-25-wednesday-ii
+ (((part First) (reference "Proverbs 30:5-9"))
+ ((part Gospel) (reference "Luke 9:1-6"))))
+ (of-ordinary-time-26-friday-i
+ (((part First) (reference "Baruch 1:15-22"))
+ ((part Gospel) (reference "Luke 10:13-16"))))
+ (of-ordinary-time-26-friday-ii
+ (((part First) (reference "Job 38:1,12-21;40:3-5"))
+ ((part Gospel) (reference "Luke 10:13-16"))))
+ (of-ordinary-time-26-monday-i
+ (((part First) (reference "Zechariah 8:1-8"))
+ ((part Gospel) (reference "Luke 9:46-50"))))
+ (of-ordinary-time-26-monday-ii
+ (((part First) (reference "Job 1:6-22"))
+ ((part Gospel) (reference "Luke 9:46-50"))))
+ (of-ordinary-time-26-saturday-i
+ (((part First) (reference "Baruch 4:5-12,27-29"))
+ ((part Gospel) (reference "Luke 10:17-24"))))
+ (of-ordinary-time-26-saturday-ii
+ (((part First) (reference "Job 42:1-3,5-6,12-17"))
+ ((part Gospel) (reference "Luke 10:17-24"))))
+ (of-ordinary-time-26-thursday-i
+ (((part First) (reference "Nehemiah 8:1-4a,5-6,7b-12"))
+ ((part Gospel) (reference "Luke 10:1-12"))))
+ (of-ordinary-time-26-thursday-ii
+ (((part First) (reference "Job 19:21-27"))
+ ((part Gospel) (reference "Luke 10:1-12"))))
+ (of-ordinary-time-26-tuesday-i
+ (((part First) (reference "Zechariah 8:20-23"))
+ ((part Gospel) (reference "Luke 9:51-56"))))
+ (of-ordinary-time-26-tuesday-ii
+ (((part First) (reference "Job 3:1-3,11-17,20-23"))
+ ((part Gospel) (reference "Luke 9:51-56"))))
+ (of-ordinary-time-26-wednesday-i
+ (((part First) (reference "Nehemiah 2:1-8"))
+ ((part Gospel) (reference "Luke 9:57-62"))))
+ (of-ordinary-time-26-wednesday-ii
+ (((part First) (reference "Job 9:1-12,14-16"))
+ ((part Gospel) (reference "Luke 9:57-62"))))
+ (of-ordinary-time-27-friday-i
+ (((part First) (reference "Joel 1:13-15;2:1-2"))
+ ((part Gospel) (reference "Luke 11:15-26"))))
+ (of-ordinary-time-27-friday-ii
+ (((part First) (reference "Galatians 3:7-14"))
+ ((part Gospel) (reference "Luke 11:15-26"))))
+ (of-ordinary-time-27-monday-i
+ (((part First) (reference "Jonah 1:1-2:2,11"))
+ ((part Gospel) (reference "Luke 10:25-37"))))
+ (of-ordinary-time-27-monday-ii
+ (((part First) (reference "Galatians 1:6-12"))
+ ((part Gospel) (reference "Luke 10:25-37"))))
+ (of-ordinary-time-27-saturday-i
+ (((part First) (reference "Joel 3:12-21"))
+ ((part Gospel) (reference "Luke 11:27-28"))))
+ (of-ordinary-time-27-saturday-ii
+ (((part First) (reference "Galatians 3:22-29"))
+ ((part Gospel) (reference "Luke 11:27-28"))))
+ (of-ordinary-time-27-thursday-i
+ (((part First) (reference "Malachi 3:13-18;4:1-2"))
+ ((part Gospel) (reference "Luke 11:5-13"))))
+ (of-ordinary-time-27-thursday-ii
+ (((part First) (reference "Galatians 3:1-5"))
+ ((part Gospel) (reference "Luke 11:5-13"))))
+ (of-ordinary-time-27-tuesday-i
+ (((part First) (reference "Jonah 3:1-10"))
+ ((part Gospel) (reference "Luke 10:38-42"))))
+ (of-ordinary-time-27-tuesday-ii
+ (((part First) (reference "Galatians 1:13-24"))
+ ((part Gospel) (reference "Luke 10:38-42"))))
+ (of-ordinary-time-27-wednesday-i
+ (((part First) (reference "Jonah 4:1-11"))
+ ((part Gospel) (reference "Luke 11:1-4"))))
+ (of-ordinary-time-27-wednesday-ii
+ (((part First) (reference "Galatians 2:1-2,7-14"))
+ ((part Gospel) (reference "Luke 11:1-4"))))
+ (of-ordinary-time-28-friday-i
+ (((part First) (reference "Romans 4:1-8"))
+ ((part Gospel) (reference "Luke 12:1-7"))))
+ (of-ordinary-time-28-friday-ii
+ (((part First) (reference "Ephesians 1:11-14"))
+ ((part Gospel) (reference "Luke 12:1-7"))))
+ (of-ordinary-time-28-monday-i
+ (((part First) (reference "Romans 1:1-7"))
+ ((part Gospel) (reference "Luke 11:29-32"))))
+ (of-ordinary-time-28-monday-ii
+ (((part First) (reference "Galatians 4:22-24,26-27,31-5:1"))
+ ((part Gospel) (reference "Luke 11:29-32"))))
+ (of-ordinary-time-28-saturday-i
+ (((part First) (reference "Romans 4:13,16-18"))
+ ((part Gospel) (reference "Luke 12:8-12"))))
+ (of-ordinary-time-28-saturday-ii
+ (((part First) (reference "Ephesians 1:15-23"))
+ ((part Gospel) (reference "Luke 12:8-12"))))
+ (of-ordinary-time-28-thursday-i
+ (((part First) (reference "Romans 3:21-30"))
+ ((part Gospel) (reference "Luke 11:47-54"))))
+ (of-ordinary-time-28-thursday-ii
+ (((part First) (reference "Ephesians 1:1-10"))
+ ((part Gospel) (reference "Luke 11:47-54"))))
+ (of-ordinary-time-28-tuesday-i
+ (((part First) (reference "Romans 1:16-25"))
+ ((part Gospel) (reference "Luke 11:37-41"))))
+ (of-ordinary-time-28-tuesday-ii
+ (((part First) (reference "Galatians 5:1-6"))
+ ((part Gospel) (reference "Luke 11:37-41"))))
+ (of-ordinary-time-28-wednesday-i
+ (((part First) (reference "Romans 2:1-11"))
+ ((part Gospel) (reference "Luke 11:42-46"))))
+ (of-ordinary-time-28-wednesday-ii
+ (((part First) (reference "Galatians 5:18-25"))
+ ((part Gospel) (reference "Luke 11:42-46"))))
+ (of-ordinary-time-29-friday-i
+ (((part First) (reference "Romans 7:18-25a"))
+ ((part Gospel) (reference "Luke 12:54-59"))))
+ (of-ordinary-time-29-friday-ii
+ (((part First) (reference "Ephesians 4:1-6"))
+ ((part Gospel) (reference "Luke 12:54-59"))))
+ (of-ordinary-time-29-monday-i
+ (((part First) (reference "Romans 4:20-25"))
+ ((part Gospel) (reference "Luke 12:13-21"))))
+ (of-ordinary-time-29-monday-ii
+ (((part First) (reference "Ephesians 2:1-10"))
+ ((part Gospel) (reference "Luke 12:13-21"))))
+ (of-ordinary-time-29-saturday-i
+ (((part First) (reference "Romans 8:1-11"))
+ ((part Gospel) (reference "Luke 13:1-9"))))
+ (of-ordinary-time-29-saturday-ii
+ (((part First) (reference "Ephesians 4:7-16"))
+ ((part Gospel) (reference "Luke 13:1-9"))))
+ (of-ordinary-time-29-thursday-i
+ (((part First) (reference "Romans 6:19-23"))
+ ((part Gospel) (reference "Luke 12:49-53"))))
+ (of-ordinary-time-29-thursday-ii
+ (((part First) (reference "Ephesians 3:14-21"))
+ ((part Gospel) (reference "Luke 12:49-53"))))
+ (of-ordinary-time-29-tuesday-i
+ (((part First) (reference "Romans 5:12,15b,17-19,20b-21"))
+ ((part Gospel) (reference "Luke 12:35-38"))))
+ (of-ordinary-time-29-tuesday-ii
+ (((part First) (reference "Ephesians 2:12-22"))
+ ((part Gospel) (reference "Luke 12:35-38"))))
+ (of-ordinary-time-29-wednesday-i
+ (((part First) (reference "Romans 6:12-18"))
+ ((part Gospel) (reference "Luke 12:39-48"))))
+ (of-ordinary-time-29-wednesday-ii
+ (((part First) (reference "Ephesians 3:2-12"))
+ ((part Gospel) (reference "Luke 12:39-48"))))
+ (of-ordinary-time-3-friday-i
+ (((part First) (reference "Hebrews 10:32-39"))
+ ((part Gospel) (reference "Mark 4:26-34"))))
+ (of-ordinary-time-3-friday-ii
+ (((part First) (reference "2 Samuel 11:1-4a,5-10a,13-17"))
+ ((part Gospel) (reference "Mark 4:26-34"))))
+ (of-ordinary-time-3-monday-i
+ (((part First) (reference "Hebrews 9:15,24-28"))
+ ((part Gospel) (reference "Mark 3:22-30"))))
+ (of-ordinary-time-3-monday-ii
+ (((part First) (reference "2 Samuel 5:1-7,10"))
+ ((part Gospel) (reference "Mark 3:22-30"))))
+ (of-ordinary-time-3-saturday-i
+ (((part First) (reference "Hebrews 11:1-2,8-19"))
+ ((part Gospel) (reference "Mark 4:35-41"))))
+ (of-ordinary-time-3-saturday-ii
+ (((part First) (reference "2 Samuel 12:1-7a,10-17"))
+ ((part Gospel) (reference "Mark 4:35-41"))))
+ (of-ordinary-time-3-thursday-i
+ (((part First) (reference "Hebrews 10:19-25"))
+ ((part Gospel) (reference "Mark 4:21-25"))))
+ (of-ordinary-time-3-thursday-ii
+ (((part First) (reference "2 Samuel 7:18-19,24-29"))
+ ((part Gospel) (reference "Mark 4:21-25"))))
+ (of-ordinary-time-3-tuesday-i
+ (((part First) (reference "Hebrews 10:1-10"))
+ ((part Gospel) (reference "Mark 3:31-35"))))
+ (of-ordinary-time-3-tuesday-ii
+ (((part First) (reference "2 Samuel 6:12b-15,17-19"))
+ ((part Gospel) (reference "Mark 3:31-35"))))
+ (of-ordinary-time-3-wednesday-i
+ (((part First) (reference "Hebrews 10:11-18"))
+ ((part Gospel) (reference "Mark 4:1-20"))))
+ (of-ordinary-time-3-wednesday-ii
+ (((part First) (reference "2 Samuel 7:4-17"))
+ ((part Gospel) (reference "Mark 4:1-22"))))
+ (of-ordinary-time-30-friday-i
+ (((part First) (reference "Romans 9:1-5"))
+ ((part Gospel) (reference "Luke 14:1-6"))))
+ (of-ordinary-time-30-friday-ii
+ (((part First) (reference "Philippians 1:1-11"))
+ ((part Gospel) (reference "Luke 14:1-6"))))
+ (of-ordinary-time-30-monday-i
+ (((part First) (reference "Romans 8:12-17"))
+ ((part Gospel) (reference "Luke 13:10-17"))))
+ (of-ordinary-time-30-monday-ii
+ (((part First) (reference "Ephesians 4:32-5:8"))
+ ((part Gospel) (reference "Luke 13:10-17"))))
+ (of-ordinary-time-30-saturday-i
+ (((part First) (reference "Romans 11:1-2a,11-12,25-29"))
+ ((part Gospel) (reference "Luke 14:1,7-11"))))
+ (of-ordinary-time-30-saturday-ii
+ (((part First) (reference "Philippians 1:18b-26"))
+ ((part Gospel) (reference "Luke 14:1,7-11"))))
+ (of-ordinary-time-30-thursday-i
+ (((part First) (reference "Romans 8:31b-39"))
+ ((part Gospel) (reference "Luke 13:31-35"))))
+ (of-ordinary-time-30-thursday-ii
+ (((part First) (reference "Ephesians 6:10-22"))
+ ((part Gospel) (reference "Luke 13:31-35"))))
+ (of-ordinary-time-30-tuesday-i
+ (((part First) (reference "Romans 8:18-25"))
+ ((part Gospel) (reference "Luke 13:18-21"))))
+ (of-ordinary-time-30-tuesday-ii
+ (((part First) (reference "Ephesians 5:21-33"))
+ ((part Gospel) (reference "Luke 13:18-21"))))
+ (of-ordinary-time-30-wednesday-i
+ (((part First) (reference "Romans 8:26-30"))
+ ((part Gospel) (reference "Luke 13:22-30"))))
+ (of-ordinary-time-30-wednesday-ii
+ (((part First) (reference "Ephesians 6:1-9"))
+ ((part Gospel) (reference "Luke 13:22-30"))))
+ (of-ordinary-time-31-friday-i
+ (((part First) (reference "Romans 15:14-21"))
+ ((part Gospel) (reference "Luke 16:1-8"))))
+ (of-ordinary-time-31-friday-ii
+ (((part First) (reference "Philippians 3:17-4:1"))
+ ((part Gospel) (reference "Luke 16:1-8"))))
+ (of-ordinary-time-31-monday-i
+ (((part First) (reference "Romans 11:29-36"))
+ ((part Gospel) (reference "Luke 14:12-14"))))
+ (of-ordinary-time-31-monday-ii
+ (((part First) (reference "Philippians 2:1-4"))
+ ((part Gospel) (reference "Luke 14:12-14"))))
+ (of-ordinary-time-31-saturday-i
+ (((part First) (reference "Romans 16:3-9,16,22-27"))
+ ((part Gospel) (reference "Luke 16:9-15"))))
+ (of-ordinary-time-31-saturday-ii
+ (((part First) (reference "Philippians 4:10-19"))
+ ((part Gospel) (reference "Luke 16:9-15"))))
+ (of-ordinary-time-31-thursday-i
+ (((part First) (reference "Romans 14:7-12"))
+ ((part Gospel) (reference "Luke 15:1-10"))))
+ (of-ordinary-time-31-thursday-ii
+ (((part First) (reference "Philippians 3:3-8a"))
+ ((part Gospel) (reference "Luke 15:1-10"))))
+ (of-ordinary-time-31-tuesday-i
+ (((part First) (reference "Romans 12:5-16ab"))
+ ((part Gospel) (reference "Luke 14:15-24"))))
+ (of-ordinary-time-31-tuesday-ii
+ (((part First) (reference "Philippians 2:5-11"))
+ ((part Gospel) (reference "Luke 14:15-24"))))
+ (of-ordinary-time-31-wednesday-i
+ (((part First) (reference "Romans 13:8-10"))
+ ((part Gospel) (reference "Luke 14:25-33"))))
+ (of-ordinary-time-31-wednesday-ii
+ (((part First) (reference "Philippians 2:12-18"))
+ ((part Gospel) (reference "Luke 14:25-33"))))
+ (of-ordinary-time-32-friday-i
+ (((part First) (reference "Wisdom 13:1-9"))
+ ((part Gospel) (reference "Luke 17:26-37"))))
+ (of-ordinary-time-32-friday-ii
+ (((part First) (reference "2 John 4-9"))
+ ((part Gospel) (reference "Luke 17:26-37"))))
+ (of-ordinary-time-32-monday-i
+ (((part First) (reference "Wisdom 1:1-7"))
+ ((part Gospel) (reference "Luke 17:1-6"))))
+ (of-ordinary-time-32-monday-ii
+ (((part First) (reference "Titus 1:1-9"))
+ ((part Gospel) (reference "Luke 17:1-6"))))
+ (of-ordinary-time-32-saturday-i
+ (((part First) (reference "Wisdom 18:14-16;19:6-9"))
+ ((part Gospel) (reference "Luke 18:1-8"))))
+ (of-ordinary-time-32-saturday-ii
+ (((part First) (reference "3 John 5-8"))
+ ((part Gospel) (reference "Luke 18:1-8"))))
+ (of-ordinary-time-32-thursday-i
+ (((part First) (reference "Wisdom 7:22b-8:1"))
+ ((part Gospel) (reference "Luke 17:20-25"))))
+ (of-ordinary-time-32-thursday-ii
+ (((part First) (reference "Philemon 7-22"))
+ ((part Gospel) (reference "Luke 17:20-25"))))
+ (of-ordinary-time-32-tuesday-i
+ (((part First) (reference "Wisdom 2:23-3:9"))
+ ((part Gospel) (reference "Luke 17:7-10"))))
+ (of-ordinary-time-32-tuesday-ii
+ (((part First) (reference "Titus 2:1-8,11-14"))
+ ((part Gospel) (reference "Luke 17:7-10"))))
+ (of-ordinary-time-32-wednesday-i
+ (((part First) (reference "Wisdom 6:1-11"))
+ ((part Gospel) (reference "Luke 17:11-19"))))
+ (of-ordinary-time-32-wednesday-ii
+ (((part First) (reference "Titus 3:1-7"))
+ ((part Gospel) (reference "Luke 17:11-19"))))
+ (of-ordinary-time-33-friday-i
+ (((part First) (reference "1 Maccabees 4:36-37,52-59"))
+ ((part Gospel) (reference "Luke 19:45-48"))))
+ (of-ordinary-time-33-friday-ii
+ (((part First) (reference "Revelation 10:8-11"))
+ ((part Gospel) (reference "Luke 19:45-48"))))
+ (of-ordinary-time-33-monday-i
+ (((part First) (reference "1 Maccabees 1:10-15,41-43,54-57,62-63"))
+ ((part Gospel) (reference "Luke 18:35-43"))))
+ (of-ordinary-time-33-monday-ii
+ (((part First) (reference "Revelation 1:1-4;2:1-5"))
+ ((part Gospel) (reference "Luke 18:35-43"))))
+ (of-ordinary-time-33-saturday-i
+ (((part First) (reference "1 Maccabees 6:1-13"))
+ ((part Gospel) (reference "Luke 20:27-40"))))
+ (of-ordinary-time-33-saturday-ii
+ (((part First) (reference "Revelation 11:4-12"))
+ ((part Gospel) (reference "Luke 20:27-40"))))
+ (of-ordinary-time-33-thursday-i
+ (((part First) (reference "1 Maccabees 2:15-29"))
+ ((part Gospel) (reference "Luke 19:41-44"))))
+ (of-ordinary-time-33-thursday-ii
+ (((part First) (reference "Revelation 5:1-10"))
+ ((part Gospel) (reference "Luke 19:41-44"))))
+ (of-ordinary-time-33-tuesday-i
+ (((part First) (reference "2 Maccabees 6:18-31"))
+ ((part Gospel) (reference "Luke 19:1-10"))))
+ (of-ordinary-time-33-tuesday-ii
+ (((part First) (reference "Revelation 3:1-6,14-22"))
+ ((part Gospel) (reference "Luke 19:1-10"))))
+ (of-ordinary-time-33-wednesday-i
+ (((part First) (reference "2 Maccabees 7:1,20-31"))
+ ((part Gospel) (reference "Luke 19:11-28"))))
+ (of-ordinary-time-33-wednesday-ii
+ (((part First) (reference "Revelation 4:1-11"))
+ ((part Gospel) (reference "Luke 19:11-28"))))
+ (of-ordinary-time-34-friday-i
+ (((part First) (reference "Daniel 7:2-14"))
+ ((part Gospel) (reference "Luke 21:29-33"))))
+ (of-ordinary-time-34-friday-ii
+ (((part First) (reference "Revelation 20:1-4,11-21:2"))
+ ((part Gospel) (reference "Luke 21:29-33"))))
+ (of-ordinary-time-34-monday-i
+ (((part First) (reference "Daniel 1:1-6,8-20"))
+ ((part Gospel) (reference "Luke 21:1-4"))))
+ (of-ordinary-time-34-monday-ii
+ (((part First) (reference "Revelation 14:1-3,4b-5"))
+ ((part Gospel) (reference "Luke 21:1-4"))))
+ (of-ordinary-time-34-saturday-i
+ (((part First) (reference "Daniel 7:15-27"))
+ ((part Gospel) (reference "Luke 21:34-36"))))
+ (of-ordinary-time-34-saturday-ii
+ (((part First) (reference "Revelation 22:1-7"))
+ ((part Gospel) (reference "Luke 21:34-36"))))
+ (of-ordinary-time-34-thursday-i
+ (((part First) (reference "Daniel 6:12-28"))
+ ((part Gospel) (reference "Luke 21:20-28"))))
+ (of-ordinary-time-34-thursday-ii
+ (((part First) (reference "Revelation 18:1-2,21-23;19:1-3,9a"))
+ ((part Gospel) (reference "Luke 21:20-28"))))
+ (of-ordinary-time-34-tuesday-i
+ (((part First) (reference "Daniel 2:31-45"))
+ ((part Gospel) (reference "Luke 21:5-11"))))
+ (of-ordinary-time-34-tuesday-ii
+ (((part First) (reference "Revelation 14:14-19"))
+ ((part Gospel) (reference "Luke 21:5-11"))))
+ (of-ordinary-time-34-wednesday-i
+ (((part First) (reference "Daniel 5:1-6,13-14,16-17,23-28"))
+ ((part Gospel) (reference "Luke 21:12-19"))))
+ (of-ordinary-time-34-wednesday-ii
+ (((part First) (reference "Revelation 15:1-4"))
+ ((part Gospel) (reference "Luke 21:12-19"))))
+ (of-ordinary-time-4-friday-i
+ (((part First) (reference "Hebrews 13:1-8"))
+ ((part Gospel) (reference "Mark 6:14-29"))))
+ (of-ordinary-time-4-friday-ii
+ (((part First) (reference "Sirach 47:2-11"))
+ ((part Gospel) (reference "Mark 6:14-29"))))
+ (of-ordinary-time-4-monday-i
+ (((part First) (reference "Hebrews 11:32-40"))
+ ((part Gospel) (reference "Mark 5:1-20"))))
+ (of-ordinary-time-4-monday-ii
+ (((part First) (reference "2 Samuel 15:13-14,30;16:5-13"))
+ ((part Gospel) (reference "Mark 5:1-22"))))
+ (of-ordinary-time-4-saturday-i
+ (((part First) (reference "Hebrews 13:15-17,20-21"))
+ ((part Gospel) (reference "Mark 6:30-34"))))
+ (of-ordinary-time-4-saturday-ii
+ (((part First) (reference "1 Kings 3:4-13"))
+ ((part Gospel) (reference "Mark 6:30-34"))))
+ (of-ordinary-time-4-thursday-i
+ (((part First) (reference "Hebrews 12:18-19,21-24"))
+ ((part Gospel) (reference "Mark 6:7-13"))))
+ (of-ordinary-time-4-thursday-ii
+ (((part First) (reference "1 Kings 2:1-4,10-12"))
+ ((part Gospel) (reference "Mark 6:7-13"))))
+ (of-ordinary-time-4-tuesday-i
+ (((part First) (reference "Hebrews 12:1-4"))
+ ((part Gospel) (reference "Mark 5:21-43"))))
+ (of-ordinary-time-4-tuesday-ii
+ (((part First) (reference "2 Samuel 18:9-10,14b,24-25a,30-19:3"))
+ ((part Gospel) (reference "Mark 5:21-43"))))
+ (of-ordinary-time-4-wednesday-i
+ (((part First) (reference "Hebrews 12:4-7,11-15"))
+ ((part Gospel) (reference "Mark 6:1-6"))))
+ (of-ordinary-time-4-wednesday-ii
+ (((part First) (reference "2 Samuel 24:2,9-17"))
+ ((part Gospel) (reference "Mark 6:1-6"))))
+ (of-ordinary-time-5-friday-i
+ (((part First) (reference "Genesis 3:1-8"))
+ ((part Gospel) (reference "Mark 7:31-37"))))
+ (of-ordinary-time-5-friday-ii
+ (((part First) (reference "1 Kings 11:29-32;12:19"))
+ ((part Gospel) (reference "Mark 7:31-37"))))
+ (of-ordinary-time-5-monday-i
+ (((part First) (reference "Genesis 1:1-19"))
+ ((part Gospel) (reference "Mark 6:53-56"))))
+ (of-ordinary-time-5-monday-ii
+ (((part First) (reference "1 Kings 8:1-7,9-13"))
+ ((part Gospel) (reference "Mark 6:53-56"))))
+ (of-ordinary-time-5-saturday-i
+ (((part First) (reference "Genesis 3:9-24"))
+ ((part Gospel) (reference "Mark 8:1-10"))))
+ (of-ordinary-time-5-saturday-ii
+ (((part First) (reference "1 Kings 12:26-32;13:33-34"))
+ ((part Gospel) (reference "Mark 8:1-10"))))
+ (of-ordinary-time-5-thursday-i
+ (((part First) (reference "Genesis 2:18-25"))
+ ((part Gospel) (reference "Mark 7:24-30"))))
+ (of-ordinary-time-5-thursday-ii
+ (((part First) (reference "1 Kings 11:4-13"))
+ ((part Gospel) (reference "Mark 7:24-30"))))
+ (of-ordinary-time-5-tuesday-i
+ (((part First) (reference "Genesis 1:20-2:4a"))
+ ((part Gospel) (reference "Mark 7:1-13"))))
+ (of-ordinary-time-5-tuesday-ii
+ (((part First) (reference "1 Kings 8:22-23,27-30"))
+ ((part Gospel) (reference "Mark 7:1-13"))))
+ (of-ordinary-time-5-wednesday-i
+ (((part First) (reference "Genesis 2:4b-9,15-17"))
+ ((part Gospel) (reference "Mark 7:14-23"))))
+ (of-ordinary-time-5-wednesday-ii
+ (((part First) (reference "1 Kings 10:1-10"))
+ ((part Gospel) (reference "Mark 7:14-23"))))
+ (of-ordinary-time-6-friday-i
+ (((part First) (reference "Genesis 11:1-9"))
+ ((part Gospel) (reference "Mark 8:34-9:1"))))
+ (of-ordinary-time-6-friday-ii
+ (((part First) (reference "James 2:14-24,26"))
+ ((part Gospel) (reference "Mark 8:34-9:1"))))
+ (of-ordinary-time-6-monday-i
+ (((part First) (reference "Genesis 4:1-15,25"))
+ ((part Gospel) (reference "Mark 8:11-13"))))
+ (of-ordinary-time-6-monday-ii
+ (((part First) (reference "James 1:1-11"))
+ ((part Gospel) (reference "Mark 8:11-13"))))
+ (of-ordinary-time-6-saturday-i
+ (((part First) (reference "Hebrews 11:1-7"))
+ ((part Gospel) (reference "Mark 9:2-13"))))
+ (of-ordinary-time-6-saturday-ii
+ (((part First) (reference "James 3:1-10"))
+ ((part Gospel) (reference "Mark 9:2-13"))))
+ (of-ordinary-time-6-thursday-i
+ (((part First) (reference "Genesis 9:1-13"))
+ ((part Gospel) (reference "Mark 8:27-33"))))
+ (of-ordinary-time-6-thursday-ii
+ (((part First) (reference "James 2:1-9"))
+ ((part Gospel) (reference "Mark 8:27-33"))))
+ (of-ordinary-time-6-tuesday-i
+ (((part First) (reference "Genesis 6:5-8;7:1-5,10"))
+ ((part Gospel) (reference "Mark 8:14-21"))))
+ (of-ordinary-time-6-tuesday-ii
+ (((part First) (reference "James 1:12-18"))
+ ((part Gospel) (reference "Mark 8:14-21"))))
+ (of-ordinary-time-6-wednesday-i
+ (((part First) (reference "Genesis 8:6-13,20-22"))
+ ((part Gospel) (reference "Mark 8:22-26"))))
+ (of-ordinary-time-6-wednesday-ii
+ (((part First) (reference "James 1:19-27"))
+ ((part Gospel) (reference "Mark 8:22-26"))))
+ (of-ordinary-time-7-friday-i
+ (((part First) (reference "Sirach 6:5-17"))
+ ((part Gospel) (reference "Mark 10:1-12"))))
+ (of-ordinary-time-7-friday-ii
+ (((part First) (reference "James 5:9-12"))
+ ((part Gospel) (reference "Mark 10:1-12"))))
+ (of-ordinary-time-7-monday-i
+ (((part First) (reference "Sirach 1:1-10"))
+ ((part Gospel) (reference "Mark 9:14-29"))))
+ (of-ordinary-time-7-monday-ii
+ (((part First) (reference "James 3:13-18"))
+ ((part Gospel) (reference "Mark 9:14-29"))))
+ (of-ordinary-time-7-saturday-i
+ (((part First) (reference "Sirach 17:1-15"))
+ ((part Gospel) (reference "Mark 10:13-16"))))
+ (of-ordinary-time-7-saturday-ii
+ (((part First) (reference "James 5:13-22"))
+ ((part Gospel) (reference "Mark 10:13-16"))))
+ (of-ordinary-time-7-thursday-i
+ (((part First) (reference "Sirach 5:1-8"))
+ ((part Gospel) (reference "Mark 9:41-50"))))
+ (of-ordinary-time-7-thursday-ii
+ (((part First) (reference "James 5:1-6"))
+ ((part Gospel) (reference "Mark 9:41-50"))))
+ (of-ordinary-time-7-tuesday-i
+ (((part First) (reference "Sirach 2:1-11"))
+ ((part Gospel) (reference "Mark 9:30-37"))))
+ (of-ordinary-time-7-tuesday-ii
+ (((part First) (reference "James 4:1-10"))
+ ((part Gospel) (reference "Mark 9:30-37"))))
+ (of-ordinary-time-7-wednesday-i
+ (((part First) (reference "Sirach 4:11-19"))
+ ((part Gospel) (reference "Mark 9:38-40"))))
+ (of-ordinary-time-7-wednesday-ii
+ (((part First) (reference "James 4:13-17"))
+ ((part Gospel) (reference "Mark 9:38-40"))))
+ (of-ordinary-time-8-friday-i
+ (((part First) (reference "Sirach 44:1,9-13"))
+ ((part Gospel) (reference "Mark 11:11-26"))))
+ (of-ordinary-time-8-friday-ii
+ (((part First) (reference "1 Peter 4:7-13"))
+ ((part Gospel) (reference "Mark 11:11-26"))))
+ (of-ordinary-time-8-monday-i
+ (((part First) (reference "Sirach 17:20-24"))
+ ((part Gospel) (reference "Mark 10:17-27"))))
+ (of-ordinary-time-8-monday-ii
+ (((part First) (reference "1 Peter 1:3-9"))
+ ((part Gospel) (reference "Mark 10:17-27"))))
+ (of-ordinary-time-8-saturday-i
+ (((part First) (reference "Sirach 51:12cd-20"))
+ ((part Gospel) (reference "Mark 11:27-33"))))
+ (of-ordinary-time-8-saturday-ii
+ (((part First) (reference "Jude 17,20b-25"))
+ ((part Gospel) (reference "Mark 11:27-33"))))
+ (of-ordinary-time-8-thursday-i
+ (((part First) (reference "Sirach 42:15-25"))
+ ((part Gospel) (reference "Mark 10:46-52"))))
+ (of-ordinary-time-8-thursday-ii
+ (((part First) (reference "1 Peter 2:2-5,9-12"))
+ ((part Gospel) (reference "Mark 10:46-52"))))
+ (of-ordinary-time-8-tuesday-i
+ (((part First) (reference "Sirach 35:1-12"))
+ ((part Gospel) (reference "Mark 10:28-31"))))
+ (of-ordinary-time-8-tuesday-ii
+ (((part First) (reference "1 Peter 1:10-16"))
+ ((part Gospel) (reference "Mark 10:28-31"))))
+ (of-ordinary-time-8-wednesday-i
+ (((part First) (reference "Sirach 36:1,4-5a,10-17"))
+ ((part Gospel) (reference "Mark 10:32-45"))))
+ (of-ordinary-time-8-wednesday-ii
+ (((part First) (reference "1 Peter 1:18-25"))
+ ((part Gospel) (reference "Mark 10:32-45"))))
+ (of-ordinary-time-9-friday-i
+ (((part First) (reference "Tobit 11:5-17"))
+ ((part Gospel) (reference "Mark 12:35-37"))))
+ (of-ordinary-time-9-friday-ii
+ (((part First) (reference "2 Timothy 3:10-17"))
+ ((part Gospel) (reference "Mark 12:35-37"))))
+ (of-ordinary-time-9-monday-i
+ (((part First) (reference "Tobit 1:3;2:1a-8"))
+ ((part Gospel) (reference "Mark 12:1-12"))))
+ (of-ordinary-time-9-monday-ii
+ (((part First) (reference "2 Peter 1:2-7"))
+ ((part Gospel) (reference "Mark 12:1-12"))))
+ (of-ordinary-time-9-saturday-i
+ (((part First) (reference "Tobit 12:1,5-15,20"))
+ ((part Gospel) (reference "Mark 12:38-44"))))
+ (of-ordinary-time-9-saturday-ii
+ (((part First) (reference "2 Timothy 4:1-8"))
+ ((part Gospel) (reference "Mark 12:38-44"))))
+ (of-ordinary-time-9-thursday-i
+ (((part First) (reference "Tobit 6:10-11;7:1bcde,9-17;8:4-9a"))
+ ((part Gospel) (reference "Mark 12:28b-34"))))
+ (of-ordinary-time-9-thursday-ii
+ (((part First) (reference "2 Timothy 2:8-15"))
+ ((part Gospel) (reference "Mark 12:28b-34"))))
+ (of-ordinary-time-9-tuesday-i
+ (((part First) (reference "Tobit 2:9-14"))
+ ((part Gospel) (reference "Mark 12:13-17"))))
+ (of-ordinary-time-9-tuesday-ii
+ (((part First) (reference "2 Peter 3:12-15a,17-18"))
+ ((part Gospel) (reference "Mark 12:13-17"))))
+ (of-ordinary-time-9-wednesday-i
+ (((part First) (reference "Tobit 3:1-11a,16-17a"))
+ ((part Gospel) (reference "Mark 12:18-27"))))
+ (of-ordinary-time-9-wednesday-ii
+ (((part First) (reference "2 Timothy 1:1-3,6-12"))
+ ((part Gospel) (reference "Mark 12:18-27"))))
+ (of-ordinary-time-sunday-10-a
+ (((part First) (reference "Hosea 6:3-6"))
+ ((part Gospel) (reference "Matthew 9:9-13"))))
+ (of-ordinary-time-sunday-10-b
+ (((part First) (reference "Genesis 3:9-15"))
+ ((part Gospel) (reference "Mark 3:20-35"))))
+ (of-ordinary-time-sunday-10-c
+ (((part First) (reference "1 Kings 17:17-24"))
+ ((part Gospel) (reference "Luke 7:11-17"))))
+ (of-ordinary-time-sunday-11-a
+ (((part First) (reference "Exodus 19:2-6a"))
+ ((part Gospel) (reference "Matthew 9:36-10:8"))))
+ (of-ordinary-time-sunday-11-b
+ (((part First) (reference "Ezekiel 17:22-24"))
+ ((part Gospel) (reference "Mark 4:26-34"))))
+ (of-ordinary-time-sunday-11-c
+ (((part First) (reference "2 Samuel 12:7-10,13"))
+ ((part Gospel) (reference "Luke 7:36-8:3"))))
+ (of-ordinary-time-sunday-12-a
+ (((part First) (reference "Jeremiah 20:10-13"))
+ ((part Gospel) (reference "Matthew 10:26-33"))))
+ (of-ordinary-time-sunday-12-b
+ (((part First) (reference "Job 38:1,8-11"))
+ ((part Gospel) (reference "Mark 4:35-41"))))
+ (of-ordinary-time-sunday-12-c
+ (((part First) (reference "Zechariah 12:10-11;13:1"))
+ ((part Gospel) (reference "Luke 9:18-24"))))
+ (of-ordinary-time-sunday-13-a
+ (((part First) (reference "2 Kings 4:8-11,14-16a"))
+ ((part Gospel) (reference "Matthew 10:37-42"))))
+ (of-ordinary-time-sunday-13-b
+ (((part First) (reference "Wisdom 1:13-15;2:23-24"))
+ ((part Gospel) (reference "Mark 5:21-43"))))
+ (of-ordinary-time-sunday-13-c
+ (((part First) (reference "1 Kings 19:16b,19-21"))
+ ((part Gospel) (reference "Luke 9:51-62"))))
+ (of-ordinary-time-sunday-14-a
+ (((part First) (reference "Zechariah 9:9-10"))
+ ((part Gospel) (reference "Matthew 11:25-30"))))
+ (of-ordinary-time-sunday-14-b
+ (((part First) (reference "Ezekiel 2:2-5"))
+ ((part Gospel) (reference "Mark 6:1-6"))))
+ (of-ordinary-time-sunday-14-c
+ (((part First) (reference "Isaiah 66:10-14c"))
+ ((part Gospel) (reference "Luke 10:1-12,17-20"))))
+ (of-ordinary-time-sunday-15-a
+ (((part First) (reference "Isaiah 55:10-11"))
+ ((part Gospel) (reference "Matthew 13:1-23"))))
+ (of-ordinary-time-sunday-15-b
+ (((part First) (reference "Amos 7:12-15"))
+ ((part Gospel) (reference "Mark 6:7-13"))))
+ (of-ordinary-time-sunday-15-c
+ (((part First) (reference "Deuteronomy 30:10-14"))
+ ((part Gospel) (reference "Luke 10:25-37"))))
+ (of-ordinary-time-sunday-16-a
+ (((part First) (reference "Wisdom 12:13,16-19"))
+ ((part Gospel) (reference "Matthew 13:24-43"))))
+ (of-ordinary-time-sunday-16-b
+ (((part First) (reference "Jeremiah 23:1-6"))
+ ((part Gospel) (reference "Mark 6:30-34"))))
+ (of-ordinary-time-sunday-16-c
+ (((part First) (reference "Genesis 18:1-10a"))
+ ((part Gospel) (reference "Luke 10:38-42"))))
+ (of-ordinary-time-sunday-17-a
+ (((part First) (reference "1 Kings 3:5,7-12"))
+ ((part Gospel) (reference "Matthew 13:44-52"))))
+ (of-ordinary-time-sunday-17-b
+ (((part First) (reference "2 Kings 4:42-44"))
+ ((part Gospel) (reference "John 6:1-15"))))
+ (of-ordinary-time-sunday-17-c
+ (((part First) (reference "Genesis 18:20-32"))
+ ((part Gospel) (reference "Luke 11:1-13"))))
+ (of-ordinary-time-sunday-18-a
+ (((part First) (reference "Isaiah 55:1-3"))
+ ((part Gospel) (reference "Matthew 14:13-21"))))
+ (of-ordinary-time-sunday-18-b
+ (((part First) (reference "Exodus 16:2-4,12-15"))
+ ((part Gospel) (reference "John 6:24-35"))))
+ (of-ordinary-time-sunday-18-c
+ (((part First) (reference "Ecclesiastes 1:2;2:21-23"))
+ ((part Gospel) (reference "Luke 12:13-21"))))
+ (of-ordinary-time-sunday-19-a
+ (((part First) (reference "1 Kings 19:9a,11-13a"))
+ ((part Gospel) (reference "Matthew 14:22-33"))))
+ (of-ordinary-time-sunday-19-b
+ (((part First) (reference "1 Kings 19:4-8"))
+ ((part Gospel) (reference "John 6:41-51"))))
+ (of-ordinary-time-sunday-19-c
+ (((part First) (reference "Wisdom 18:6-9"))
+ ((part Gospel) (reference "Luke 12:32-48"))))
+ (of-ordinary-time-sunday-2-a
+ (((part First) (reference "Isaiah 49:3,5-6"))
+ ((part Gospel) (reference "John 1:29-34"))))
+ (of-ordinary-time-sunday-2-b
+ (((part First) (reference "1 Samuel 3:3b-10,19"))
+ ((part Gospel) (reference "John 1:35-42"))))
+ (of-ordinary-time-sunday-2-c
+ (((part First) (reference "Isaiah 62:1-5"))
+ ((part Gospel) (reference "John 2:1-11"))))
+ (of-ordinary-time-sunday-20-a
+ (((part First) (reference "Isaiah 56:1,6-7"))
+ ((part Gospel) (reference "Matthew 15:21-28"))))
+ (of-ordinary-time-sunday-20-b
+ (((part First) (reference "Proverbs 9:1-6"))
+ ((part Gospel) (reference "John 6:51-58"))))
+ (of-ordinary-time-sunday-20-c
+ (((part First) (reference "Jeremiah 38:4-6,8-10"))
+ ((part Gospel) (reference "Luke 12:49-53"))))
+ (of-ordinary-time-sunday-21-a
+ (((part First) (reference "Isaiah 22:19-23"))
+ ((part Gospel) (reference "Matthew 16:13-20"))))
+ (of-ordinary-time-sunday-21-b
+ (((part First) (reference "Joshua 24:1-2a,15-17,18b"))
+ ((part Gospel) (reference "John 6:60-69"))))
+ (of-ordinary-time-sunday-21-c
+ (((part First) (reference "Isaiah 66:18-21"))
+ ((part Gospel) (reference "Luke 13:22-30"))))
+ (of-ordinary-time-sunday-22-a
+ (((part First) (reference "Jeremiah 20:7-9"))
+ ((part Gospel) (reference "Matthew 16:21-27"))))
+ (of-ordinary-time-sunday-22-b
+ (((part First) (reference "Deuteronomy 4:1-2,6-8"))
+ ((part Gospel) (reference "Mark 7:1-8,14-15,21-23"))))
+ (of-ordinary-time-sunday-22-c
+ (((part First) (reference "Sirach 3:17-18,20,28-29"))
+ ((part Gospel) (reference "Luke 14:1,7-14"))))
+ (of-ordinary-time-sunday-23-a
+ (((part First) (reference "Ezekiel 33:7-9"))
+ ((part Gospel) (reference "Matthew 18:15-20"))))
+ (of-ordinary-time-sunday-23-b
+ (((part First) (reference "Isaiah 35:4-7a"))
+ ((part Gospel) (reference "Mark 7:31-37"))))
+ (of-ordinary-time-sunday-23-c
+ (((part First) (reference "Wisdom 9:13-18b"))
+ ((part Gospel) (reference "Luke 14:25-33"))))
+ (of-ordinary-time-sunday-24-a
+ (((part First) (reference "Sirach 27:30-28:7"))
+ ((part Gospel) (reference "Matthew 18:21-35"))))
+ (of-ordinary-time-sunday-24-b
+ (((part First) (reference "Isaiah 50:4-9a"))
+ ((part Gospel) (reference "Mark 8:27-35"))))
+ (of-ordinary-time-sunday-24-c
+ (((part First) (reference "Exodus 32:7-11,13-14"))
+ ((part Gospel) (reference "Luke 15:1-32"))))
+ (of-ordinary-time-sunday-25-a
+ (((part First) (reference "Isaiah 55:6-9"))
+ ((part Gospel) (reference "Matthew 20:1-16a"))))
+ (of-ordinary-time-sunday-25-b
+ (((part First) (reference "Wisdom 2:12,17-20"))
+ ((part Gospel) (reference "Mark 9:30-37"))))
+ (of-ordinary-time-sunday-25-c
+ (((part First) (reference "Amos 8:4-7"))
+ ((part Gospel) (reference "Luke 16:1-13"))))
+ (of-ordinary-time-sunday-26-a
+ (((part First) (reference "Ezekiel 18:25-28"))
+ ((part Gospel) (reference "Matthew 21:28-32"))))
+ (of-ordinary-time-sunday-26-b
+ (((part First) (reference "Numbers 11:25-29"))
+ ((part Gospel) (reference "Mark 9:38-43,45,47-48"))))
+ (of-ordinary-time-sunday-26-c
+ (((part First) (reference "Amos 6:1a,4-7"))
+ ((part Gospel) (reference "Luke 16:19-31"))))
+ (of-ordinary-time-sunday-27-a
+ (((part First) (reference "Isaiah 5:1-7"))
+ ((part Gospel) (reference "Matthew 21:33-43"))))
+ (of-ordinary-time-sunday-27-b
+ (((part First) (reference "Genesis 2:18-24"))
+ ((part Gospel) (reference "Mark 10:2-16"))))
+ (of-ordinary-time-sunday-27-c
+ (((part First) (reference "Habakkuk 1:2-3;2:2-4"))
+ ((part Gospel) (reference "Luke 17:5-10"))))
+ (of-ordinary-time-sunday-28-a
+ (((part First) (reference "Isaiah 25:6-10a"))
+ ((part Gospel) (reference "Matthew 22:1-14"))))
+ (of-ordinary-time-sunday-28-b
+ (((part First) (reference "Wisdom 7:7-11"))
+ ((part Gospel) (reference "Mark 10:17-30"))))
+ (of-ordinary-time-sunday-28-c
+ (((part First) (reference "2 Kings 5:14-17"))
+ ((part Gospel) (reference "Luke 17:11-19"))))
+ (of-ordinary-time-sunday-29-a
+ (((part First) (reference "Isaiah 45:1,4-6"))
+ ((part Gospel) (reference "Matthew 22:15-21"))))
+ (of-ordinary-time-sunday-29-b
+ (((part First) (reference "Isaiah 53:10-11"))
+ ((part Gospel) (reference "Mark 10:35-45"))))
+ (of-ordinary-time-sunday-29-c
+ (((part First) (reference "Exodus 17:8-13"))
+ ((part Gospel) (reference "Luke 18:1-8"))))
+ (of-ordinary-time-sunday-3-a
+ (((part First) (reference "Isaiah 8:23b-9:3"))
+ ((part Gospel) (reference "Matthew 4:12-23"))))
+ (of-ordinary-time-sunday-3-b
+ (((part First) (reference "Jonah 3:1-5,10"))
+ ((part Gospel) (reference "Mark 1:14-20"))))
+ (of-ordinary-time-sunday-3-c
+ (((part First) (reference "Nehemiah 8:2-4a,5-6,8-10"))
+ ((part Gospel) (reference "Luke 1:1-4;4:14-21"))))
+ (of-ordinary-time-sunday-30-a
+ (((part First) (reference "Exodus 22:20-26"))
+ ((part Gospel) (reference "Matthew 22:34-40"))))
+ (of-ordinary-time-sunday-30-b
+ (((part First) (reference "Jeremiah 31:7-9"))
+ ((part Gospel) (reference "Mark 10:46-52"))))
+ (of-ordinary-time-sunday-30-c
+ (((part First) (reference "Sirach 35:12-14,16-18"))
+ ((part Gospel) (reference "Luke 18:9-14"))))
+ (of-ordinary-time-sunday-31-a
+ (((part First) (reference "Malachi 1:14b-2:2b,8-10"))
+ ((part Gospel) (reference "Matthew 23:1-12"))))
+ (of-ordinary-time-sunday-31-b
+ (((part First) (reference "Deuteronomy 6:2-6"))
+ ((part Gospel) (reference "Mark 12:28b-34"))))
+ (of-ordinary-time-sunday-31-c
+ (((part First) (reference "Wisdom 11:22-12:2"))
+ ((part Gospel) (reference "Luke 19:1-10"))))
+ (of-ordinary-time-sunday-32-a
+ (((part First) (reference "Wisdom 6:12-16"))
+ ((part Gospel) (reference "Matthew 25:1-13"))))
+ (of-ordinary-time-sunday-32-b
+ (((part First) (reference "1 Kings 17:10-16"))
+ ((part Gospel) (reference "Mark 12:38-44"))))
+ (of-ordinary-time-sunday-32-c
+ (((part First) (reference "2 Maccabees 7:1-2,9-14"))
+ ((part Gospel) (reference "Luke 20:27-38"))))
+ (of-ordinary-time-sunday-33-a
+ (((part First) (reference "Proverbs 31:10-13,19-20,30-31"))
+ ((part Gospel) (reference "Matthew 25:14-30"))))
+ (of-ordinary-time-sunday-33-b
+ (((part First) (reference "Daniel 12:1-3"))
+ ((part Gospel) (reference "Mark 13:24-32"))))
+ (of-ordinary-time-sunday-33-c
+ (((part First) (reference "Malachi 4:1-2"))
+ ((part Gospel) (reference "Luke 21:5-19"))))
+ (of-ordinary-time-sunday-4-a
+ (((part First) (reference "Zephaniah 2:3;3:12-13"))
+ ((part Gospel) (reference "Matthew 5:1-12a"))))
+ (of-ordinary-time-sunday-4-b
+ (((part First) (reference "Deuteronomy 18:15-20"))
+ ((part Gospel) (reference "Mark 1:21-28"))))
+ (of-ordinary-time-sunday-4-c
+ (((part First) (reference "Jeremiah 1:4-5,17-19"))
+ ((part Gospel) (reference "Luke 4:21-30"))))
+ (of-ordinary-time-sunday-5-a
+ (((part First) (reference "Isaiah 58:7-10"))
+ ((part Gospel) (reference "Matthew 5:13-16"))))
+ (of-ordinary-time-sunday-5-b
+ (((part First) (reference "Job 7:1-4,6-7"))
+ ((part Gospel) (reference "Mark 1:29-39"))))
+ (of-ordinary-time-sunday-5-c
+ (((part First) (reference "Isaiah 6:1-2a,3-8"))
+ ((part Gospel) (reference "Luke 5:1-11"))))
+ (of-ordinary-time-sunday-6-a
+ (((part First) (reference "Sirach 15:16-21"))
+ ((part Gospel) (reference "Matthew 5:17-37"))))
+ (of-ordinary-time-sunday-6-b
+ (((part First) (reference "Leviticus 13:1-2,44-46"))
+ ((part Gospel) (reference "Mark 1:40-45"))))
+ (of-ordinary-time-sunday-6-c
+ (((part First) (reference "Jeremiah 17:5-8"))
+ ((part Gospel) (reference "Luke 6:17,20-26"))))
+ (of-ordinary-time-sunday-7-a
+ (((part First) (reference "Leviticus 19:1-2,17-18"))
+ ((part Gospel) (reference "Matthew 5:38-48"))))
+ (of-ordinary-time-sunday-7-b
+ (((part First) (reference "Isaiah 43:18-19,21-22,24b-25"))
+ ((part Gospel) (reference "Mark 2:1-12"))))
+ (of-ordinary-time-sunday-7-c
+ (((part First) (reference "1 Samuel 26:2,7-9,12-13,22-23"))
+ ((part Gospel) (reference "Luke 6:27-38"))))
+ (of-ordinary-time-sunday-8-a
+ (((part First) (reference "Isaiah 49:14-15"))
+ ((part Gospel) (reference "Matthew 6:24-34"))))
+ (of-ordinary-time-sunday-8-b
+ (((part First) (reference "Hosea 2:16b,17b,21-22"))
+ ((part Gospel) (reference "Mark 2:18-22"))))
+ (of-ordinary-time-sunday-8-c
+ (((part First) (reference "Sirach 27:5-8"))
+ ((part Gospel) (reference "Luke 6:39-45"))))
+ (of-ordinary-time-sunday-9-a
+ (((part First) (reference "Deuteronomy 11:18,26-28,32"))
+ ((part Gospel) (reference "Matthew 7:21-27"))))
+ (of-ordinary-time-sunday-9-b
+ (((part First) (reference "Deuteronomy 5:12-15"))
+ ((part Gospel) (reference "Mark 2:23-3:6"))))
+ (of-ordinary-time-sunday-9-c
+ (((part First) (reference "1 Kings 8:41-43"))
+ ((part Gospel) (reference "Luke 7:1-10"))))
+ (of-palm-sunday-a
+ (((part First) (reference "Isaiah 50:4-7"))
+ ((part Gospel) (reference "Mat 27:11-54"))))
+ (of-palm-sunday-b
+ (((part First) (reference "Isaiah 50:4-7"))
+ ((part Gospel) (reference "Mark 15:1-39"))))
+ (of-palm-sunday-c
+ (((part First) (reference "Isaiah 50:4-7"))
+ ((part Gospel) (reference "Luke 23:1-49"))))
+ (of-pentecost-a
+ (((part First) (reference "The Acts 2:1-11"))
+ ((part Gospel) (reference "John 20:19-23"))))
+ (of-pentecost-b
+ (((part First) (reference "The Acts 2:1-11"))
+ ((part Gospel) (reference "John 15:26-27;16:12-15"))))
+ (of-pentecost-c
+ (((part First) (reference "The Acts 2:1-11"))
+ ((part Gospel) (reference "John 14:15-16,23b-26"))))
+ (of-trinity-a
+ (((part First) (reference "Exodus 34:4b-6,8-9"))
+ ((part Gospel) (reference "John 3:16-18"))))
+ (of-trinity-b
+ (((part First) (reference "Deuteronomy 4:32-34,39-40"))
+ ((part Gospel) (reference "Matthew 28:16-20"))))
+ (of-trinity-c
+ (((part First) (reference "Proverbs 8:22-31"))
+ ((part Gospel) (reference "John 16:12-15"))))
+ (presentation-of-the-lord
+ (((part First) (reference "Malachi 3:1-4"))
+ ((part Gospel) (reference "Luke 2:22-32"))))
+ (sacred-heart-of-jesus-a
+ (((part First) (reference "Deuteronomy 7:6-11"))
+ ((part Gospel) (reference "Matthew 11:25-30"))))
+ (sacred-heart-of-jesus-b
+ (((part First) (reference "Hosea 11:1,3-4,8c-9"))
+ ((part Gospel) (reference "John 19:31-37"))))
+ (sacred-heart-of-jesus-c
+ (((part First) (reference "Ezekiel 34:11-16"))
+ ((part Gospel) (reference "Luke 15:3-7"))))
+ (saints-michael-gabriel-and-raphael-archangels
+ (((part First) (reference "Daniel 7:9-10,13-14"))
+ ((part Gospel) (reference "John 1:47-51"))))
+ (saints-peter-and-paul-apostles
+ (((part First) (reference "Acts 3:1-10"))
+ ((part Gospel) (reference "John 21:15-19"))))
+ (saints-philip-and-james-apostles
+ (((part First) (reference "Revelation 11:19;12,1-6,10ab"))
+ ((part Gospel) (reference "John 19:25-27"))))
+ (simon-and-saint-jude-apostles
+ (((part First) (reference "Ephesians 2:19-22"))
+ ((part Gospel) (reference "Luke 6:12-19"))))
+ (stephen-the-first-martyr
+ (((part First) (reference "Acts 6:8-10;7:54-60"))
+ ((part Gospel) (reference "Mat 10:17-22"))))
+ (the-conversion-of-saint-paul-apostle
+ (((part First) (reference "Acts 22:3-16"))
+ ((part Gospel) (reference "Mark 16:15-18"))))
+ (thomas-the-apostle
+ (((part First) (reference "Ephesians 2:19-22"))
+ ((part Gospel) (reference "John 20:24-29"))))
+ (transfiguration-of-the-lord-a
+ (((part First) (reference "Daniel 7:9-10,13-14"))
+ ((part Gospel) (reference "Mat 17:1-9"))))
+ (transfiguration-of-the-lord-b
+ (((part First) (reference "Daniel 7:9-10,13-14"))
+ ((part Gospel) (reference "Mark 9:2-10"))))
+ (transfiguration-of-the-lord-c
+ (((part First) (reference "Daniel 7:9-10,13-14"))
+ ((part Gospel) (reference "Luke 9:28-36"))))
+ (triumph-of-the-holy-cross
+ (((part First) (reference "Numbers 21:4-9"))
+ ((part Gospel) (reference "John 3:13-17"))))
+ (visitation-of-the-blessed-virgin-mary
+ (((part First) (reference "Zephaniah 3:14-17"))
+ ((part Gospel) (reference "Luke 1:39-56")))))
diff --git a/lib/rites/rite_of/lectionary_of.ml b/lib/rites/rite_of/lectionary_of.ml
new file mode 100644
index 0000000..1664fad
--- /dev/null
+++ b/lib/rites/rite_of/lectionary_of.ml
@@ -0,0 +1,107 @@
+(* See lectionary_of.mli for the full citations and design argument. *)
+open Colitur_kernel
+
+type sunday_cycle = Year_a | Year_b | Year_c
+type weekday_cycle = Year_i | Year_ii
+
+let sunday_cycle_letter = function Year_a -> "a" | Year_b -> "b" | Year_c -> "c"
+let weekday_cycle_letter = function Year_i -> "i" | Year_ii -> "ii"
+
+(* The civil year in which the liturgical year CONTAINING [date] opened --
+ i.e. the year y such that [year_start y <= date < year_start (y + 1)].
+ This is the one piece of arithmetic both cycle rules share, and it is
+ exactly the "get the boundary right" the task brief names: a date in,
+ say, early December belongs to the liturgical year that opened THAT
+ same Advent only once Advent has actually started that year (compared
+ by real date, not by month) -- a month-based shortcut ("December always
+ means the new liturgical year") is wrong in the (real, if rare) case of
+ a December date still ahead of that year's own Advent I. *)
+let liturgical_year_open_year ~year_start date =
+ let y = Date.year date in
+ if Date.compare date (year_start y) >= 0 then y else y - 1
+
+(* OLM n.66 + footnote 102 (mli's own citation): the LABEL year is the one
+ most of the liturgical year falls in, i.e. one more than the year
+ Advent opened in ("a prima hebdomada Adventus, quae cadit in anno
+ civili praecedente" -- the first week of Advent falls in the PRECEDING
+ civil year relative to the label). Divisible by 3 -> C, then A, then B,
+ worked example 1980=C/1981=A/1982=B/1983=C verified against the real
+ page image. *)
+let sunday_cycle ~year_start date =
+ let label = liturgical_year_open_year ~year_start date + 1 in
+ match label mod 3 with 0 -> Year_c | 1 -> Year_a | _ -> Year_b
+
+(* OLM n.69 point 4 (mli's own citation): "Annus primus adhibetur annis
+ imparibus, annus secundus vero annis paribus" -- Year I in odd label
+ years, Year II in even. Same label-year computation as [sunday_cycle]
+ above, for the identical reason: this is a two-year cycle, not a
+ three-year one, but the label-year definition itself does not depend on
+ which modulus governs it. *)
+let weekday_cycle ~year_start date =
+ let label = liturgical_year_open_year ~year_start date + 1 in
+ if label mod 2 = 1 then Year_i else Year_ii
+
+(* Tries [base] flat, then [base]-<sunday letter>, then [base]-<weekday
+ letter>, in that order. Safe unconditionally: tools/
+ bootstrap_lectionary_of.ml emits a given base under AT MOST ONE of
+ these three forms (a flat entry when the two/three cycle years were
+ byte-identical, a cycle-lettered family otherwise -- never both), so at
+ most one of the three lookups below can ever hit, and trying the two
+ irrelevant forms for a family of the other kind or a flat family is
+ simply two wasted, harmless misses. This is what lets [readings] below
+ stay ignorant of which of the two cycle systems (or neither) a given
+ slug's own family actually uses. *)
+let lookup_any lectionary ~year_start base date =
+ match Lectionary.find lectionary base with
+ | Some cs -> Some cs
+ | None -> (
+ let with_suffix suffix = Slug.of_string_exn (Slug.to_string base ^ "-" ^ suffix) in
+ match Lectionary.find lectionary (with_suffix (sunday_cycle_letter (sunday_cycle ~year_start date))) with
+ | Some cs -> Some cs
+ | None -> Lectionary.find lectionary (with_suffix (weekday_cycle_letter (weekday_cycle ~year_start date))))
+
+let readings ~lectionary ~year_start ~(observed : Vocab_of.rank Celebration.t)
+ ~(temporal : (Vocab_of.season, Vocab_of.rank) Temporal.t) ~date ~temporal_at:_ =
+ match observed.Celebration.citations with
+ | _ :: _ as cs ->
+ (Some { Mass_formulary.said = Some observed.Celebration.slug; via = Mass_formulary.Proper }, cs)
+ | [] -> (
+ (* Step 2: a sanctoral entity actually won the day -- i.e. the
+ observed celebration is not itself the day's own temporal office.
+ Same guard shape as Rite_ef.Lectionary_ef.readings' own step 4
+ (see that module's implementation comment for the full argument
+ for why this comparison, not a [subject]/[status] test, is the
+ right one): comparing SLUGS is exact whenever the temporal and
+ sanctoral streams cannot collide, which holds here for the
+ identical reason it holds for EF -- every Temporal_of slug this
+ module ever constructs carries the "of-" prefix (temporal_of.ml's
+ own [temporal], every branch), and 0 of the 222 shipped
+ data/of/calendar-2002.sexp + amendments sanctoral slugs do. *)
+ let sanctoral_office =
+ not (Slug.equal observed.Celebration.slug temporal.Temporal.office.Celebration.slug)
+ in
+ match
+ if sanctoral_office then lookup_any lectionary ~year_start observed.Celebration.slug date else None
+ with
+ | Some cs ->
+ (* Mass_formulary.Proper, not .Common -- see lectionary_of.mli's
+ own doc comment on this branch for the full argument. In
+ short: EF's [Common] constructor names a SPECIFIC mechanism
+ (several saints sharing one formulary via an explicit
+ assignment table, data/ef/commons.sexp) that OF's own data has
+ no counterpart for -- every sanctoral slug this step resolves
+ carries its OWN dedicated lectio entry, not a shared one, so
+ relabelling it [Common] would claim a mechanism that is not
+ actually present. [Proper] is the honest fit: "the observed
+ celebration's own proper Mass", true regardless of whether the
+ citations are embedded on Celebration.t (step 1) or held
+ externally in [lectionary] (this step) -- a storage detail
+ Mass_formulary.source was never built to carry. *)
+ (Some { Mass_formulary.said = Some observed.Celebration.slug; via = Mass_formulary.Proper }, cs)
+ | None -> (
+ match lookup_any lectionary ~year_start temporal.Temporal.office.Celebration.slug date with
+ | Some cs ->
+ ( Some { Mass_formulary.said = Some temporal.Temporal.office.Celebration.slug;
+ via = Mass_formulary.Own_slug },
+ cs )
+ | None -> (None, [])))
diff --git a/lib/rites/rite_of/lectionary_of.mli b/lib/rites/rite_of/lectionary_of.mli
new file mode 100644
index 0000000..0c4d1d6
--- /dev/null
+++ b/lib/rites/rite_of/lectionary_of.mli
@@ -0,0 +1,136 @@
+(** The OF reading-cycle arithmetic and the temporal + sanctoral lectionary
+ resolution chain (Task 4, 2026-08-25-colitur-of-phases-3-5).
+
+ Two halves with a different character, per the task's own brief:
+
+ - {b The cycle rules are CODE}, computed from the civil year, cited to
+ the OLM (Ordo Lectionum Missae) 1981 Praenotanda -- see {!sunday_cycle}
+ and {!weekday_cycle} below for the citations, each verified against the
+ real page image (docs/research/of/olm-1981.pdf pp.32-33/"XXXII-XXXIII"),
+ not the unreliable OCR text layer (design spec 2026-08-24-colitur-of-
+ rite-module-design.md sec4.4's own caveat).
+ - {b The data is bootstrapped from lectio} (binding decision 3), a
+ POLISH VERNACULAR pastoral lectionary (niedziela.pl), not the Latin
+ OLM itself -- see tools/bootstrap_lectionary_of.ml's own top-of-file
+ comment and data/of/lectionary.sexp's own provenance header for the
+ full lineage statement and what it cannot show. *)
+
+open Colitur_kernel
+
+(** OLM 1981 Praenotanda n.66 (page-image verified, p.32/"XXXII"): "cyclus
+ trium annorum proponitur" -- the three-year Sunday/solemnity cycle.
+ Footnote 102, same page, gives the determining rule with a worked
+ example: "Per litteram C designatur annus cuius numerus in tres partes
+ aequales dividi potest... Sic annus 1980 est annus C, annus vero
+ sequens, scilicet annus 1981, est annus A, annus vero 1982 est annus B,
+ et annus 1983 est iterum annus C" -- the year divisible by three is
+ Year C, the next Year A, the next Year B. The SAME footnote also gives
+ the Gospel-per-year identity quoted on {!sunday_cycle}'s own doc
+ comment below (A = Matthew, B = Mark, C = Luke), and states explicitly
+ that each cycle's own "year" runs "iuxta dispositionem anni liturgici,
+ nempe a prima hebdomada Adventus, quae cadit in anno civili
+ praecedente" -- according to the liturgical year, namely from the first
+ week of Advent, WHICH FALLS IN THE PRECEDING CIVIL YEAR. This is the
+ task brief's own "the cycle turns at Advent I, not 1 January": Advent
+ 1980 (civil year 1980) already opens the 1981-labelled liturgical year
+ (Year A), even though most of civil year 1980 was still Year C. *)
+type sunday_cycle = Year_a | Year_b | Year_c
+
+(** OLM 1981 Praenotanda n.69 (page-image verified, p.33/"XXXIII"), the
+ "c) De ordinatione lectionum pro feriis" subsection's own point 4:
+ "Pro feriis vero triginta quattuor hebdomadarum <<per annum>> lectiones
+ evangelicae unico disponuntur cyclo, qui singulis annis resumitur.
+ Prior vero lectio, in duplici cyclo ordinatur, alternis annis legenda.
+ Annus primus adhibetur annis imparibus, annus secundus vero annis
+ paribus" -- for the ferias of the thirty-four weeks of Ordinary Time,
+ the GOSPEL is arranged in a single cycle repeated every year; the FIRST
+ reading alone alternates over two years. Year I is used in odd years,
+ Year II in even years. The SAME point 4, its own preceding points 2-3,
+ state the two-year alternation is confined to Ordinary Time: Lent has
+ its own single seasonal cycle (point 2) and "Pro feriis Adventus,
+ temporis Nativitatis et paschalis cyclus eodem modo annualis est:
+ lectiones ideo non mutantur" -- for the ferias of Advent, Christmastide
+ and Paschaltide the cycle is likewise annual: the readings DO NOT
+ CHANGE (point 3). {!Lectionary.t} does not need to encode that
+ distinction itself: a non-alternating family's own two cycle-letter
+ keys were collapsed to one flat entry at bootstrap time (see
+ tools/bootstrap_lectionary_of.ml's own [collapse_weekday]), so trying
+ both letters here is always safe -- the flat entry is found first
+ either way. *)
+type weekday_cycle = Year_i | Year_ii
+
+val sunday_cycle_letter : sunday_cycle -> string
+val weekday_cycle_letter : weekday_cycle -> string
+
+(** [sunday_cycle ~year_start date]: which of the three-year cycle's own
+ labelled years [date] falls in, per {!sunday_cycle}'s own citation.
+ A = Matthew, B = Mark, C = Luke -- OLM n.66's own footnote 102, same
+ passage: "primus cycli annus dicitur et est annus legendi Matthaeum,
+ ceteri vero, secundus nempe et tertius, respective annus legendi
+ Marcum et annus legendi Lucam". [year_start] is the rite's own
+ Advent-anchor function ({!Temporal_of.year_start}), supplied by the
+ caller rather than hard-coded, the same seam {!Rite_ef.Lectionary_ef
+ .readings}'s own [~lectionary]/[~commons] already use for rite data --
+ this module reads no filesystem and knows no OF-specific season
+ vocabulary of its own beyond what [year_start] and {!Colitur_kernel
+ .Temporal.t} already carry. *)
+val sunday_cycle : year_start:(int -> Date.t) -> Date.t -> sunday_cycle
+
+(** [weekday_cycle ~year_start date]: which of the two-year cycle's own
+ labelled years [date] falls in, per {!weekday_cycle}'s own citation. *)
+val weekday_cycle : year_start:(int -> Date.t) -> Date.t -> weekday_cycle
+
+(** The Mass's Epistle and Gospel citations for this day, and (when the
+ shipped data can name one) which formulary they came from -- the OF
+ counterpart of {!Rite_ef.Lectionary_ef.readings}, deliberately simpler:
+ OF has no Commons indirection table (spec's own scope for this task),
+ so the chain is three steps, not four:
+
+ - {b Step 1} -- the observed celebration's own embedded citations, if
+ any. {!Colitur_kernel.Mass_formulary.Proper}. Defensive: every
+ shipped data/of/calendar-2002.sexp entry carries [citations ()]
+ today (Task 1), so this step is currently dead on shipped data, kept
+ for the same forward-compatibility reason EF's own step 1 stays
+ first even where most callers reach it rarely.
+ - {b Step 2} -- when the observed celebration is NOT itself the day's
+ own temporal office (a real sanctoral entity won occurrence), its
+ own slug looked up directly in [lectionary] (tried flat, then both
+ cycle-letter suffixes via {!sunday_cycle}/{!weekday_cycle} -- a
+ sanctoral entry may be tagged either way in the shipped data, see
+ tools/bootstrap_lectionary_of.ml's own header, so both are tried
+ rather than assumed). Tagged {!Colitur_kernel.Mass_formulary.Proper}
+ too, not {!Colitur_kernel.Mass_formulary.Common}: OF has no shared-
+ formulary indirection the way EF's Commons do (this task's own
+ scope), so a looked-up sanctoral citation is still, substantively,
+ "the observed celebration's own proper" -- only ITS STORAGE differs
+ from step 1's (external file vs an embedded field), which
+ {!Colitur_kernel.Mass_formulary.source} was never designed to
+ distinguish (its own doc names what DECIDED the Mass, not where the
+ bytes happen to live). {!Colitur_kernel.Mass_formulary.source} is a
+ closed kernel type outside this task's own scope to extend; see
+ lectionary_of.ml's own implementation comment on this branch for the
+ full argument. [said] the observed slug.
+ - {b Step 3} -- the day's own temporal slug, same three-way lookup.
+ {!Colitur_kernel.Mass_formulary.Own_slug}, [said] that slug.
+ - A day matching neither gets [(None, [])] -- see data/of/lectionary
+ .sexp's own provenance header for exactly which days that is, both
+ directions, measured, not guessed.
+
+ NO preceding-Sunday fallback (EF's own step 3): unlike EF's RG 299,
+ the OF's own two-year FERIAL cycle assigns every Ordinary Time weekday
+ its own reading by design (OLM n.69 point 4, {!weekday_cycle}'s own
+ citation) -- there is no OF norm this task found instructing a ferial
+ with no proper of its own to repeat the preceding Sunday's Mass, so no
+ such step is built. [temporal_at] is therefore accepted, unused, to
+ satisfy {!Colitur_kernel.Rite.t}'s own [readings] field shape (the same
+ contract {!Rite_ef.Lectionary_ef.readings} satisfies) -- kept rather
+ than dropped so a future task that DOES find such a rule has the
+ callback already in place. *)
+val readings :
+ lectionary:Lectionary.t ->
+ year_start:(int -> Date.t) ->
+ observed:Vocab_of.rank Celebration.t ->
+ temporal:(Vocab_of.season, Vocab_of.rank) Temporal.t ->
+ date:Date.t ->
+ temporal_at:(Date.t -> (Vocab_of.season, Vocab_of.rank) Temporal.t) ->
+ Mass_formulary.t option * Citation.t list
diff --git a/test/dune b/test/dune
index c5bfe07..50bdee2 100644
--- a/test/dune
+++ b/test/dune
@@ -29,6 +29,8 @@
../data/of/expected-divergences-litcal.sexp
../data/ef/lectionary.sexp
../data/ef/commons.sexp
+ ../data/of/lectionary.sexp
+ ../tools/bootstrap_lectionary_of.exe
../data/ef/examples/diocesan-example.sexp
fixtures/lectio-ef-2005-2050.txt
fixtures/missalemeum-ef-2026-2027.txt
diff --git a/test/test_colitur.ml b/test/test_colitur.ml
index 3e16566..30e649e 100644
--- a/test/test_colitur.ml
+++ b/test/test_colitur.ml
@@ -27,6 +27,7 @@ let () =
Test_golden.suite;
("lectionary", Test_lectionary.suite);
("lectionary-ef", Test_lectionary_ef.suite);
+ ("lectionary-of", Test_lectionary_of.suite);
Test_escape.suite;
Test_template.suite;
Test_template.render_suite;
diff --git a/test/test_lectionary_of.ml b/test/test_lectionary_of.ml
new file mode 100644
index 0000000..6fb48a0
--- /dev/null
+++ b/test/test_lectionary_of.ml
@@ -0,0 +1,372 @@
+(* Task 4 (2026-08-25-colitur-of-phases-3-5): the reading-cycle arithmetic
+ and the temporal + sanctoral lectionary resolution chain,
+ Rite_of.Lectionary_of.
+
+ No Rite_of.context exists yet (Task 5's own deliverable), so the
+ coverage test below builds its own APPROXIMATE day resolver directly
+ against Layer.on_date + Temporal_of.temporal, rather than through
+ Calendar.day/Colitur_kernel.Validate -- it does not run RG-style
+ occurrence/precedence resolution (Precedence_of.rules is Task 5's own
+ wiring point too), so on a date where more than one sanctoral entry
+ would occur it simply takes the layer's own canonically-sorted first
+ match. This is not a claim that the FULL calendar resolves this way; it
+ is the minimum needed to exercise Lectionary_of.readings' own
+ observed-vs-temporal branch honestly, over real (not synthetic) data. *)
+
+module L = Colitur_kernel.Layer
+module O = Colitur_kernel.Overlay
+module Cel = Colitur_kernel.Celebration
+module D = Colitur_kernel.Date
+module Slug = Colitur_kernel.Slug
+module Mass_formulary = Colitur_kernel.Mass_formulary
+module Lectionary = Colitur_kernel.Lectionary
+module Computus = Colitur_kernel.Computus
+module V = Rite_of.Vocab_of
+module T = Rite_of.Temporal_of
+module Lect_of = Rite_of.Lectionary_of
+
+let d y m dd = match D.make ~year:y ~month:m ~day:dd with Ok t -> t | Error e -> Alcotest.failf "%s" e
+let iso = D.to_iso8601
+
+(* ---- fixtures -------------------------------------------------------- *)
+
+let lectionary_path = "../data/of/lectionary.sexp"
+let calendar_path = "../data/of/calendar-2002.sexp"
+let amendments_dir = "../data/of/amendments/"
+
+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_lectionary () =
+ match Lectionary.load lectionary_path with
+ | Ok l -> l
+ | Error e -> Alcotest.failf "%s: failed to load: %s" lectionary_path e
+
+let real_sanctoral_layer () =
+ let base =
+ match L.load V.rank_of_sexp calendar_path with
+ | Ok l -> l
+ | Error e -> Alcotest.failf "%s: failed to load: %s" calendar_path e
+ in
+ let overlays =
+ List.map
+ (fun name ->
+ let path = amendments_dir ^ name in
+ match O.load V.rank_of_sexp path with
+ | Ok o -> o
+ | Error e -> Alcotest.failf "%s: failed to load: %s" path e)
+ amendment_files
+ in
+ let merged, diagnostics = O.merge base overlays in
+ Alcotest.(check (list string)) "the committed OF overlays apply cleanly, no diagnostics" []
+ (List.map O.diagnostic_to_string diagnostics);
+ merged
+
+(* Approximate "observed" celebration for [date]: the sanctoral layer's own
+ (canonically-sorted) first match if any, else the day's own temporal
+ office -- see this file's own top-of-file comment for why this is a
+ deliberately simplified stand-in for real occurrence resolution. *)
+let observed_on index date temporal =
+ match L.on_date index date with
+ | e :: _ -> e.L.cel
+ | [] -> temporal.Colitur_kernel.Temporal.office
+
+let readings_on lectionary index date =
+ let temporal = T.temporal date in
+ let observed = observed_on index date temporal in
+ Lect_of.readings ~lectionary ~year_start:T.year_start ~observed ~temporal ~date ~temporal_at:T.temporal
+
+(* ---- cycle arithmetic (OLM 1981 Praenotanda n.66/n.69 -- see
+ lectionary_of.mli's own citations, page-image verified) ---- *)
+
+let sunday_letter c = Lect_of.sunday_cycle_letter c
+let weekday_letter c = Lect_of.weekday_cycle_letter c
+
+(* Every case here is derivable from OLM n.66's own footnote 102, whose
+ worked example ("annus 1980 est annus C, annus vero sequens, scilicet
+ annus 1981, est annus A, annus vero 1982 est annus B, et annus 1983 est
+ iterum annus C") is reproduced directly by testing dates EITHER SIDE of
+ Advent 1980/1981/1982 -- the task brief's own "straddle Advent I inside
+ a single civil year" requirement, exercised three times over, against
+ the primary source's own numbers, not invented ones. *)
+let test_sunday_cycle_table () =
+ let cases =
+ [ (* Just before Advent 1980 (still the liturgical year opened Advent
+ 1979, labelled 1980 -- OLM's own "1980 est annus C"), and Advent
+ 1980 itself (opens the year labelled 1981 -- "1981, est annus A"):
+ both civil dates fall in the SAME civil year, 1980, on either side
+ of that year's own Advent I -- the boundary the brief names. *)
+ (D.add_days (T.advent_start 1980) (-1), "c", "before Advent 1980 (civil year 1980, label 1980)");
+ (T.advent_start 1980, "a", "Advent Sunday 1980 itself (civil year 1980, label 1981)");
+ (D.add_days (T.advent_start 1980) 3, "a", "a few days into Advent 1980 (still label 1981)");
+ (* Advent 1981 -> 1982 (A -> B). *)
+ (D.add_days (T.advent_start 1981) (-1), "a", "before Advent 1981 (label 1981)");
+ (T.advent_start 1981, "b", "Advent Sunday 1981 (label 1982)");
+ (* Advent 1982 -> 1983 (B -> C). *)
+ (D.add_days (T.advent_start 1982) (-1), "b", "before Advent 1982 (label 1982)");
+ (T.advent_start 1982, "c", "Advent Sunday 1982 (label 1983)");
+ (* A live-relevant pair: Advent 2025 (opens the "2026" liturgical
+ year, this task's own civil year) is label 2026, 2026 mod 3 = 1
+ -> A; the civil days immediately before it are still label 2025,
+ 2025 mod 3 = 0 -> C. *)
+ (D.add_days (T.advent_start 2025) (-1), "c", "before Advent 2025 (label 2025)");
+ (T.advent_start 2025, "a", "Advent Sunday 2025 (label 2026)")
+ ]
+ in
+ List.iter
+ (fun (date, expected, label) ->
+ Alcotest.(check string) (label ^ " (" ^ iso date ^ ")") expected
+ (sunday_letter (Lect_of.sunday_cycle ~year_start:T.year_start date)))
+ cases
+
+(* OLM n.69 point 4: Year I odd label years, Year II even. Reuses the SAME
+ Advent-1980/1981/1982 boundaries as the Sunday-cycle table above (label
+ 1980 even -> II, 1981 odd -> I, 1982 even -> II, 1983 odd -> I),
+ straddling Advent I within a single civil year exactly as the Sunday
+ table does. *)
+let test_weekday_cycle_table () =
+ let cases =
+ [ (D.add_days (T.advent_start 1980) (-1), "ii", "before Advent 1980 (label 1980, even)");
+ (T.advent_start 1980, "i", "Advent Sunday 1980 (label 1981, odd)");
+ (D.add_days (T.advent_start 1981) (-1), "i", "before Advent 1981 (label 1981, odd)");
+ (T.advent_start 1981, "ii", "Advent Sunday 1981 (label 1982, even)");
+ (D.add_days (T.advent_start 1982) (-1), "ii", "before Advent 1982 (label 1982, even)");
+ (T.advent_start 1982, "i", "Advent Sunday 1982 (label 1983, odd)");
+ (D.add_days (T.advent_start 2025) (-1), "i", "before Advent 2025 (label 2025, odd)");
+ (T.advent_start 2025, "ii", "Advent Sunday 2025 (label 2026, even)")
+ ]
+ in
+ List.iter
+ (fun (date, expected, label) ->
+ Alcotest.(check string) (label ^ " (" ^ iso date ^ ")") expected
+ (weekday_letter (Lect_of.weekday_cycle ~year_start:T.year_start date)))
+ cases
+
+(* The two cycles are independent computations, not two views of the same
+ number -- Advent 1981 (label 1982) is Sunday-cycle B but weekday-cycle
+ II, a label that is even for one modulus and not reducible to the
+ other. *)
+let test_cycles_are_independent () =
+ let date = T.advent_start 1981 in
+ Alcotest.(check string) "Sunday cycle B" "b" (sunday_letter (Lect_of.sunday_cycle ~year_start:T.year_start date));
+ Alcotest.(check string) "weekday cycle II" "ii"
+ (weekday_letter (Lect_of.weekday_cycle ~year_start:T.year_start date))
+
+(* ---- SHA-256 pins ----------------------------------------------------- *)
+
+let sha256_of_file path =
+ let tmp = Filename.temp_file "colitur_lectionary_of_sha256" ".txt" in
+ let cmd = Printf.sprintf "sha256sum %s > %s" (Filename.quote path) (Filename.quote tmp) in
+ (match Sys.command cmd with
+ | 0 -> ()
+ | n -> Alcotest.failf "sha256sum exited %d" n);
+ let ic = open_in tmp in
+ let line = input_line ic in
+ close_in ic;
+ Sys.remove tmp;
+ match String.split_on_char ' ' line with
+ | hash :: _ -> hash
+ | [] -> Alcotest.fail "sha256sum produced no output"
+
+(* Pinned 2026-08-26 against the shipped file itself, independently
+ re-derived (`sha256sum data/of/lectionary.sexp`), the same "derive the
+ new value, don't transcribe it from generator stdout" discipline
+ test_calendar_of_data.ml's own [test_sha256] already follows. *)
+let test_sha256_pinned () =
+ Alcotest.(check string) "data/of/lectionary.sexp SHA-256"
+ "e7fd109bc30baf8a5531a614995e986959214424c80f4d444fa2b772538decde" (sha256_of_file lectionary_path)
+
+(* lectio's OWN of-lectionary.ini SHA-256, pinned inside data/of/
+ lectionary.sexp's own provenance header (tools/bootstrap_lectionary_of
+ .ml's own emitted "; SHA-256: ..." line for the SOURCE, not the file
+ pinned above) -- checked here as a plain substring of the shipped file,
+ not by re-reading the sibling lectio repository (which need not be
+ present wherever this test runs; the point of pinning it in the header
+ is that this repo alone is then enough to know which snapshot produced
+ it). *)
+let test_source_sha256_pinned_in_header () =
+ let ic = open_in lectionary_path in
+ let n = in_channel_length ic in
+ let content = really_input_string ic n in
+ close_in ic;
+ let needle = "SHA-256: f0b527aef58b93e6ccdfbeafe52b340ed2a9d7d72805bf5083e3da04b080123c" in
+ let contains haystack needle =
+ let hl = String.length haystack and nl = String.length needle in
+ let rec go i = i + nl <= hl && (String.sub haystack i nl = needle || go (i + 1)) in
+ go 0
+ in
+ Alcotest.(check bool) "lectio's of-lectionary.ini SHA-256 is pinned in the provenance header" true
+ (contains content needle)
+
+(* A missing lectio snapshot must fail LOUDLY -- Task 1's own extractor
+ shipped exactly this bug (parse_lectio_ini swallowing FileNotFoundError,
+ silently producing a DIFFERENT file with a different SHA-256 and zero
+ `en` names) and needed a review round to fix; this task's own brief
+ names it explicitly as a trap not to repeat. Exercised here as a real
+ subprocess run, not merely by reading the generator's source: invokes
+ the built tools/bootstrap_lectionary_of.exe against a path that does
+ not exist and asserts BOTH a non-zero exit AND that no output file was
+ written (a generator that failed loudly but left a partial/stale
+ destination file behind would be only half fixed). *)
+let test_missing_source_fails_loudly () =
+ let exe = "../tools/bootstrap_lectionary_of.exe" in
+ let bogus_src = Filename.temp_file "colitur_lectionary_of_missing" ".ini" in
+ Sys.remove bogus_src;
+ (* guaranteed not to exist, still a plausible-looking path *)
+ let dst = Filename.temp_file "colitur_lectionary_of_dst" ".sexp" in
+ Sys.remove dst;
+ let log = Filename.temp_file "colitur_lectionary_of_stderr" ".txt" in
+ let cmd =
+ Printf.sprintf "%s %s %s >%s 2>&1" (Filename.quote exe) (Filename.quote bogus_src) (Filename.quote dst)
+ (Filename.quote log)
+ in
+ let status = Sys.command cmd in
+ let ic = open_in log in
+ let n = in_channel_length ic in
+ let stderr_text = really_input_string ic n in
+ close_in ic;
+ Sys.remove log;
+ Alcotest.(check bool) "non-zero exit on a missing source file" true (status <> 0);
+ Alcotest.(check bool) "no output file written" false (Sys.file_exists dst);
+ Alcotest.(check bool) "error message names the missing path and explains why this matters" true
+ (let contains haystack needle =
+ let hl = String.length haystack and nl = String.length needle in
+ let rec go i = i + nl <= hl && (String.sub haystack i nl = needle || go (i + 1)) in
+ go 0
+ in
+ contains stderr_text "no such file" && contains stderr_text bogus_src)
+
+(* ---- basic load ------------------------------------------------------- *)
+
+let test_load () =
+ let l = real_lectionary () in
+ Alcotest.(check int) "754 entries" 754 (List.length (Lectionary.entries l))
+
+(* ---- coverage: a full sample civil year, both directions, PINNED ------ *)
+
+(* Civil year 2026 -- the same year this task's data file's own coverage
+ report uses. Iterates every day, resolving readings the same
+ approximate way [readings_on] does (see this file's own top-of-file
+ comment), and asserts BOTH the total resolved count AND the exact,
+ named set of unresolved dates -- never a silent zero (task brief's own
+ Step 4 requirement). *)
+let all_days_of_2026 =
+ let days_in_month = [| 31; 28; 31; 30; 31; 30; 31; 31; 30; 31; 30; 31 |] in
+ List.concat
+ (List.init 12 (fun mi ->
+ let m = mi + 1 in
+ List.init days_in_month.(mi) (fun di -> d 2026 m (di + 1))))
+
+let test_coverage_2026 () =
+ let lectionary = real_lectionary () in
+ let layer = real_sanctoral_layer () in
+ let index = L.index layer ~easter:Computus.gregorian_easter ~years:[ 2025; 2026 ] in
+ let unresolved =
+ List.filter_map
+ (fun date ->
+ match readings_on lectionary index date with
+ | None, [] -> Some (iso date)
+ | Some _, (_ :: _) -> None
+ | (Some _, []) | (None, _ :: _) ->
+ Alcotest.failf "%s: Mass_formulary.t and citations disagree on whether readings resolved"
+ (iso date))
+ all_days_of_2026
+ in
+ Alcotest.(check int) "365 days in 2026" 365 (List.length all_days_of_2026);
+ (* The ONE genuine gap this task's own bootstrap found and named: lectio's
+ 988 keys never include a Christmas DAY Mass (only the Vigil) -- see
+ data/of/lectionary.sexp's own provenance header and
+ tools/bootstrap_lectionary_of.ml's own [named_overrides] comment on
+ "christmas". Pinned as a NAMED set, not a bare count: a silent zero
+ here is exactly the failure mode the task brief warns against. *)
+ Alcotest.(check (list string)) "the unresolved-day set is exactly {25 December}" [ "2026-12-25" ] unresolved;
+ Alcotest.(check int) "364 of 365 days resolve readings" 364 (365 - List.length unresolved)
+
+(* Same measurement, restated as "how many days resolve" rather than "how
+ many don't" -- redundant with the count above by construction, kept
+ because Step 4's own brief asks for a pinned resolved-count assertion
+ specifically, not only its complement. *)
+let test_pinned_resolved_count () =
+ let lectionary = real_lectionary () in
+ let layer = real_sanctoral_layer () in
+ let index = L.index layer ~easter:Computus.gregorian_easter ~years:[ 2025; 2026 ] in
+ let resolved =
+ List.length
+ (List.filter
+ (fun date -> match readings_on lectionary index date with Some _, _ :: _ -> true | _ -> false)
+ all_days_of_2026)
+ in
+ Alcotest.(check int) "364 days resolve readings in 2026" 364 resolved
+
+(* ---- resolution chain: unit-level spot checks -------------------------- *)
+
+(* Step 3: an ordinary Ordinary Time weekday with no sanctoral entry
+ resolves via its own temporal slug, cycle-selected. 16 June 2026 is a
+ Tuesday of Ordinary Time, in the SECOND (post-Pentecost) block, with no
+ calendar-2002.sexp/amendments entry (checked against the real merged
+ layer, not assumed, and clear of the three nearby movable solemnities
+ -- Corpus Christi 4 June, Sacred Heart 12 June, Immaculate Heart 13
+ June). The expected slug is read off Temporal_of.temporal itself, not
+ hand-computed: the second block's own week arithmetic (temporal_of.ml's
+ own [ordinary_time_week]) is counted BACKWARDS from Christ the King, not
+ forwards from the Baptism -- re-deriving that by hand here would just
+ duplicate the one calculation this test exists to exercise, not check
+ it independently. *)
+let test_step3_temporal_ferial () =
+ let lectionary = real_lectionary () in
+ let layer = real_sanctoral_layer () in
+ let index = L.index layer ~easter:Computus.gregorian_easter ~years:[ 2025; 2026 ] in
+ let date = d 2026 6 16 in
+ Alcotest.(check bool) "16 June 2026: no sanctoral entry" true (L.on_date index date = []);
+ let expected_slug = (T.temporal date).Colitur_kernel.Temporal.office.Cel.slug in
+ match readings_on lectionary index date with
+ | Some fm, (_ :: _ as cs) ->
+ Alcotest.(check bool) "tagged Own_slug" true (fm.Mass_formulary.via = Mass_formulary.Own_slug);
+ Alcotest.(check (option string)) "said the temporal slug" (Some (Slug.to_string expected_slug))
+ (Option.map Slug.to_string fm.Mass_formulary.said);
+ Alcotest.(check int) "two citations (First + Gospel)" 2 (List.length cs)
+ | _ -> Alcotest.fail "16 June 2026 should resolve readings via step 3"
+
+(* Step 2: a sanctoral saint who won the day resolves via his own slug, not
+ the temporal ferial's. 30 November 2026 is a Monday of Advent week 1
+ (which would otherwise be "of-advent-1-monday") but is also St Andrew
+ the Apostle's own fixed date. *)
+let test_step2_sanctoral_wins () =
+ let lectionary = real_lectionary () in
+ let layer = real_sanctoral_layer () in
+ let index = L.index layer ~easter:Computus.gregorian_easter ~years:[ 2025; 2026 ] in
+ let date = d 2026 11 30 in
+ (match L.on_date index date with
+ | [ e ] -> Alcotest.(check string) "St Andrew's own entry" "andrew-the-apostle" (Slug.to_string e.L.cel.Cel.slug)
+ | es -> Alcotest.failf "expected exactly one sanctoral entry on 30 Nov 2026, got %d" (List.length es));
+ match readings_on lectionary index date with
+ | Some fm, (_ :: _ as cs) ->
+ Alcotest.(check bool) "tagged Proper" true (fm.Mass_formulary.via = Mass_formulary.Proper);
+ Alcotest.(check (option string)) "said Andrew's own slug" (Some "andrew-the-apostle")
+ (Option.map Slug.to_string fm.Mass_formulary.said);
+ (* "of-advent-1-monday" is FLAT, not cycle-lettered (OLM n.69 point 3:
+ Advent's own ferias do not change year to year -- confirmed by
+ this generator's own collapse, tools/bootstrap_lectionary_of.ml's
+ [collapse_weekday]), so there is exactly one temporal citation
+ set to compare against, not two. *)
+ Alcotest.(check bool) "NOT the temporal ferial's Advent citations" true
+ (cs <> Option.get (Lectionary.find lectionary (Slug.of_string_exn "of-advent-1-monday")))
+ | _ -> Alcotest.fail "30 November 2026 should resolve readings via step 2"
+
+let suite =
+ [ Alcotest.test_case "Sunday cycle table (OLM n.66, straddles Advent I)" `Quick test_sunday_cycle_table;
+ Alcotest.test_case "weekday cycle table (OLM n.69.4, straddles Advent I)" `Quick test_weekday_cycle_table;
+ Alcotest.test_case "the two cycles are independent" `Quick test_cycles_are_independent;
+ Alcotest.test_case "data/of/lectionary.sexp SHA-256 pinned" `Quick test_sha256_pinned;
+ Alcotest.test_case "lectio source SHA-256 pinned in the header" `Quick test_source_sha256_pinned_in_header;
+ Alcotest.test_case "a missing lectio source fails loudly, not silently" `Quick test_missing_source_fails_loudly;
+ Alcotest.test_case "loads, 754 entries" `Quick test_load;
+ Alcotest.test_case "2026 coverage: exactly {25 December} unresolved" `Quick test_coverage_2026;
+ Alcotest.test_case "2026 coverage: 364 days resolve" `Quick test_pinned_resolved_count;
+ Alcotest.test_case "step 3: temporal ferial fallback" `Quick test_step3_temporal_ferial;
+ Alcotest.test_case "step 2: sanctoral proper wins over the ferial" `Quick test_step2_sanctoral_wins
+ ]
diff --git a/tools/bootstrap_lectionary_of.ml b/tools/bootstrap_lectionary_of.ml
new file mode 100644
index 0000000..f521bb1
--- /dev/null
+++ b/tools/bootstrap_lectionary_of.ml
@@ -0,0 +1,827 @@
+(* Bootstraps data/of/lectionary.sexp from lectio's of-lectionary.ini
+ (Task 4, 2026-08-25-colitur-of-phases-3-5). Lives in tools/, OCaml, not
+ Python -- deliberately: this task's own brief named
+ tools/extract_of_lectionary.py, but tools/bootstrap_lectionary.ml
+ already IS the established shape for exactly this job (EF's own
+ lectionary bootstrap), including a real, load-bearing safety net --
+ [assert_reachable] below sweeps Rite_of.Temporal_of.temporal AND the
+ real merged sanctoral layer directly, so a mapping-table typo cannot
+ ship a dead key silently. Reimplementing that check in Python would mean
+ duplicating colitur's own date arithmetic in a second language, exactly
+ the drift risk this generator exists to avoid. Named to match the
+ OF-specific sibling convention (temporal_of.ml, precedence_of.ml), not
+ bootstrap_lectionary.ml's own bare name, since a second rite needs a
+ second, distinguishable generator.
+
+ THE LINEAGE, stated once, here, because every downstream comment and the
+ emitted file's own header both lean on it: lectio's of-lectionary.ini
+ says of itself (its own top-of-file comment) that it is "Generated from
+ niedziela.pl by scripts/genlect-of.go (harvest 2020-2025)". niedziela.pl
+ is a POLISH VERNACULAR pastoral lectionary aid, not the Latin OLM
+ (Ordo Lectionum Missae) 1981 itself, and its own citations are, per the
+ design spec (2026-08-24-colitur-of-rite-module-design.md sec4.4),
+ ENGLISH-CANONICAL (English book names/verse numbering), not the OLM's
+ Vulgate-numbered Latin. THIS IS A SEPARATE LINEAGE from lectio's OF
+ CALENDAR (data/of/calendar-2002.sexp, roman-calendar.ini, upstream
+ calapi.inadiutorium.cz) -- lectio is not one OF witness but two,
+ unrelated upstreams glued together by one downstream project, and
+ neither is the typical edition. What this data CANNOT show: any
+ divergence between niedziela.pl's own pastoral choices and the Latin
+ OLM's own text (verse-range short/long forms, alternative readings,
+ Vulgate-vs-Nova-Vulgata numbering -- the design spec's own sec4.4 records
+ three real, confirmed such divergences against the actual OLM page
+ images: Holy Family Year A's second-reading short form, Trinity Sunday's
+ Dan 3:56, and the Baptism of the Lord's Mc 9:6 vs "Mark 9:7"); nor can it
+ show anything about the OLM's SHORT-FORM/LONG-FORM alternatives, which
+ niedziela.pl does not distinguish. This generator does not attempt to
+ correct any of that -- it transcribes the vernacular data faithfully,
+ states the lineage loudly, and lets a future task with the actual OLM
+ page images (docs/research/of/olm-1981.pdf) do primary-source
+ verification the way tools/bootstrap_lectionary.ml's own Holy Week
+ entries did for EF. *)
+open Colitur_kernel
+
+let default_source = "../lectio/internal/caldata/of-lectionary.ini"
+let default_dest = "data/of/lectionary.sexp"
+
+let die fmt =
+ Printf.ksprintf
+ (fun s -> prerr_endline ("bootstrap_lectionary_of: " ^ s); exit 1)
+ fmt
+
+(* ---- INI parsing --------------------------------------------------- *)
+
+type section = { name : string; fields : (string * string) list }
+
+(* Fails loudly, not silently, when the source file is absent -- Task 1's
+ own review found exactly this bug in the calendar extractor
+ (parse_lectio_ini swallowing FileNotFoundError, producing a DIFFERENT
+ file with a different SHA-256 and no warning): checked BEFORE any read
+ is attempted, and the [open_in] itself is also guarded as defence in
+ depth, mirroring tools/bootstrap_lectionary.ml's own [parse_ini]. *)
+let parse_ini path =
+ if not (Sys.file_exists path) then
+ die "%s: no such file (a missing lectio snapshot must fail loudly, not \
+ silently regenerate with a different SHA-256 and no warning -- Task 1's \
+ own review round found exactly this bug)"
+ path;
+ let ic = try open_in path with Sys_error e -> die "%s" e in
+ let sections = ref [] and cur = ref None and malformed = ref [] and lineno = ref 0 in
+ let flush () =
+ match !cur with
+ | Some (n, fs) -> sections := { name = n; fields = List.rev fs } :: !sections
+ | None -> ()
+ in
+ (try
+ while true do
+ incr lineno;
+ let raw = input_line ic in
+ let line = String.trim raw in
+ if line = "" || line.[0] = ';' || line.[0] = '#' then ()
+ else if line.[0] = '[' then begin
+ flush ();
+ cur := Some (String.sub line 1 (String.length line - 2), [])
+ end
+ else
+ let known_key k = List.mem k [ "first"; "psalm"; "second"; "gospel" ] in
+ match String.index_opt line '=' with
+ | Some i when known_key (String.trim (String.sub line 0 i)) ->
+ let k = String.trim (String.sub line 0 i) in
+ let v = String.trim (String.sub line (i + 1) (String.length line - i - 1)) in
+ cur :=
+ (match !cur with
+ | Some (n, fs) -> Some (n, (k, v) :: fs)
+ | None -> die "%s:%d: field %S before any section" path !lineno k)
+ | Some _ | None ->
+ (* Known, single, understood anomaly (see the assertion below):
+ line 1276 of the shipped snapshot, inside [holy-family-A],
+ reads bare "=Sir3:2-6,12-14-Gk" -- an EMPTY key, not "no
+ '=' sign" (an earlier version of this parser tested for the
+ latter and missed this line entirely, since [String.
+ index_opt] DOES find the '=' at position 0; a key must now
+ be one of the four known field names, checked explicitly).
+ This is the Polish lectionary's own Septuagint/Greek-
+ numbering variant for Sirach 3 (design spec sec5's own
+ "Polish is independent on one point": Syr 3,2-6.12-14
+ against the OLM/CEI/USA table's shared Nova Vulgata
+ 3,3-7.14-17a), evidently emitted by niedziela.pl's own
+ scraper as a stray annotation rather than a proper
+ "first_alt = ..." field. Recorded, not silently dropped:
+ every such line is collected and the count is asserted
+ below, so a NEW malformed line in a future lectio snapshot
+ still fails loudly rather than being quietly absorbed by
+ this same tolerance. *)
+ malformed := (!lineno, line) :: !malformed
+ done
+ with End_of_file -> ());
+ flush ();
+ close_in ic;
+ (match List.rev !malformed with
+ | [ (1276, "=Sir3:2-6,12-14-Gk") ] -> ()
+ | [] -> die "%s: expected exactly one known malformed line (1276, the Sirach \
+ Septuagint-numbering annotation) but found none -- either the \
+ snapshot changed or this tolerance is now dead code; re-check \
+ by hand before touching this assertion" path
+ | other ->
+ List.iter (fun (n, l) -> Printf.eprintf " line %d: %S\n" n l) other;
+ die "%s: %d unparseable line(s) found, not the one previously-known \
+ anomaly (see above) -- investigate before shipping; a new \
+ malformed line must be understood, not silently swallowed"
+ path (List.length other));
+ List.rev !sections
+
+(* ---- Citation extraction -- First + Gospel only --------------------- *)
+
+(* Psalm and Second are deliberately dropped, even though lectio's ini
+ carries [psalm] (every entry) and [second] (Sundays/solemnities):
+ Colitur_kernel.Validate's own ["citations"] check (kernel, off limits to
+ this task) hard-asserts every day's citation-part list is EXACTLY
+ [[First; Gospel]] -- the identical scope boundary
+ tools/bootstrap_lectionary.ml's own [convert] already holds for EF
+ ("Nothing here encodes... the chants (Psalm, Second, Tract, Alleluia,
+ Sequence) are deliberately unbuilt"). Carrying Psalm/Second through here
+ would not add capability today (nothing reads them) and would set up a
+ guaranteed collision with that kernel check the moment a future task
+ wires Validate over OF data. *)
+let cite sec =
+ let get k = match List.assoc_opt k sec.fields with None | Some "" -> None | Some v -> Some v in
+ match (get "first", get "gospel") with
+ | Some first, Some gospel ->
+ Some [ { Citation.part = Citation.First; reference = first };
+ { Citation.part = Citation.Gospel; reference = gospel } ]
+ | _ -> None
+
+(* ---- Cycle-family grouping ------------------------------------------ *)
+
+(* Every one of the 988 sections carries a cycle suffix: -A/-B/-C (Sunday
+ cycle, 102 bases x 3 = 306) or -I/-II (weekday cycle, 341 bases x up to
+ 2 = up to 682; two bases are short one cycle -- see
+ [collapse_weekday] below). Measured exhaustively before writing this
+ generator: no section carries any OTHER suffix, and no base name
+ appears in both groups. *)
+let strip_suffix ~suffix s =
+ let ls = String.length s and lsuf = String.length suffix in
+ if ls > lsuf && String.sub s (ls - lsuf) lsuf = suffix then
+ Some (String.sub s 0 (ls - lsuf))
+ else None
+
+let base_and_letter name =
+ match strip_suffix ~suffix:"-A" name with
+ | Some b -> Some (b, `A)
+ | None -> (
+ match strip_suffix ~suffix:"-B" name with
+ | Some b -> Some (b, `B)
+ | None -> (
+ match strip_suffix ~suffix:"-C" name with
+ | Some b -> Some (b, `C)
+ | None -> (
+ match strip_suffix ~suffix:"-II" name with
+ | Some b -> Some (b, `II)
+ | None -> (
+ match strip_suffix ~suffix:"-I" name with
+ | Some b -> Some (b, `I)
+ | None -> None))))
+
+type resolved =
+ | Flat of Citation.t list (* cycle-independent: one citation set for every year *)
+ | Sunday_cycle of (Citation.t list * Citation.t list * Citation.t list) (* A, B, C *)
+ | Weekday_cycle of (Citation.t list option * Citation.t list option) (* I, II -- either may be absent *)
+
+(* Sunday-cycle collapse: mechanical, not curated per-saint. Measured
+ across all 102 bases before this generator existed: 43 are byte-
+ identical across A/B/C (routine -- a fixed-date saint's own Mass simply
+ does not vary by year, e.g. andrew-the-apostle); 57 are genuinely
+ distinct on all three letters (real OLM n.66 three-year-cycle content --
+ every numbered Sunday, plus the handful of movable/fixed solemnities of
+ the Lord whose OWN Gospel varies by year: Holy Family, Baptism of the
+ Lord, Ascension, Corpus Christi, Christ the King, Trinity, Sacred Heart,
+ Transfiguration); and EXACTLY 2 have a clean 2-of-3 majority with the
+ third an unrelated passage from a DIFFERENT day entirely --
+ annunciation-of-the-lord (B is Monday of Holy Week's own Mass,
+ Isa 42:1-7/John 12:1-11 -- a scraping-year artifact: the Annunciation
+ was genuinely impeded and transferred that harvest year, so
+ niedziela.pl's site had Holy Week's Mass on 25 March instead) and
+ immaculate-conception-of-the-blessed-virgin-mary (A is Isa 35:1-10/
+ Luke 5:17-26, an ordinary Lenten-feria Gospel, the same shape). Both
+ solemnities are, in real practice, NOT cycle-dependent at all (single
+ Mass every year) -- corroborated externally by the "2 of 3 agree, none
+ of the 57 genuine cases exhibit that shape" measurement itself, not
+ merely asserted -- so majority-collapse is applied, and the discarded
+ outlier is logged. No other base in the whole 102-base population has
+ this 2-of-3 shape; the rule is general, not hand-targeted at these two
+ names. *)
+let collapse_sunday base va vb vc =
+ if va = vb && vb = vc then Flat va
+ else if va = vb then begin
+ Printf.eprintf
+ "bootstrap_lectionary_of: %s: cycle C disagreed with A/B (scraping-year \
+ artifact, majority kept): %s\n"
+ base (match vc with [ f; _ ] -> f.Citation.reference | _ -> "?");
+ Flat va
+ end
+ else if va = vc then begin
+ Printf.eprintf
+ "bootstrap_lectionary_of: %s: cycle B disagreed with A/C (scraping-year \
+ artifact, majority kept): %s\n"
+ base (match vb with [ f; _ ] -> f.Citation.reference | _ -> "?");
+ Flat va
+ end
+ else if vb = vc then begin
+ Printf.eprintf
+ "bootstrap_lectionary_of: %s: cycle A disagreed with B/C (scraping-year \
+ artifact, majority kept): %s\n"
+ base (match va with [ f; _ ] -> f.Citation.reference | _ -> "?");
+ Flat vb
+ end
+ else Sunday_cycle (va, vb, vc)
+
+(* Weekday-cycle collapse: same mechanical byte-identity test. OLM 1981
+ Praenotanda n.69 points 2-3 (page-image verified,
+ docs/research/of/olm-1981.pdf p.33/"XXXIII") state that Lent has its own
+ fixed seasonal cycle and Advent/Christmastide/Paschaltide ferias "do not
+ change" year to year -- exactly the byte-identical shape measured for
+ those families (advent-1/2/3, advent-dec-17..24, lent-after-ashes-*,
+ holy-week-*, easter-octave-*: 119 of 341 bases). Point 4 confines the
+ REAL two-year alternation to Ordinary Time's 34 weeks, and even there
+ only the FIRST reading alternates -- the Gospel is one single,
+ year-independent cycle (n.69 point 4: "lectiones evangelicae unico
+ disponuntur cyclo... Prior vero lectio, in duplici cyclo ordinatur") --
+ which is exactly why 198 of the 221 non-identical bases still share a
+ common Gospel with only the First Reading differing: real content, kept
+ as two entries because the FULL pair genuinely differs, not a scraping
+ artifact (unlike the two Sunday-cycle cases above, no base in this group
+ showed a "majority of one, unrelated outlier" shape). *)
+let collapse_weekday base v1 v2 =
+ match (v1, v2) with
+ | Some a, Some b when a = b -> Flat a
+ | Some _, Some _ -> Weekday_cycle (v1, v2)
+ | Some _, None | None, Some _ ->
+ Printf.eprintf
+ "bootstrap_lectionary_of: %s: only one weekday-cycle year present in \
+ lectio's own snapshot (a real gap in niedziela.pl's 2020-2025 harvest, \
+ not a parsing defect) -- transcribed as-is\n"
+ base;
+ Weekday_cycle (v1, v2)
+ | None, None -> die "%s: cycle collapse called with no data" base
+
+let resolve_sections secs =
+ let tbl = Hashtbl.create 1024 in
+ List.iter
+ (fun sec ->
+ match base_and_letter sec.name with
+ | None -> die "%s: no recognised cycle suffix (-A/-B/-C/-I/-II)" sec.name
+ | Some (base, letter) -> (
+ match cite sec with
+ | None -> die "%s: no first/gospel field" sec.name
+ | Some cs ->
+ let cur = try Hashtbl.find tbl base with Not_found -> (None, None, None, None, None) in
+ let a, b, c, i, ii = cur in
+ let updated =
+ match letter with
+ | `A -> (Some cs, b, c, i, ii)
+ | `B -> (a, Some cs, c, i, ii)
+ | `C -> (a, b, Some cs, i, ii)
+ | `I -> (a, b, c, Some cs, ii)
+ | `II -> (a, b, c, i, Some cs)
+ in
+ Hashtbl.replace tbl base updated))
+ secs;
+ Hashtbl.fold
+ (fun base (a, b, c, i, ii) acc ->
+ match (a, b, c, i, ii) with
+ | Some va, Some vb, Some vc, None, None -> (base, collapse_sunday base va vb vc) :: acc
+ | None, None, None, i, ii when i <> None || ii <> None ->
+ (base, collapse_weekday base i ii) :: acc
+ | Some va, Some vb, Some vc, i, ii when i <> None || ii <> None ->
+ (* A real, measured duplicate in lectio's own source, confined
+ (checked below by this generator's own exhaustive Hashtbl.fold)
+ to the six Easter Octave weekdays: each carries BOTH an
+ -A/-B/-C section AND an -I/-II one, evidently written by two
+ different passes of niedziela.pl's own generation pipeline.
+ Content-verified identical in substance (Acts 2:14,22-32/33,
+ Ps 16, Matt 28:8-15 -- "Acts"/"The Acts" and "Mat"/"Matthew"
+ spelling differ, the citation does not), and each of the two
+ representations is ALSO internally self-consistent
+ (A=B=C, I=II) on its own -- so this is redundancy, not a real
+ conflict. The -A/-B/-C reading is kept (it is what this
+ generator's own [named_overrides] table for these six bases
+ already targets); the -I/-II reading is discarded, logged
+ here rather than silently dropped. *)
+ Printf.eprintf
+ "bootstrap_lectionary_of: %s: BOTH Sunday- and weekday-cycle data present \
+ (a genuine lectio duplicate, not a defect -- see the comment on this branch); \
+ keeping the Sunday-cycle (A/B/C) reading, discarding the weekday-cycle (I/II) one\n"
+ base;
+ (base, collapse_sunday base va vb vc) :: acc
+ | _ ->
+ die "%s: mixed or incomplete cycle data (a=%b b=%b c=%b i=%b ii=%b)" base (a <> None)
+ (b <> None) (c <> None) (i <> None) (ii <> None))
+ tbl []
+
+(* ---- colitur slug mapping -------------------------------------------- *)
+
+let weekday_pairs =
+ (* (colitur full word, lectio abbreviation) *)
+ [ ("monday", "mon"); ("tuesday", "tue"); ("wednesday", "wed"); ("thursday", "thu");
+ ("friday", "fri"); ("saturday", "sat") ]
+
+let split_dash s = String.split_on_char '-' s
+
+(* (colitur season word, lectio season word, max week number) -- ferial
+ families. Min week is always 1. Week 6 of Lent (Holy Week) and week 1 of
+ Easter (the Octave) are deliberately excluded from this generic table --
+ both have their own named families, handled in [special_overrides]. *)
+let ferial_families =
+ [ ("advent", "advent", 4); ("lent", "lent", 5); ("easter", "easter", 7);
+ ("ordinary-time", "ordinary", 34) ]
+
+(* Easter's own numbered Sunday family runs 3..7 in lectio (2 is the
+ separately-named "easter-octave-sun", see [named_overrides]) but the
+ upper bound here is deliberately still a loose "any n >= 1" check (see
+ [pattern_match]'s own guard) -- lectio simply never emits an
+ "easter-sunday-1"/"-2" base for this family to collide with. *)
+let sunday_families =
+ [ ("advent", "advent", 4); ("lent", "lent", 5); ("easter", "easter", 7);
+ ("ordinary-time", "ordinary", 33) ]
+
+(* A base that pattern-matches a numbered ferial or Sunday family. Returns
+ the colitur slug directly. *)
+let pattern_match base =
+ match split_dash base with
+ | [ w; "sunday"; n ] -> (
+ match (List.find_opt (fun (_, lw, _) -> lw = w) sunday_families, int_of_string_opt n) with
+ | Some (cw, _, max_n), Some ni when ni >= 1 && ni <= max_n ->
+ Some (Printf.sprintf "of-%s-sunday-%d" cw ni)
+ | _ -> None)
+ | [ w; n; wd ] -> (
+ match
+ ( List.find_opt (fun (_, lw, _) -> lw = w) ferial_families,
+ int_of_string_opt n,
+ List.find_opt (fun (_, la) -> la = wd) weekday_pairs )
+ with
+ | Some (cw, _, max_n), Some ni, Some (full_wd, _) when ni >= 1 && ni <= max_n ->
+ Some (Printf.sprintf "of-%s-%d-%s" cw ni full_wd)
+ | _ -> None)
+ | _ -> None
+
+(* Named-day and irregular-family renames -- everything [pattern_match]
+ above cannot reach because colitur's own slug uses a DIFFERENT word, a
+ DIFFERENT numbering scheme, or (the Christmas-season families) the SAME
+ weekday-keyed scheme lectio happens to expose under a differently-named
+ family. Each entry cites the content verification that justified it,
+ not merely the name resemblance -- three of these (christmas,
+ christmas-sunday-sun, easter-octave-sun) would have been WRONG if
+ matched by name alone; see the comment on each. *)
+let named_overrides =
+ [ (* Content-verified against the real reading (Isa 62:1-5/Matt 1:18-25,
+ the genealogy/annunciation-to-Joseph narrative): this is the VIGIL
+ Mass, not "Christmas Day" despite the bare name -- the real Christmas
+ DAY Mass (Isa 52:7-10/John 1:1-14) is ABSENT from lectio's own 988
+ keys entirely, a genuine, notable gap (see the generator's own
+ coverage report). *)
+ ("christmas", [ "of-nativity-vigil" ]);
+ (* Content-verified (Sirach 24 Wisdom-personified / Eph 1 / John 1:1-18):
+ this is the SECOND SUNDAY AFTER THE NATIVITY (Normae n.36), not a
+ generic "the Sunday of Christmas" despite the bare name -- Holy
+ Family (a DIFFERENT Sunday, Normae n.35(a)) has its own "holy-family"
+ base, mapped just below. *)
+ ("christmas-sunday-sun", [ "of-christmas-sunday-2" ]);
+ ("mary-mother-of-god-octave-of-christmas", [ "of-mary-mother-of-god" ]);
+ (* Content-verified (Joel 2:12-18/Matt 6:1-6,16-18, THE Ash Wednesday
+ Mass): lectio groups Ash Wednesday itself into this weekday-cycle
+ family rather than giving it a bare "ash-wednesday" key. Its own
+ three siblings (Thursday/Friday/Saturday right after Ash
+ Wednesday) are plain ferias, matched by the SAME family, needing
+ only the word rename ("lent-after-ashes" -> "of-lent-after-ashes")
+ [pattern_match] cannot supply on its own (it is not a numbered
+ week). *)
+ ("lent-after-ashes-wed", [ "of-ash-wednesday" ]);
+ ("lent-after-ashes-thu", [ "of-lent-after-ashes-thursday" ]);
+ ("lent-after-ashes-fri", [ "of-lent-after-ashes-friday" ]);
+ ("lent-after-ashes-sat", [ "of-lent-after-ashes-saturday" ]);
+ ("trinity-sunday", [ "of-trinity" ]);
+ (* Content-verified (John 20:19-31, the Divine Mercy Gospel): the
+ Sunday CLOSING the Easter Octave, colitur's own generic
+ week-2-of-Easter Sunday slug, not a second distinct office. *)
+ ("easter-octave-sun", [ "of-easter-sunday-2" ]);
+ (* The remaining single- or compound-word NAMED temporal days
+ (Temporal_of.named/[temporal]'s own Sunday branches): colitur's own
+ slug is simply "of-" prepended to lectio's own bare name, verified
+ against temporal_of.ml directly rather than assumed -- these are
+ NOT reachable by pass-through (pass-through checks the SANCTORAL
+ layer only, and none of these is sanctoral data). *)
+ ("epiphany", [ "of-epiphany" ]);
+ ("palm-sunday", [ "of-palm-sunday" ]);
+ ("easter-sunday", [ "of-easter-sunday" ]);
+ ("ascension", [ "of-ascension" ]);
+ ("pentecost", [ "of-pentecost" ]);
+ ("baptism-of-the-lord", [ "of-baptism-of-the-lord" ]);
+ ("christ-the-king", [ "of-christ-the-king" ]);
+ ("corpus-christi", [ "of-corpus-christi" ]);
+ ("holy-family", [ "of-holy-family" ]);
+ (* Sacred Heart is SANCTORAL data (calendar-2002.sexp, Easter_offset 68
+ -- F-HEARTS finding, this plan's Task 1), not a Temporal_of slug, and
+ its colitur slug carries "-of-jesus" that lectio's bare "sacred-heart"
+ does not. *)
+ ("sacred-heart", [ "sacred-heart-of-jesus" ]);
+ (* Holy Week Monday-Wednesday and the Triduum: colitur's own
+ Temporal_of deliberately does NOT name these days (Lent's own
+ generic week-6 ferial slug covers them, see temporal_of.ml's own
+ [season] function -- Lent runs "through Holy Saturday inclusive").
+ lectio names them by a WEEKDAY family lectio itself calls
+ "holy-week"/"triduum" rather than "lent-6". *)
+ ("holy-week-mon", [ "of-lent-6-monday" ]);
+ ("holy-week-tue", [ "of-lent-6-tuesday" ]);
+ ("holy-week-wed", [ "of-lent-6-wednesday" ]);
+ ("triduum-thu", [ "of-lent-6-thursday" ]);
+ ("triduum-fri", [ "of-lent-6-friday" ]);
+ ("triduum-sat", [ "of-lent-6-saturday" ]);
+ (* Easter Octave weekdays: colitur names these directly
+ (of-easter-octave-day-N, Monday=2..Saturday=7 -- temporal_of.ml's
+ own [named], "Easter Sunday (above) plus these six"). *)
+ ("easter-octave-mon", [ "of-easter-octave-day-2" ]);
+ ("easter-octave-tue", [ "of-easter-octave-day-3" ]);
+ ("easter-octave-wed", [ "of-easter-octave-day-4" ]);
+ ("easter-octave-thu", [ "of-easter-octave-day-5" ]);
+ ("easter-octave-fri", [ "of-easter-octave-day-6" ]);
+ ("easter-octave-sat", [ "of-easter-octave-day-7" ]);
+ (* The three Christmas-season ferial stretches
+ (Temporal_of.christmas_feria_slug's own three "of-christmas-{0,1,2}-
+ <weekday>" stretches, 26-31 Dec / 2-5 Jan / 7 Jan..pre-Baptism) are
+ WEEKDAY-keyed on colitur's side. lectio exposes THREE separate
+ weekday-keyed families that line up with them one-for-one, under
+ names that do not textually resemble colitur's own -- matched here
+ by CONTENT/POSITION, not by name:
+ - "christmas-octave-<wd>" (1 John/John 1, the Octave itself, 26-31
+ Dec) -> stretch 0.
+ - "christmas-<wd>" bare, no "-octave-"/"-dec-"/"-jan-" (1 John
+ 2-3/John 1:29-51, the semi-continuous reading BETWEEN the Octave
+ and Epiphany, 2-5 Jan) -> stretch 1.
+ - "christmas-after-epiphany-<wd>" (7 Jan..Baptism) -> stretch 2.
+ lectio ALSO carries "christmas-dec-29/30/31" and "christmas-jan-
+ 2..7", a DATE-keyed duplicate of the same stretches -- deliberately
+ UNUSED (see [excluded_bases] below): colitur's own slugs are
+ weekday-keyed, not date-keyed, so a fixed civil date such as
+ "29 December" is not any single colitur slug -- it is a DIFFERENT
+ weekday (hence a different of-christmas-0-<weekday>) in different
+ years, and Lectionary.t has no per-date lookup at all. *)
+ ("christmas-octave-mon", [ "of-christmas-0-monday" ]);
+ ("christmas-octave-tue", [ "of-christmas-0-tuesday" ]);
+ ("christmas-octave-wed", [ "of-christmas-0-wednesday" ]);
+ ("christmas-octave-thu", [ "of-christmas-0-thursday" ]);
+ ("christmas-octave-fri", [ "of-christmas-0-friday" ]);
+ ("christmas-octave-sat", [ "of-christmas-0-saturday" ]);
+ ("christmas-mon", [ "of-christmas-1-monday" ]);
+ ("christmas-tue", [ "of-christmas-1-tuesday" ]);
+ ("christmas-wed", [ "of-christmas-1-wednesday" ]);
+ ("christmas-thu", [ "of-christmas-1-thursday" ]);
+ ("christmas-fri", [ "of-christmas-1-friday" ]);
+ ("christmas-sat", [ "of-christmas-1-saturday" ]);
+ ("christmas-after-epiphany-mon", [ "of-christmas-2-monday" ]);
+ ("christmas-after-epiphany-tue", [ "of-christmas-2-tuesday" ]);
+ ("christmas-after-epiphany-wed", [ "of-christmas-2-wednesday" ]);
+ ("christmas-after-epiphany-thu", [ "of-christmas-2-thursday" ]);
+ ("christmas-after-epiphany-fri", [ "of-christmas-2-friday" ]);
+ ("christmas-after-epiphany-sat", [ "of-christmas-2-saturday" ])
+ ]
+
+(* Deliberately unmapped, with the reason named -- see [named_overrides]'s
+ own comment on the Christmas-season families for the date-vs-weekday
+ mismatch these two groups share:
+
+ - "advent-dec-17".."advent-dec-24": the O-Antiphon days. colitur's own
+ Temporal_of has no per-date slug for late Advent at all (Temporal_ef's
+ EF counterpart doesn't either); these ferias fall through to the
+ ordinary week-numbered "of-advent-{3,4}-<weekday>" slug, and WHICH
+ weekday-string a given December date is varies year to year, so no
+ static base-name mapping is possible. A future task wanting these
+ eight dates covered needs a genuinely date-keyed lookup path in
+ Lectionary_of.readings, not a slug rename here.
+ - "christmas-dec-29/30/31", "christmas-jan-2/3/4/5/6/7": the date-keyed
+ duplicates of the weekday-keyed families already mapped above. Same
+ reasoning, same remedy if ever closed.
+ - "easter-6-thu": Thursday of Easter week 6 is STRUCTURALLY, always,
+ the Ascension (Easter+39 is always a Thursday) -- Temporal_of's own
+ [named] intercepts it before the generic ferial branch ever runs, so
+ "of-easter-6-thursday" is not a slug Temporal_of can ever produce.
+ - "advent-4-sat": the Saturday of Advent week 4 is STRUCTURALLY, always,
+ either 24 December (intercepted by [named]'s own Nativity Vigil
+ branch on every non-Sunday year) or does not exist as a ferial at all
+ (when 24 December is itself the Fourth Sunday of Advent, week 4 has
+ no ferial days whatsoever) -- "of-advent-4-saturday" is not a slug
+ Temporal_of can ever produce either.
+ Both confirmed, not assumed: [assert_reachable]'s own reachability
+ sweep flagged each as a genuine dead key this generator's own pattern
+ rule produced (after fixing the suffix-stripping bug that function's
+ own comment describes, which had masked them under 580 false
+ positives on this generator's first run). *)
+let excluded_bases =
+ [ "advent-dec-17"; "advent-dec-18"; "advent-dec-19"; "advent-dec-20"; "advent-dec-21";
+ "advent-dec-22"; "advent-dec-23"; "advent-dec-24";
+ "christmas-dec-29"; "christmas-dec-30"; "christmas-dec-31";
+ "christmas-jan-2"; "christmas-jan-3"; "christmas-jan-4"; "christmas-jan-5"; "christmas-jan-6";
+ "christmas-jan-7"; "easter-6-thu"; "advent-4-sat" ]
+
+type mapping_report = { mapped : int; excluded : int; unmapped : string list }
+
+(* Resolves every (base, resolved-citations) pair into zero or more
+ (colitur-slug, resolved-citations) pairs, and separately tracks what
+ could not be resolved -- the second half of Step 1's own "measure the
+ gap in both directions" requirement. A sanctoral PASS-THROUGH (lectio's
+ own base name used verbatim as colitur's slug) is verified against the
+ real merged sanctoral layer at generation time, not assumed: an
+ unverified guess would be exactly the silent-drop failure mode this
+ whole task exists to avoid. *)
+let map_bases resolved ~sanctoral_slugs =
+ let unmapped = ref [] in
+ let excluded = ref 0 in
+ let out =
+ List.filter_map
+ (fun (base, r) ->
+ if List.mem base excluded_bases then begin
+ incr excluded;
+ None
+ end
+ else
+ match pattern_match base with
+ | Some slug -> Some (slug, r)
+ | None -> (
+ match List.assoc_opt base named_overrides with
+ | Some [ slug ] -> Some (slug, r)
+ | Some _ -> die "%s: named_overrides entry must name exactly one slug" base
+ | None ->
+ if Hashtbl.mem sanctoral_slugs base then Some (base, r)
+ else begin
+ unmapped := base :: !unmapped;
+ None
+ end))
+ resolved
+ in
+ (out, { mapped = List.length out; excluded = !excluded; unmapped = List.sort compare !unmapped })
+
+(* ---- Emit one Lectionary.t entry per (slug, resolved) pair ---------- *)
+
+let sunday_letter = function `A -> "a" | `B -> "b" | `C -> "c"
+let weekday_letter = function `I -> "i" | `II -> "ii"
+
+let slug_or_die name = match Slug.of_string name with Ok s -> s | Error e -> die "%s" e
+
+let entries_of (slug, r) =
+ match r with
+ | Flat cs -> [ (slug_or_die slug, cs) ]
+ | Sunday_cycle (a, b, c) ->
+ [ (slug_or_die (slug ^ "-" ^ sunday_letter `A), a);
+ (slug_or_die (slug ^ "-" ^ sunday_letter `B), b);
+ (slug_or_die (slug ^ "-" ^ sunday_letter `C), c) ]
+ | Weekday_cycle (i, ii) ->
+ List.filter_map
+ (fun (letter, v) -> Option.map (fun cs -> (slug_or_die (slug ^ "-" ^ weekday_letter letter), cs)) v)
+ [ (`I, i); (`II, ii) ]
+
+(* ---- Real-code reachability, both temporal and sanctoral ------------ *)
+
+(* Same discipline as tools/bootstrap_lectionary.ml's own
+ [reachable_temporal_slugs]/[assert_reachable]: this sweeps
+ Rite_of.Temporal_of.temporal directly over a real civil-day range, so an
+ emitted key naming no real office is a DEAD KEY, caught here rather than
+ shipped silently. 2004-2051 matches the EF generator's own range and
+ for the same reason -- wide enough to enumerate every distinct slug
+ FAMILY (season/week/weekday recur every year; only which year exhibits a
+ given alignment changes), not a claim about the kernel's full
+ 1583-9999 domain, which is this bootstrap tool's business only insofar
+ as [Temporal_of.temporal] itself is already total over it. *)
+let reachable_temporal_slugs () =
+ let tbl = Hashtbl.create 512 in
+ let mk y m d = match Date.make ~year:y ~month:m ~day:d with Ok t -> t | Error e -> die "%s" e in
+ for y = 2004 to 2051 do
+ let d = ref (mk y 1 1) in
+ let stop = mk y 12 31 in
+ while Date.compare !d stop <= 0 do
+ let t = Rite_of.Temporal_of.temporal !d in
+ Hashtbl.replace tbl (Slug.to_string t.Temporal.office.Celebration.slug) true;
+ d := Date.add_days !d 1
+ done
+ done;
+ tbl
+
+(* The merged sanctoral layer -- calendar-2002.sexp plus all 13 decree
+ overlays, the SAME base + amendment set Tasks 1/2 shipped, loaded here
+ read-only, purely to know which slugs are real. A missing/malformed
+ calendar or amendment file is fatal (die), not silently treated as "zero
+ sanctoral slugs", which would make [map_bases]' own pass-through
+ validation vacuously reject every saint. *)
+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 reachable_sanctoral_slugs () =
+ let base_path = "data/of/calendar-2002.sexp" in
+ let amendments_dir = "data/of/amendments/" in
+ let base =
+ match Layer.load Rite_of.Vocab_of.rank_of_sexp base_path with
+ | Ok l -> l
+ | Error e -> die "%s: %s" base_path e
+ in
+ let overlays =
+ List.map
+ (fun name ->
+ let path = amendments_dir ^ name in
+ match Overlay.load Rite_of.Vocab_of.rank_of_sexp path with
+ | Ok o -> o
+ | Error e -> die "%s: %s" path e)
+ amendment_files
+ in
+ let merged, diagnostics = Overlay.merge base overlays in
+ (match diagnostics with
+ | [] -> ()
+ | ds ->
+ die "data/of/amendments: %d diagnostic(s) applying to the base calendar -- \
+ fix the amendment files before bootstrapping the lectionary from them: %s"
+ (List.length ds)
+ (String.concat "; " (List.map Overlay.diagnostic_to_string ds)));
+ let tbl = Hashtbl.create 256 in
+ List.iter (fun (e : _ Layer.entry) -> Hashtbl.replace tbl (Slug.to_string e.Layer.cel.Celebration.slug) true)
+ merged.Layer.entries;
+ tbl
+
+(* [base_and_letter] strips the RAW ini suffixes (-A/-B/-C/-I/-II,
+ uppercase, as lectio itself spells them). The final EMITTED slugs use
+ {!entries_of}'s own lowercase letters (-a/-b/-c/-i/-ii, valid
+ {!Slug.t} characters -- Slug.ml's own [valid_char] rejects uppercase
+ outright), so a distinct stripper is needed here; reusing
+ [base_and_letter] silently matched nothing (a real bug this generator's
+ own first run caught: every emitted key showed up as "dead", 580 of
+ them, because "-a" never matches an uppercase "-A" test). *)
+let strip_emitted_suffix s =
+ List.fold_left
+ (fun acc suf -> match acc with Some _ -> acc | None -> strip_suffix ~suffix:suf s)
+ None [ "-a"; "-b"; "-c"; "-ii"; "-i" ]
+ |> Option.value ~default:s
+
+let assert_reachable entries ~temporal_slugs ~sanctoral_slugs =
+ let base_of s = strip_emitted_suffix (Slug.to_string s) in
+ let dead =
+ List.filter
+ (fun (s, _) ->
+ let b = base_of s in
+ not (Hashtbl.mem temporal_slugs b || Hashtbl.mem sanctoral_slugs b))
+ entries
+ in
+ (match dead with
+ | [] -> ()
+ | _ ->
+ List.iter
+ (fun (s, _) ->
+ Printf.eprintf
+ "bootstrap_lectionary_of: DEAD KEY -- %S is not a real Temporal_of slug (2004-2051) \
+ nor a real sanctoral slug\n"
+ (Slug.to_string s))
+ dead;
+ die "%d emitted key(s) are unreachable (see above)" (List.length dead));
+ let emitted_temporal = Hashtbl.create 512 in
+ List.iter
+ (fun (s, _) ->
+ let b = base_of s in
+ if Hashtbl.mem temporal_slugs b then Hashtbl.replace emitted_temporal b true)
+ entries;
+ let uncovered =
+ Hashtbl.fold (fun s _ acc -> if Hashtbl.mem emitted_temporal s then acc else s :: acc) temporal_slugs []
+ |> List.sort compare
+ in
+ uncovered
+
+(* ---- Coverage measurement, both directions --------------------------- *)
+
+(* Number 1 (temporal-day coverage): over every day of civil year 2026, how
+ many days does Rite_of.Temporal_of.temporal produce a slug this
+ generator never emits an entry for (tried flat, then both cycle-letter
+ suffixes -- exactly the lookup order Lectionary_of.readings itself
+ uses). Those are days with no readings via the temporal-slug path
+ (a sanctoral proper on the same day, if any, is a separate, second
+ chance -- see the generator's own summary printout for that count too). *)
+let temporal_day_gap ~lectionary ~year_start =
+ let mk m d = match Date.make ~year:2026 ~month:m ~day:d with Ok t -> t | Error e -> die "%s" e in
+ let count = ref 0 and total = ref 0 and misses = ref [] in
+ for m = 1 to 12 do
+ let days_in_month = match m with
+ | 1 | 3 | 5 | 7 | 8 | 10 | 12 -> 31 | 4 | 6 | 9 | 11 -> 30 | 2 -> 28 | _ -> assert false
+ in
+ for d = 1 to days_in_month do
+ incr total;
+ let date = mk m d in
+ let t = Rite_of.Temporal_of.temporal date in
+ let base = Slug.to_string t.Temporal.office.Celebration.slug in
+ let found =
+ Lectionary.mem lectionary (slug_or_die base)
+ || Lectionary.mem lectionary
+ (slug_or_die
+ (base ^ "-"
+ ^ Rite_of.Lectionary_of.sunday_cycle_letter (Rite_of.Lectionary_of.sunday_cycle ~year_start date)))
+ || Lectionary.mem lectionary
+ (slug_or_die
+ (base ^ "-"
+ ^ Rite_of.Lectionary_of.weekday_cycle_letter
+ (Rite_of.Lectionary_of.weekday_cycle ~year_start date)))
+ in
+ if not found then begin
+ incr count;
+ misses := (Date.to_iso8601 date, base) :: !misses
+ end
+ done
+ done;
+ (!count, !total, List.rev !misses)
+
+let sha256 path =
+ let ic = Unix.open_process_in (Printf.sprintf "sha256sum %s" (Filename.quote path)) in
+ let line = try input_line ic with End_of_file -> die "sha256sum failed" in
+ ignore (Unix.close_process_in ic);
+ List.hd (String.split_on_char ' ' line)
+
+let () =
+ let src = if Array.length Sys.argv > 1 then Sys.argv.(1) else default_source in
+ let dst = if Array.length Sys.argv > 2 then Sys.argv.(2) else default_dest in
+ let secs = parse_ini src in
+ let resolved = resolve_sections secs in
+ let sanctoral_slugs = reachable_sanctoral_slugs () in
+ let mapped, report = map_bases resolved ~sanctoral_slugs in
+ let entries = List.concat_map entries_of mapped in
+ let temporal_slugs = reachable_temporal_slugs () in
+ let uncovered_temporal = assert_reachable entries ~temporal_slugs ~sanctoral_slugs in
+ let lect = match Lectionary.of_entries entries with Ok l -> l | Error e -> die "%s" e in
+ let gap_count, gap_total, gap_misses =
+ temporal_day_gap ~lectionary:lect ~year_start:Rite_of.Temporal_of.year_start
+ in
+ let oc = open_out dst in
+ Printf.fprintf oc
+ "; data/of/lectionary.sexp -- OF (2002) temporal + sanctoral lectionary\n\
+ ; (Epistle + Gospel citations, never scripture text), bootstrapped from\n\
+ ; lectio.\n\
+ ;\n\
+ ; LINEAGE, stated loudly because it constrains what this file can show\n\
+ ; (design spec 2026-08-24-colitur-of-rite-module-design.md sec4.4/sec5):\n\
+ ; this is a POLISH VERNACULAR pastoral lectionary (niedziela.pl,\n\
+ ; harvested 2020-2025 by lectio's own scripts/genlect-of.go), NOT the\n\
+ ; Latin OLM (Ordo Lectionum Missae) 1981 itself, and its citations are\n\
+ ; ENGLISH-CANONICAL, not OLM's Vulgate numbering. It CANNOT show any\n\
+ ; divergence between niedziela.pl's own pastoral choices and OLM's own\n\
+ ; text -- three such divergences are already confirmed against the real\n\
+ ; OLM page images (design spec sec4.4): Holy Family Year A's second-\n\
+ ; reading short form, Trinity Sunday's Dan 3:56, and the Baptism of the\n\
+ ; Lord's Mc 9:6 vs \"Mark 9:7\". Nor can it show OLM's short/long-form\n\
+ ; reading alternatives, which niedziela.pl does not distinguish. This is\n\
+ ; ALSO a SEPARATE lineage from lectio's own OF CALENDAR data\n\
+ ; (data/of/calendar-2002.sexp, roman-calendar.ini, upstream\n\
+ ; calapi.inadiutorium.cz) -- lectio is two unrelated upstreams glued\n\
+ ; together by one downstream project, not one witness, and neither is\n\
+ ; the typical edition.\n\
+ ;\n\
+ ; Generator: tools/bootstrap_lectionary_of.ml -- do not hand-edit;\n\
+ ; re-run against the same lectio snapshot (its SHA-256 is pinned below;\n\
+ ; a MISSING source file is fatal, checked before any read is attempted --\n\
+ ; see this generator's own [parse_ini]) and commit the diff instead.\n\
+ ; Every emitted key is asserted, at generation time, to be a slug\n\
+ ; Rite_of.Temporal_of actually computes OR a slug the real merged\n\
+ ; sanctoral layer (data/of/calendar-2002.sexp + all 13 decree overlays)\n\
+ ; actually carries -- see [assert_reachable].\n\
+ ;\n\
+ ; Source: %s\n\
+ ; SHA-256: %s\n\
+ ; %d ini sections (988 expected) -> %d resolved (base, cycle-shape) \
+pairs -> %d colitur slugs mapped, %d ini bases deliberately excluded (date-\n\
+ ; keyed duplicates/late-Advent, no colitur date-keyed lookup exists --\n\
+ ; see [excluded_bases]), %d ini bases genuinely unmapped (no pattern, no\n\
+ ; override, no matching sanctoral slug) -> %d emitted lectionary entries.\n\
+ ;\n\
+ ; COVERAGE, BOTH DIRECTIONS (Step 1 of this task's own brief):\n\
+ ; (1) Temporal-day gap: of the %d days of civil year 2026, %d produce a\n\
+ ; Rite_of.Temporal_of slug with NO entry in this file (tried flat,\n\
+ ; then both the Sunday- and weekday-cycle letter suffixes -- the\n\
+ ; same order Lectionary_of.readings itself tries). Those are days\n\
+ ; with no readings via the temporal-slug path (a sanctoral proper\n\
+ ; on the same civil day, where one exists, is Lectionary_of's own\n\
+ ; separate first chance). Named set below.\n\
+ ; (2) Unmapped lectio keys: %d ini base names (of 988 sections, %d\n\
+ ; distinct bases) map to no colitur slug at all -- data being\n\
+ ; silently dropped if unreported. Named below.\n\
+ ; Regenerate with:\n\
+ ; eval $(opam env) && dune exec tools/bootstrap_lectionary_of.exe -- %s %s\n"
+ src (sha256 src) (List.length secs) (List.length resolved) report.mapped
+ (List.length excluded_bases) (List.length report.unmapped) (List.length entries)
+ gap_total gap_count (List.length report.unmapped) (List.length resolved) src dst;
+ Printf.fprintf oc "; Unmapped lectio bases (%d):\n" (List.length report.unmapped);
+ List.iter (fun b -> Printf.fprintf oc "; %s\n" b) report.unmapped;
+ Printf.fprintf oc "; Temporal_of slugs (2004-2051) with no lectionary entry (%d, informational --\n\
+ ; most are the Christmas-season/late-Advent date-vs-weekday gap named above):\n"
+ (List.length uncovered_temporal);
+ List.iter (fun s -> Printf.fprintf oc "; %s\n" s) uncovered_temporal;
+ Sexplib.Sexp.output_hum oc (Lectionary.sexp_of_t lect);
+ output_char oc '\n';
+ close_out oc;
+ Printf.printf "bootstrap_lectionary_of: %d entries -> %s\n" (List.length entries) dst;
+ Printf.printf "bootstrap_lectionary_of: coverage gap 1 (temporal days, 2026): %d/%d\n" gap_count gap_total;
+ Printf.printf "bootstrap_lectionary_of: coverage gap 2 (unmapped lectio bases): %d\n"
+ (List.length report.unmapped);
+ ignore gap_misses
diff --git a/tools/dune b/tools/dune
index 9a4dea5..40e9836 100644
--- a/tools/dune
+++ b/tools/dune
@@ -23,6 +23,21 @@
(name bootstrap_lectionary)
(libraries colitur_kernel rite_ef unix sexplib))
+; Task 4 (2026-08-25-colitur-of-phases-3-5): converts lectio's
+; of-lectionary.ini into data/of/lectionary.sexp. Run via `dune exec
+; tools/bootstrap_lectionary_of.exe -- <source.ini> <dest.sexp>`. Same
+; `unix`-for-`sha256sum` usage as bootstrap_lectionary.ml above; `rite_of`
+; for the identical "code, not data" reason bootstrap_lectionary.ml links
+; `rite_ef` -- [assert_reachable] sweeps Rite_of.Temporal_of.temporal AND
+; the real merged sanctoral layer directly, so a mapping-table typo cannot
+; ship a dead key silently. Runs from the repo root (its own [reachable_
+; sanctoral_slugs] reads data/of/calendar-2002.sexp and data/of/amendments/
+; by a repo-root-relative path, unlike bootstrap_lectionary.ml's own
+; source/dest arguments, which are caller-supplied).
+(executable
+ (name bootstrap_lectionary_of)
+ (libraries colitur_kernel rite_of unix sexplib))
+
; Task 6 (2026-08-21-colitur-celebrant-rubrics-phase1): turns pdftotext's
; -layout dump of the Latin Mass Society Ordo into test/fixtures/
; lms-ordo-2024-2025.sexp. Run via `dune exec tools/extract_lms_ordo.exe --