summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/of/amendments/001-padre-pio.sexp39
-rw-r--r--data/of/amendments/002-juan-diego-cuauhtlatoatzin.sexp40
-rw-r--r--data/of/amendments/003-our-lady-of-guadalupe.sexp41
-rw-r--r--data/of/amendments/004-john-xxiii-john-paul-ii.sexp50
-rw-r--r--data/of/amendments/005-mary-magdalene-rank.sexp49
-rw-r--r--data/of/amendments/006-mary-mother-of-the-church.sexp76
-rw-r--r--data/of/amendments/007-paul-vi.sexp31
-rw-r--r--data/of/amendments/008-our-lady-of-loreto.sexp27
-rw-r--r--data/of/amendments/009-faustina-kowalska.sexp34
-rw-r--r--data/of/amendments/010-narek-avila-hildegard.sexp76
-rw-r--r--data/of/amendments/011-martha-mary-lazarus.sexp38
-rw-r--r--data/of/amendments/012-teresa-of-calcutta.sexp30
-rw-r--r--data/of/amendments/013-john-henry-newman.sexp47
-rw-r--r--test/dune13
-rw-r--r--test/test_amendments_of.ml217
-rw-r--r--test/test_colitur.ml1
16 files changed, 809 insertions, 0 deletions
diff --git a/data/of/amendments/001-padre-pio.sexp b/data/of/amendments/001-padre-pio.sexp
new file mode 100644
index 0000000..27758ee
--- /dev/null
+++ b/data/of/amendments/001-padre-pio.sexp
@@ -0,0 +1,39 @@
+; data/of/amendments/001-padre-pio.sexp -- ADDS St Pius of Pietrelcina
+; (Padre Pio) to the General Roman Calendar.
+;
+; Decree: "Ex uberi terra", Congregation for Divine Worship and the
+; Discipline of the Sacraments, 26 June 2002. Signed Marius Marini,
+; Subsecretarius.
+; Published: Notitiae 38 (2002), 549-550 (annexed liturgical texts run
+; 551-554). Absent from AAS 2002-2006 (checked directly, not merely
+; unindexed -- docs/research/of/PROVENANCE-amendments.md item 1).
+;
+; What it does: inscribes 23 September, memoria (obligatory -- the
+; decree's own operative sentence, "in posterum memoria Sancti Pii de
+; Pietrelcina, presbyteri, quotannis... celebretur", carries no "ad
+; libitum" qualifier; confirmed directly against the decree's own text,
+; Notitiae 38 (2002) 551, line 1643 of the extracted transcript).
+;
+; Absent from the printed 2002 Missal's own Calendarium (23 September is
+; blank in data/of/calendar-2002.sexp's source PDF) despite Pio's
+; canonization (16 June 2002) preceding this decree by ten days -- a
+; genuine post-typical-edition addition, not a transcription gap.
+;
+; `en`/slug reused from lectio's own roman-calendar.ini
+; ([pio-of-pietrelcina-padre-pio-priest], date 09-23, rank memorial,
+; class saint, colour white) -- an engineering-key/cross-check reuse only,
+; per calendar-2002.sexp's own header discipline; `la` taken directly from
+; the decree's own calendarium table row ("S. Pii de Pietrelcina,
+; presbyteri", Notitiae 38 (2002) 551).
+((id of-amend-01-padre-pio)
+ (directives
+ ((Add
+ ((date (Fixed (month 9) (day 23)))
+ (cel
+ ((slug pio-of-pietrelcina-padre-pio-priest)
+ (names
+ ((en "Saint Pio of Pietrelcina (Padre Pio), priest")
+ (la "S. Pii de Pietrelcina, presbyteri")))
+ (rank Memoria_obligatoria) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/002-juan-diego-cuauhtlatoatzin.sexp b/data/of/amendments/002-juan-diego-cuauhtlatoatzin.sexp
new file mode 100644
index 0000000..0efca17
--- /dev/null
+++ b/data/of/amendments/002-juan-diego-cuauhtlatoatzin.sexp
@@ -0,0 +1,40 @@
+; data/of/amendments/002-juan-diego-cuauhtlatoatzin.sexp -- ADDS St Juan
+; Diego Cuauhtlatoatzin to the General Roman Calendar.
+;
+; Decree: "Reverentia atque cultus", Congregation for Divine Worship and
+; the Discipline of the Sacraments, 28 September 2002, Prot. n. 1828/02/L.
+; Signed Georgius A. Card. Medina Estevez (Praefectus) + Franciscus Pius
+; Tamburrino (Archiepiscopus a Secretis). A DIFFERENT protocol number from
+; 003-our-lady-of-guadalupe.sexp's own decree (Prot. N. 1622/02/L) --
+; issued the same day and published in the same Notitiae article, but two
+; separate juridical instruments, hence two separate files per this
+; project's own "exactly one decree per file" discipline.
+; Published: Notitiae 40 (2004), 196 (part of a combined article, pp.
+; 194-201). Absent from AAS 2002-2006 (checked directly).
+;
+; What it does: inscribes 9 December, memoria ad libitum, extending to the
+; universal calendar a devotion previously particular to Mexico (a 25
+; March 1999 CDW decree, Notitiae 35 (1999) 227-247, out of this
+; inventory's scope: it predates the 2002 baseline and was never
+; universal). Absent from the printed 2002 Missal's own Calendarium
+; (9 December is blank).
+;
+; `en`/`la`/slug/rank/colour/subject reused from lectio's own
+; roman-calendar.ini ([juan-diego], date 12-09, rank optional, class
+; saint, colour white) -- an engineering-key/cross-check reuse only, per
+; calendar-2002.sexp's own header discipline. `la` matches the decree's
+; own calendarium table row ("S. Ioannis Didaci Cuahtlatoatzin";
+; lectio's own transcription carries a stray "[*]" footnote marker not
+; present in the decree text itself, dropped here).
+((id of-amend-02-juan-diego)
+ (directives
+ ((Add
+ ((date (Fixed (month 12) (day 9)))
+ (cel
+ ((slug juan-diego)
+ (names
+ ((en "Saint Juan Diego")
+ (la "S. Ioannis Didaci Cuahtlatoatzin")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/003-our-lady-of-guadalupe.sexp b/data/of/amendments/003-our-lady-of-guadalupe.sexp
new file mode 100644
index 0000000..141e9b7
--- /dev/null
+++ b/data/of/amendments/003-our-lady-of-guadalupe.sexp
@@ -0,0 +1,41 @@
+; data/of/amendments/003-our-lady-of-guadalupe.sexp -- ADDS Our Lady of
+; Guadalupe to the General Roman Calendar (universal extension).
+;
+; Decree: "Beatam Mariam Virginem", Congregation for Divine Worship and
+; the Discipline of the Sacraments, 28 September 2002, Prot. N.
+; 1622/02/L. Same signatories, same day and same Notitiae article as
+; 002-juan-diego-cuauhtlatoatzin.sexp's own decree, but a DIFFERENT
+; protocol number -- a second, separate juridical instrument, hence its
+; own file.
+; Published: Notitiae 40 (2004), 197. Absent from AAS 2002-2006 (checked
+; directly).
+;
+; What it does: inscribes 12 December, memoria ad libitum, as a
+; UNIVERSAL entry -- this is the first General-Roman-Calendar action for
+; Guadalupe; a 25 March 1999 CDW decree had already published Spanish-
+; language texts for a particular-calendar Feast (Mexico and, per
+; Ecclesia in America, the Americas), which is why 12 December is still
+; blank in the 2002 typical edition's own printed Calendarium despite
+; already being kept locally at the time. That 1999 grant is out of this
+; inventory's scope (particular, not universal, and pre-dates the 2002
+; baseline).
+;
+; `en`/`la`/slug/rank/colour/subject reused from lectio's own
+; roman-calendar.ini ([our-lady-of-guadalupe], date 12-12, rank optional,
+; class bvm, colour white) -- an engineering-key/cross-check reuse only,
+; per calendar-2002.sexp's own header discipline. `la` matches the
+; decree's own calendarium table row ("Beatae Mariae Virginis de
+; Guadalupe"; lectio's own transcription carries a stray "[*]" footnote
+; marker not present in the decree text itself, dropped here).
+((id of-amend-03-guadalupe)
+ (directives
+ ((Add
+ ((date (Fixed (month 12) (day 12)))
+ (cel
+ ((slug our-lady-of-guadalupe)
+ (names
+ ((en "Our Lady of Guadalupe")
+ (la "Beatae Mariae Virginis de Guadalupe")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Bvm) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/004-john-xxiii-john-paul-ii.sexp b/data/of/amendments/004-john-xxiii-john-paul-ii.sexp
new file mode 100644
index 0000000..2760313
--- /dev/null
+++ b/data/of/amendments/004-john-xxiii-john-paul-ii.sexp
@@ -0,0 +1,50 @@
+; data/of/amendments/004-john-xxiii-john-paul-ii.sexp -- ADDS St John XXIII
+; and St John Paul II to the General Roman Calendar (one decree, two
+; entries).
+;
+; Decree: 29 May 2014, Prot. N. 309/14. Signed Antonio Card. Canizares
+; Llovera (Praefectus) + Arthur Roche (Archiepiscopus a Secretis).
+; Following the joint canonization of 27 April 2014.
+;
+; Published: NOT FOUND IN AAS -- checked exhaustively (yearly indices
+; 2014-2024, and the four individual monthly AAS issues June-Sept 2014,
+; all read directly with no hit; docs/research/of/PROVENANCE-amendments.md
+; item 4 names this the weakest-sourced entry in the whole inventory).
+; Rests on the Vatican decree webpage alone:
+; http://www.vatican.va/roman_curia/congregations/ccdds/documents/rc_con_ccdds_doc_20140529_decreto-calendario-generale-gxxiii-gpii_en.html
+; -- re-fetched directly for this task (2026-08-26), which confirms the
+; operative sentence: "the Supreme Pontiff Francis... has decreed that
+; the celebrations of Pope Saint John XXIII and Pope Saint John Paul II
+; should be inserted into the General Roman Calendar, to be observed
+; annually with the rank of Optional Memorial, the first on 11 October,
+; the second on 22 October."
+;
+; What it does: two new memoria ad libitum entries, 11 October (John
+; XXIII) and 22 October (John Paul II).
+;
+; `en`/`la`/slug/rank/colour/subject all reused from lectio's own
+; roman-calendar.ini ([john-xxiii-pope] date 10-11, [john-paul-ii-pope]
+; date 10-22, both rank optional, class saint, colour white) -- an
+; engineering-key/cross-check reuse only, per calendar-2002.sexp's own
+; header discipline.
+((id of-amend-04-john-xxiii-john-paul-ii)
+ (directives
+ ((Add
+ ((date (Fixed (month 10) (day 11)))
+ (cel
+ ((slug john-xxiii-pope)
+ (names
+ ((en "Saint John XXIII, pope")
+ (la "S. Ioannis XXIII, papae")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ (Add
+ ((date (Fixed (month 10) (day 22)))
+ (cel
+ ((slug john-paul-ii-pope)
+ (names
+ ((en "Saint John Paul II, pope")
+ (la "S. Ioannis Pauli II, papae")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/005-mary-magdalene-rank.sexp b/data/of/amendments/005-mary-magdalene-rank.sexp
new file mode 100644
index 0000000..e867d58
--- /dev/null
+++ b/data/of/amendments/005-mary-magdalene-rank.sexp
@@ -0,0 +1,49 @@
+; data/of/amendments/005-mary-magdalene-rank.sexp -- RANK CHANGE: St Mary
+; Magdalene, memoria -> festum.
+;
+; Decree: "Sanctae Mariae Magdalenae", Congregation for Divine Worship and
+; the Discipline of the Sacraments, 3 June 2016, Prot. n. 708/2015. Signed
+; Robertus Card. Sarah (Praefectus) alone.
+; Published: AAS 108 (2016), 798-799.
+;
+; What it does: the day and colour are unchanged (22 July, white); only the
+; grade changes. Verified directly against the decree's own operative
+; sentence (docs/research/of/aas-monthly/2016_luglio.pdf, line 3344-3345 of
+; the extracted transcript): "...celebrationem Sanctae Mariae Magdalenae
+; Calendario Romano generali posthac inscribendam esse gradu festi loco
+; memoriae, sicut nunc habetur" -- "the celebration of St Mary Magdalene is
+; henceforth to be inscribed in the General Roman Calendar with the rank of
+; FEAST IN PLACE OF MEMORIAL, as it now stands." The decree also adds a
+; proper Preface to the Missal; colitur's calendar data carries no Preface
+; field, so that half of the decree has no representation here.
+;
+; This is an EDIT, not an Add: the 2002 Missal already carries the entry
+; (data/of/calendar-2002.sexp's own "mary-magdalene", 22 July,
+; Memoria_obligatoria -- Task 1's own lectio cross-check flagged exactly
+; this rank disagreement and deliberately left it for this task). Editing
+; in place, rather than Suppress+Add under a new slug, keeps the same
+; entity's identity stable across the amendment for anything that may come
+; to reference it by slug (a future lectionary, an overlay, a template).
+;
+; Precedence_of interaction (checked, not merely assumed): Festum and
+; Memoria_obligatoria are both NON-Sollemnitas ranks, so this edit does not
+; cross the Sollemnitas boundary -- Precedence_of.disposition's losing-case
+; answer for this candidate stays Omit either way (only a losing Sollemnitas
+; is ever Transferred). Precedence_of.band does move this candidate from
+; Tabula III.10 (band 100) to Tabula II.7 (band 70) -- a real precedence
+; strengthening on paper, but with ZERO effect on which day is OBSERVED
+; under the shipped universal calendar: 22 July carries no other
+; universal-calendar entry (verified -- grep of calendar-2002.sexp finds
+; exactly one (month 7) (day 22) block), so Mary Magdalene already won that
+; date outright at band 100 and continues to at band 70; an ordinary per
+; annum Sunday still outranks her either way (band 60 < 70 < 100 -- a
+; Festum of a SAINT, Tabula II.7, is not a Festum OF THE LORD, Tabula II.5
+; band 50, the only Festum grade that would beat a Sunday). The change
+; becomes live only if a future PROPER (diocesan/religious) overlay adds a
+; band-80-or-lower competitor to 22 July, or if a future obligatory
+; memorial elsewhere ties her old band-100 slot -- neither exists in the
+; shipped data today.
+((id of-amend-05-mary-magdalene)
+ (directives
+ ((Edit mary-magdalene ((Set_rank Festum)))
+ )))
diff --git a/data/of/amendments/006-mary-mother-of-the-church.sexp b/data/of/amendments/006-mary-mother-of-the-church.sexp
new file mode 100644
index 0000000..8fc6d64
--- /dev/null
+++ b/data/of/amendments/006-mary-mother-of-the-church.sexp
@@ -0,0 +1,76 @@
+; data/of/amendments/006-mary-mother-of-the-church.sexp -- ADDS the
+; Blessed Virgin Mary, Mother of the Church, to the General Roman
+; Calendar. The one genuinely MOVABLE amendment in this inventory.
+;
+; Decree: Congregation for Divine Worship and the Discipline of the
+; Sacraments, 11 February 2018, Prot. N. 1037/2017. Signed Robertus Card.
+; Sarah (Praefectus) + Arturus Roche (Archiepiscopus a Secretis).
+; Published: AAS 110 (2018), 437-438 (decree text continues past 438;
+; index cites 437 as the start page).
+;
+; What it does, verified directly against the decree's own operative
+; sentence (docs/research/of/aas-monthly/2018_marzo.pdf, line 2434-2437 of
+; the extracted transcript): "Summus autem Pontifex Franciscus... decrevit
+; ut memoriam B. Mariae Virginis, Ecclesiae Matris, in Calendarium
+; Romanum inscribendam esse Feria II post Pentecosten et quotannis
+; celebrandam" -- inscribes a MEMORIA (obligatory: no "ad libitum"
+; qualifier anywhere in the operative sentence) on "Feria II post
+; Pentecosten", the MONDAY AFTER PENTECOST.
+;
+; Date arithmetic, verified rather than trusted: Pentecost is Easter+49
+; (the 50th day of the Paschal season inclusive of Easter itself), so the
+; following Monday is Easter+50. Date_spec.Easter_offset 50 is exactly
+; this; kernel-level and rite-agnostic (built for EF's Rogation
+; Wednesday), no code change needed. See test_amendments_of.ml's own
+; test_mater_ecclesiae_monday_after_pentecost, which re-derives the
+; calendar date from Colitur_kernel.Computus.gregorian_easter in three
+; real years rather than trusting this offset's own arithmetic.
+;
+; The day carries no other GRC celebration to displace on any FIXED date
+; -- but the decree's own destination is a MOVABLE one, so this is not
+; quite true every year: see the finding recorded below.
+;
+; `la` name taken directly from the decree's own text ("B. Mariae
+; Virginis, Ecclesiae Matris", expanded here to "Beatae Mariae Virginis,
+; Ecclesiae Matris" to match calendar-2002.sexp's own convention of
+; writing out abbreviations in `la` names); `en` is this task's own
+; translation (no lectio entry exists for this decree -- it postdates
+; lectio's own last GRC sync).
+;
+; *** FINDING, worth surfacing rather than silently shipping: a real,
+; unresolved Precedence_of interaction. *** Easter+50 ranges over 11 May
+; - 14 June across the Gregorian Easter window (22 March - 25 April).
+; Several FIXED Memoria_obligatoria entries already sit inside that
+; window in data/of/calendar-2002.sexp: 26 May (Philip Neri), 1 June
+; (Justin Martyr), 3 June (Charles Lwanga & companions), 5 June
+; (Boniface), 11 June (Barnabas), 13 June (Anthony of Padua). Verified
+; computationally (Meeus/Jones/Butcher Gregorian Easter, 1583-2100) that
+; Easter+50 DOES land on each of those dates in real years -- e.g. 2011
+; (Easter 24 April) puts Mary, Mother of the Church squarely on 13 June,
+; Anthony of Padua's own day. On such a year both candidates band at
+; Tabula III.10 (100, both universal Memoria_obligatoria), a genuine tie
+; Precedence_of.band does not and cannot break: Precedence.resolve's own
+; tie-break (Slug.compare) then picks whichever slug sorts first
+; alphabetically as the sole OBSERVED day, silently omitting the other
+; for that year -- not a crash, not a diagnostic, just a deterministic
+; but liturgically arbitrary pick. Normae universales n. 14's own text
+; (docs/research/of/normae-universales-2002-transcription.md) resolves the
+; AD-LIBITUM/AD-LIBITUM case explicitly ("una tantum celebrari potest,
+; omissis ceteris") but is silent on two OBLIGATORY memorials colliding;
+; pastoral practice generally reduces both to ad libitum for that one
+; year, which Precedence_of.ml implements nowhere. Recorded here as a
+; real, load-bearing gap -- not fixed, out of this data-only task's own
+; scope, and not unique to this entry (any future obligatory-memorial
+; overlay entry on a fixed May/June date has the identical exposure).
+((id of-amend-06-mary-mother-of-the-church)
+ (directives
+ ((Add
+ ((date (Easter_offset 50))
+ (cel
+ ((slug mary-mother-of-the-church)
+ (names
+ ((en "The Blessed Virgin Mary, Mother of the Church")
+ (la "Beatae Mariae Virginis, Ecclesiae Matris")))
+ (rank Memoria_obligatoria) (status Feast) (colour White)
+ (subject Bvm) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/007-paul-vi.sexp b/data/of/amendments/007-paul-vi.sexp
new file mode 100644
index 0000000..1342e3b
--- /dev/null
+++ b/data/of/amendments/007-paul-vi.sexp
@@ -0,0 +1,31 @@
+; data/of/amendments/007-paul-vi.sexp -- ADDS St Paul VI, pope, to the
+; General Roman Calendar.
+;
+; Decree: Congregation for Divine Worship and the Discipline of the
+; Sacraments, 25 January 2019. Signed Robertus Card. Sarah (Praefectus).
+; (Protocol number not visible in the extracted text near the signature
+; block -- not chased further, the AAS citation is unambiguous.)
+; Published: AAS 111 (2019), 212-213.
+;
+; What it does: inscribes 29 May, memoria ad libitum. Verified directly
+; against the decree's own calendarium table row
+; (docs/research/of/aas-monthly/2019_febbraio.pdf, line 3888): "...
+; celebrationem sancti Pauli VI, papae, die 29 [maii]..." -- title "S.
+; Pauli VI, papae".
+;
+; No lectio entry exists for this decree; `en`/`la` are this task's own
+; rendering, following the decree's own Latin title and
+; calendar-2002.sexp's own convention for other popes (e.g.
+; "john-xxiii-pope").
+((id of-amend-07-paul-vi)
+ (directives
+ ((Add
+ ((date (Fixed (month 5) (day 29)))
+ (cel
+ ((slug paul-vi-pope)
+ (names
+ ((en "Saint Paul VI, pope")
+ (la "S. Pauli VI, papae")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/008-our-lady-of-loreto.sexp b/data/of/amendments/008-our-lady-of-loreto.sexp
new file mode 100644
index 0000000..1ddcb91
--- /dev/null
+++ b/data/of/amendments/008-our-lady-of-loreto.sexp
@@ -0,0 +1,27 @@
+; data/of/amendments/008-our-lady-of-loreto.sexp -- ADDS Our Lady of
+; Loreto to the General Roman Calendar.
+;
+; Decree: Congregation for Divine Worship and the Discipline of the
+; Sacraments, 7 October 2019, Prot. N. 404/19. Signed Robertus Card. Sarah
+; (Praefectus) + Arturus Roche (Archiepiscopus a Secretis).
+; Published: AAS 111 (2019), 1789-1790.
+;
+; What it does: inscribes 10 December, memoria ad libitum. Verified
+; directly against the decree's own annexed calendarium table row
+; (docs/research/of/aas-monthly/2019_novembre.pdf, line 4718): "10 B.
+; Mariae Virginis de Loreto".
+;
+; No lectio entry exists for this decree; `en`/`la` are this task's own
+; rendering, `la` matching the calendarium row above verbatim.
+((id of-amend-08-our-lady-of-loreto)
+ (directives
+ ((Add
+ ((date (Fixed (month 12) (day 10)))
+ (cel
+ ((slug our-lady-of-loreto)
+ (names
+ ((en "Our Lady of Loreto")
+ (la "B. Mariae Virginis de Loreto")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Bvm) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/009-faustina-kowalska.sexp b/data/of/amendments/009-faustina-kowalska.sexp
new file mode 100644
index 0000000..5d302cf
--- /dev/null
+++ b/data/of/amendments/009-faustina-kowalska.sexp
@@ -0,0 +1,34 @@
+; data/of/amendments/009-faustina-kowalska.sexp -- ADDS St Faustina
+; Kowalska, virgin, to the General Roman Calendar.
+;
+; Decree: Congregation for Divine Worship and the Discipline of the
+; Sacraments, 18 May 2020, Prot. N. 229/20. Signed Robertus Card. Sarah
+; (Praefectus) + Arturus Roche (Archiepiscopus a Secretis).
+; Published: AAS 112 (2020), 595-596.
+;
+; What it does: inscribes 5 October, memoria ad libitum. Verified directly
+; against the decree's own calendarium table row
+; (docs/research/of/aas-monthly/2020_giugno.pdf, line 4114): "5 S.
+; Faustinae Kowalska, virginis".
+;
+; A lead that did NOT hold up (docs/research/of/PROVENANCE-amendments.md
+; item 9): a devotional website claims an April 2005 addition; this
+; decree's own text unambiguously has Pope Francis deciding the insertion
+; in 2020, contradicting that claim, which most likely conflates a
+; particular-calendar action with this universal one. Recorded to explain
+; why this file's date is 2020, not 2005.
+;
+; No lectio entry exists for this decree; `en`/`la` are this task's own
+; rendering, `la` matching the calendarium row above verbatim.
+((id of-amend-09-faustina-kowalska)
+ (directives
+ ((Add
+ ((date (Fixed (month 10) (day 5)))
+ (cel
+ ((slug faustina-kowalska-virgin)
+ (names
+ ((en "Saint Faustina Kowalska, virgin")
+ (la "S. Faustinae Kowalska, virginis")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/010-narek-avila-hildegard.sexp b/data/of/amendments/010-narek-avila-hildegard.sexp
new file mode 100644
index 0000000..378d3ba
--- /dev/null
+++ b/data/of/amendments/010-narek-avila-hildegard.sexp
@@ -0,0 +1,76 @@
+; data/of/amendments/010-narek-avila-hildegard.sexp -- ADDS three Doctors
+; of the Church to the General Roman Calendar: St Gregory of Narek, St
+; John of Avila, St Hildegard of Bingen. ONE decree, three entries --
+; docs/research/of/PROVENANCE-amendments.md's own items 10-12.
+;
+; Decree: Congregation for Divine Worship and the Discipline of the
+; Sacraments, 25 January 2021, Prot. N. 40/21. Signed Robertus Card. Sarah
+; (Praefectus) + Arturus Roche (Archiepiscopus a Secretis).
+; Published: AAS 113 (2021), 225-226.
+;
+; What it does: inscribes three memoria-ad-libitum entries -- 27 February
+; (Narek), 10 May (Avila), 17 September (Hildegard). All three were
+; declared Doctors of the Church years earlier (Avila/Hildegard 7 October
+; 2012, Narek 21 February 2015); the GRC inscription followed 6-9 years
+; later. Verified directly against the decree's own calendarium table
+; rows (docs/research/of/aas-monthly/2021_febbraio.pdf):
+; line 2170: "27 S. Gregorii Narecensis, abbatis et Ecclesiae doctoris"
+; line 2300: "10 S. Ioannis De Avila, presbyteri et Ecclesiae doctoris"
+; line 2432: "17 S. Hildegardis Bingensis, virginis et Ecclesiae
+; doctoris"
+;
+; No lectio entries exist for this decree; `en`/`la` are this task's own
+; rendering, `la` matching the calendarium rows above verbatim.
+;
+; *** FINDING: 17 September already carries a universal entry ***
+; (calendar-2002.sexp's own "robert-bellarmine-bishop-and-doctor",
+; Memoria_ad_libitum, White) -- verified: `grep '(month 9) (day 17)'`
+; finds exactly those two blocks once this file is applied. Both are
+; ordinary optional memorials, so Normae universales n. 14's own text
+; ("Si eodem die plures inscribuntur in calendario memoriae ad libitum,
+; una tantum celebrari potest, omissis ceteris" -- if several optional
+; memorials are inscribed on the same day, only one may be celebrated,
+; the rest omitted) governs correctly and is NOT a defect. But
+; Precedence_of's tie-break for two same-band candidates is
+; Slug.compare, and "hildegard-of-bingen-virgin-and-doctor" sorts BEFORE
+; "robert-bellarmine-bishop-and-doctor" -- so applying this overlay
+; changes which candidate `Precedence.resolve` reports as OBSERVED on
+; every 17 September, from Robert Bellarmine to Hildegard. Both are
+; legitimate choices under n. 14 (the celebrant elects either), but
+; colitur's single-observed-day model cannot express "elective": it
+; reports one deterministically, and this file changes which one. Not a
+; new architectural gap -- 9 October already carries two ad-libitum
+; entries in the shipped 2002 base (Denis & companions, John Leonardi)
+; with the identical shape, undisturbed here (see
+; 013-john-henry-newman.sexp's own note: adding a third candidate there
+; leaves Denis, already alphabetically first, unchanged as observed).
+((id of-amend-10-narek-avila-hildegard)
+ (directives
+ ((Add
+ ((date (Fixed (month 2) (day 27)))
+ (cel
+ ((slug gregory-of-narek-abbot-and-doctor)
+ (names
+ ((en "Saint Gregory of Narek, abbot and doctor")
+ (la "S. Gregorii Narecensis, abbatis et Ecclesiae doctoris")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ (Add
+ ((date (Fixed (month 5) (day 10)))
+ (cel
+ ((slug john-of-avila-priest-and-doctor)
+ (names
+ ((en "Saint John of Avila, priest and doctor")
+ (la "S. Ioannis De Avila, presbyteri et Ecclesiae doctoris")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ (Add
+ ((date (Fixed (month 9) (day 17)))
+ (cel
+ ((slug hildegard-of-bingen-virgin-and-doctor)
+ (names
+ ((en "Saint Hildegard of Bingen, virgin and doctor")
+ (la "S. Hildegardis Bingensis, virginis et Ecclesiae doctoris")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/011-martha-mary-lazarus.sexp b/data/of/amendments/011-martha-mary-lazarus.sexp
new file mode 100644
index 0000000..b9365ca
--- /dev/null
+++ b/data/of/amendments/011-martha-mary-lazarus.sexp
@@ -0,0 +1,38 @@
+; data/of/amendments/011-martha-mary-lazarus.sexp -- RENAME / scope-widen:
+; the existing 29 July obligatory memorial of St Martha alone becomes
+; Sts Martha, Mary and Lazarus.
+;
+; Decree: Congregation for Divine Worship and the Discipline of the
+; Sacraments, 26 January 2021, Prot. N. 35/21. Signed Robertus Card. Sarah
+; (Praefectus) + Arturus Roche (Archiepiscopus a Secretis).
+; Published: AAS 113 (2021), 236-237.
+;
+; What it does, verified directly against the decree's own text and its
+; annexed calendarium table row (docs/research/of/aas-monthly/
+; 2021_febbraio.pdf): "Dicasterii propositis, disposuit ut memoria
+; sanctorum Marthae, Mariae et Lazari in Calendario Romano generali die 29
+; iulii inscriberetur" (line 2576-2577); the table row itself (line 2604):
+; "29 Ss. Marthae, Mariae et Lazari ... Memoria". Date and rank are
+; UNCHANGED (29 July, memoria obligatoria, inherited from the existing
+; entry, not newly stated); only the celebration's NAME (and its proper
+; texts, out of colitur's scope) changes, resolving a long Latin-tradition
+; ambiguity over "which Mary" that the reformed Roman Martyrology had
+; already settled.
+;
+; DIRECTIVE CHOICE: Edit, not Suppress+Add. This is the SAME entity
+; continuing to exist under the SAME date/rank/colour/subject -- only its
+; display name widens. Edit's Set_name field-edit expresses exactly a
+; rename without disturbing anything else, and keeps the existing slug
+; ("martha") stable for any future overlay or lectionary entry that might
+; already key off it -- a Suppress+Add under a new slug would force every
+; such reference to be rewritten for no liturgical reason (the decree
+; itself treats this as a continuation of the same memorial, "memoria...
+; inscriberetur" on the SAME date the memorial already occupied, not a
+; suppression of one and creation of another). Rank/colour/subject/status
+; are deliberately NOT touched by this Edit -- they were already correct.
+((id of-amend-11-martha-mary-lazarus)
+ (directives
+ ((Edit martha
+ ((Set_name en "Saints Martha, Mary and Lazarus")
+ (Set_name la "Ss. Marthae, Mariae et Lazari")))
+ )))
diff --git a/data/of/amendments/012-teresa-of-calcutta.sexp b/data/of/amendments/012-teresa-of-calcutta.sexp
new file mode 100644
index 0000000..e8ca63c
--- /dev/null
+++ b/data/of/amendments/012-teresa-of-calcutta.sexp
@@ -0,0 +1,30 @@
+; data/of/amendments/012-teresa-of-calcutta.sexp -- ADDS St Teresa of
+; Calcutta (Mother Teresa), virgin, to the General Roman Calendar.
+;
+; Decree: Dicastery for Divine Worship and the Discipline of the
+; Sacraments, 24 December 2024, Prot. N. 703/24. Signed Arturus Card.
+; Roche (Praefectus -- the Dicastery renamed in 2022) + Victorius
+; Franciscus Viola, O.F.M. (Archiepiscopus a Secretis). First publicised
+; via a Vatican press bulletin (11 February 2025), ahead of AAS.
+; Published: AAS 117 (2025), 256-257 -- found directly in the March 2025
+; monthly issue; no compiled 2025 index yet exists.
+;
+; What it does: inscribes 5 September, memoria ad libitum. Verified
+; directly against the decree's own calendarium table row
+; (docs/research/of/aas-monthly-2025/marzo.pdf, line 1280): "5 S.
+; Teresiae de Calcutta, virginis".
+;
+; No lectio entry exists for this decree; `en`/`la` are this task's own
+; rendering, `la` matching the calendarium row above verbatim.
+((id of-amend-12-teresa-of-calcutta)
+ (directives
+ ((Add
+ ((date (Fixed (month 9) (day 5)))
+ (cel
+ ((slug teresa-of-calcutta-virgin)
+ (names
+ ((en "Saint Teresa of Calcutta, virgin")
+ (la "S. Teresiae de Calcutta, virginis")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/data/of/amendments/013-john-henry-newman.sexp b/data/of/amendments/013-john-henry-newman.sexp
new file mode 100644
index 0000000..043f09a
--- /dev/null
+++ b/data/of/amendments/013-john-henry-newman.sexp
@@ -0,0 +1,47 @@
+; data/of/amendments/013-john-henry-newman.sexp -- ADDS St John Henry
+; Newman, priest and doctor, to the General Roman Calendar. The most
+; recent amendment in this inventory.
+;
+; Decree: Dicastery for Divine Worship and the Discipline of the
+; Sacraments, 9 November 2025, Prot. N. 760/25. Signed Arturus Card.
+; Roche (Praefectus) + Victorius Franciscus Viola. Made public via
+; Vatican commentary/press on 3 February 2026 -- under Pope Leo XIV, per
+; the decree's own preamble, the first entry in this whole inventory
+; issued under a different pope from Francis.
+; Published: AAS 118 (2026), 260-262 -- the single most recent item in
+; the inventory, found in the February 2026 monthly issue.
+;
+; What it does: inscribes 9 October, memoria ad libitum. Verified
+; directly against the decree's own calendarium table row
+; (docs/research/of/aas-monthly-2026/febbraio.pdf, line 4915): "9 S.
+; Ioannis Henrici Newman, presbyteri et Ecclesiae doctoris". Newman was
+; never ordained a bishop (he was made a Cardinal-Deacon), hence
+; "presbyteri", priest, not "episcopi".
+;
+; No lectio entry exists for this decree; `en`/`la` are this task's own
+; rendering, `la` matching the calendarium row above verbatim.
+;
+; *** NOTE: 9 October already carries TWO universal entries ***
+; (calendar-2002.sexp's own "denis-and-companions-martyrs" and
+; "john-leonardi-priest", both Memoria_ad_libitum) -- this is not a new
+; situation this file creates (Task 1's own base data already shipped two
+; ad-libitum candidates sharing that date under Normae n. 14's "one may
+; be celebrated" rule) and does not change what `Precedence.resolve`
+; reports as observed: alphabetically, "denis-and-companions-martyrs" <
+; "john-henry-newman-priest-and-doctor" < "john-leonardi-priest", so
+; Denis remains the reported observed day both before and after this
+; overlay applies. Contrast 010-narek-avila-hildegard.sexp's own 17
+; September finding, where the equivalent addition DOES flip the
+; alphabetical winner.
+((id of-amend-13-john-henry-newman)
+ (directives
+ ((Add
+ ((date (Fixed (month 10) (day 9)))
+ (cel
+ ((slug john-henry-newman-priest-and-doctor)
+ (names
+ ((en "Saint John Henry Newman, priest and doctor")
+ (la "S. Ioannis Henrici Newman, presbyteri et Ecclesiae doctoris")))
+ (rank Memoria_ad_libitum) (status Feast) (colour White)
+ (subject Saint) (citations ()) (layer of-universal)))))
+ )))
diff --git a/test/dune b/test/dune
index 9af9900..c5bfe07 100644
--- a/test/dune
+++ b/test/dune
@@ -5,6 +5,19 @@
../data/ef/sanctoral.sexp
../data/ef/adjustments.sexp
../data/of/calendar-2002.sexp
+ ../data/of/amendments/001-padre-pio.sexp
+ ../data/of/amendments/002-juan-diego-cuauhtlatoatzin.sexp
+ ../data/of/amendments/003-our-lady-of-guadalupe.sexp
+ ../data/of/amendments/004-john-xxiii-john-paul-ii.sexp
+ ../data/of/amendments/005-mary-magdalene-rank.sexp
+ ../data/of/amendments/006-mary-mother-of-the-church.sexp
+ ../data/of/amendments/007-paul-vi.sexp
+ ../data/of/amendments/008-our-lady-of-loreto.sexp
+ ../data/of/amendments/009-faustina-kowalska.sexp
+ ../data/of/amendments/010-narek-avila-hildegard.sexp
+ ../data/of/amendments/011-martha-mary-lazarus.sexp
+ ../data/of/amendments/012-teresa-of-calcutta.sexp
+ ../data/of/amendments/013-john-henry-newman.sexp
../lang/la.ini
../lang/en.ini
../lang/traditions.ini
diff --git a/test/test_amendments_of.ml b/test/test_amendments_of.ml
new file mode 100644
index 0000000..1ed21d9
--- /dev/null
+++ b/test/test_amendments_of.ml
@@ -0,0 +1,217 @@
+(* Task 2 (2026-08-25-colitur-of-phases-3-5): the post-2002 decree overlays.
+ data/of/calendar-2002.sexp (Task 1) transcribes the 2002 typical edition
+ and is never edited again -- every subsequent Calendarium Romanum Generale
+ change is its own overlay file under data/of/amendments/, one per decree,
+ per docs/research/of/PROVENANCE-amendments.md (13 decrees, 16
+ celebration-level changes -- the research inventory's own "15 items,
+ numbered 1-15, where items 10-12 are three entries carried by a single
+ decree" collapses to 13 distinct decrees once items 2/3, both dated 28
+ September 2002 but carrying DIFFERENT protocol numbers, are counted as the
+ two separate juridical instruments they are).
+
+ This suite asserts: every file parses; each has a pinned SHA-256;
+ applying all 13 in their own decree-chronological order to the base
+ calendar yields a pinned entry count; Overlay.merge reports NO diagnostic
+ (a diagnostic would mean a directive was transcribed against a slug that
+ does not exist in the base -- the exact silent failure one-file-per-decree
+ exists to prevent); and Mary, Mother of the Church resolves to the Monday
+ after Pentecost in three real, independently-computed years. *)
+
+module L = Colitur_kernel.Layer
+module O = Colitur_kernel.Overlay
+module Cel = Colitur_kernel.Celebration
+module S = Colitur_kernel.Slug
+module DS = Colitur_kernel.Date_spec
+module D = Colitur_kernel.Date
+module Computus = Colitur_kernel.Computus
+module Names = Colitur_kernel.Names
+module Lang = Colitur_kernel.Lang
+module V = Rite_of.Vocab_of
+
+let base_path = "../data/of/calendar-2002.sexp"
+let amendments_dir = "../data/of/amendments/"
+
+(* Decree-chronological order, matching docs/research/of/
+ PROVENANCE-amendments.md's own "Ordered by decree date" -- the numeric
+ filename prefixes already encode this, spelled out here explicitly so the
+ intended application order is visible in the test itself, not merely
+ inferred from a directory listing. Each paired with its SHA-256, pinned
+ 2026-08-26 against the shipped files themselves (`sha256sum
+ data/of/amendments/*.sexp`), not copied from any tool's own stdout. *)
+let files =
+ [ ("001-padre-pio.sexp",
+ "8ddd92f1820a736c7a4f3c27b3181579d6280ed82f0983f80219d523782731f6");
+ ("002-juan-diego-cuauhtlatoatzin.sexp",
+ "01000fe5615894ff82b89a099e1539d6556beccfe1d07d5664362b0126724b09");
+ ("003-our-lady-of-guadalupe.sexp",
+ "a19100769786d110d462805cc4533867c9d56308f8a058f46b257b2b0d6cb3ef");
+ ("004-john-xxiii-john-paul-ii.sexp",
+ "ae24ac41935600d0d11a81072bedce2ba9790b79e2f8192c5d4a08a9a7db4e6e");
+ ("005-mary-magdalene-rank.sexp",
+ "08a19050c21391ee565bc4d5a3ba228e3162875188db4bbc3b7f4b066a60a0c1");
+ ("006-mary-mother-of-the-church.sexp",
+ "8a1dda10c1014bc59c22779f3686c6cce0bf9ff1ec4e504cb912cf2c89319ff9");
+ ("007-paul-vi.sexp",
+ "d7b442b6b6dd6c8e7aca5f7126f7b3e65104191ae84c158e07e9afd0f70edcfc");
+ ("008-our-lady-of-loreto.sexp",
+ "772366fb6c04d1c779109d8b56fa1c0a71ff0129f92349564e1a353b253c2e13");
+ ("009-faustina-kowalska.sexp",
+ "a6bf8a1ab8e3f4aa65bb22d4ff9ba863e5f65865180444f4b143f36aa99e45b3");
+ ("010-narek-avila-hildegard.sexp",
+ "6ca11a7c2e02491b9b96349282c7b1d6fc28c9e4729f678bd54d11a70e43f568");
+ ("011-martha-mary-lazarus.sexp",
+ "c4ede10b24f22def5fd557a3627d1ecaeb5de583f263372a67bccf9ab838f023");
+ ("012-teresa-of-calcutta.sexp",
+ "5646597472f6170a2b56e1f1c4a2ef7e7917cb5c87eb5e3d1f98b8ee1aaae646");
+ ("013-john-henry-newman.sexp",
+ "f6c12d1ead043a609b0086a130ae1a9fc680a8926fe77ccd97756ee747105d7c") ]
+
+let sha256_of_file path =
+ let tmp = Filename.temp_file "colitur_amendments_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"
+
+let load_overlay 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
+
+let load_base () =
+ match L.load V.rank_of_sexp base_path with
+ | Ok l -> l
+ | Error e -> Alcotest.failf "%s: failed to load: %s" base_path e
+
+(* Every file parses. *)
+let test_files_parse () =
+ List.iter
+ (fun (name, _) ->
+ let (_ : V.rank O.t) = load_overlay name in
+ ())
+ files
+
+(* Each has a pinned SHA-256. *)
+let test_sha256_pinned () =
+ List.iter
+ (fun (name, expected) ->
+ Alcotest.(check string) (name ^ " SHA-256") expected
+ (sha256_of_file (amendments_dir ^ name)))
+ files
+
+(* Applying all 13, in decree-chronological order, to the base calendar
+ yields a pinned entry count, AND Overlay.merge reports no diagnostic --
+ the silent-no-op check the whole one-file-per-decree discipline exists
+ to enforce (a diagnostic here would mean a directive was transcribed
+ against a slug the base calendar does not actually have). *)
+let test_apply_in_order () =
+ let base = load_base () in
+ let overlays = List.map (fun (name, _) -> load_overlay name) files in
+ let merged, diagnostics = O.merge base overlays in
+ Alcotest.(check (list string)) "no diagnostics -- every directive matched something" []
+ (List.map O.diagnostic_to_string diagnostics);
+ (* 208 base entries + 14 Adds (1+1+1+2+1+1+1+1+3+1+1, files
+ 001/002/003/004/006/007/008/009/010x3/012/013) + 2 Edits (005, 011,
+ no count change) = 222. *)
+ Alcotest.(check int) "208 base + 14 adds = 222 entries" 222 (List.length merged.L.entries)
+
+(* Every new/edited slug this task introduces is actually present after
+ the merge, and the two Edits did not accidentally become Adds (no
+ "slug not present; edit ignored" diagnostic already ruled that out
+ above, but a direct spot-check on the merged layer is cheap insurance
+ against a slug typo that happened to also dodge the diagnostic, e.g. by
+ matching a DIFFERENT, wrong existing slug). *)
+let test_new_slugs_present () =
+ let base = load_base () in
+ let overlays = List.map (fun (name, _) -> load_overlay name) files in
+ let merged, _ = O.merge base overlays in
+ let has slug = L.mem merged (S.of_string_exn slug) in
+ List.iter
+ (fun slug -> Alcotest.(check bool) (slug ^ " present after merge") true (has slug))
+ [ "pio-of-pietrelcina-padre-pio-priest"; "juan-diego"; "our-lady-of-guadalupe";
+ "john-xxiii-pope"; "john-paul-ii-pope"; "mary-mother-of-the-church"; "paul-vi-pope";
+ "our-lady-of-loreto"; "faustina-kowalska-virgin"; "gregory-of-narek-abbot-and-doctor";
+ "john-of-avila-priest-and-doctor"; "hildegard-of-bingen-virgin-and-doctor";
+ "teresa-of-calcutta-virgin"; "john-henry-newman-priest-and-doctor" ];
+ (* The two Edits kept their original slugs. *)
+ match L.find merged (S.of_string_exn "mary-magdalene") with
+ | None -> Alcotest.fail "mary-magdalene: slug lost after Edit"
+ | Some e -> Alcotest.(check bool) "mary-magdalene is now Festum" true (e.L.cel.Cel.rank = V.Festum)
+
+let test_martha_mary_lazarus_renamed () =
+ let base = load_base () in
+ let overlays = List.map (fun (name, _) -> load_overlay name) files in
+ let merged, _ = O.merge base overlays in
+ match L.find merged (S.of_string_exn "martha") with
+ | None -> Alcotest.fail "martha: slug lost after Edit"
+ | Some e ->
+ Alcotest.(check (option string)) "en name widened" (Some "Saints Martha, Mary and Lazarus")
+ (Names.find e.L.cel.Cel.names (Lang.of_string_exn "en"));
+ Alcotest.(check bool) "date unchanged, 29 July" true
+ (e.L.date = (match DS.fixed ~month:7 ~day:29 with Ok d -> d | Error err -> failwith err));
+ Alcotest.(check bool) "rank unchanged, Memoria_obligatoria" true
+ (e.L.cel.Cel.rank = V.Memoria_obligatoria)
+
+(* Mary, Mother of the Church resolves to the Monday after Pentecost --
+ Easter+50 -- in three real, independently-computed years, not merely
+ trusted from the decree's own arithmetic. Pentecost is Easter+49 (the
+ 50th day of the Paschal season inclusive of Easter); the day after is
+ Easter+50. Checked structurally (weekday = Mon, and the resolved date is
+ exactly 50 days after that year's real Gregorian Easter, computed via
+ Colitur_kernel.Computus.gregorian_easter), not by hand-typing expected
+ calendar dates. *)
+let test_mater_ecclesiae_monday_after_pentecost () =
+ let base = load_base () in
+ let overlays = List.map (fun (name, _) -> load_overlay name) files in
+ let merged, _ = O.merge base overlays in
+ let entry =
+ match L.find merged (S.of_string_exn "mary-mother-of-the-church") with
+ | Some e -> e
+ | None -> Alcotest.fail "mary-mother-of-the-church: not found after merge"
+ in
+ Alcotest.(check bool) "date spec is Easter_offset 50" true (entry.L.date = DS.Easter_offset 50);
+ Alcotest.(check bool) "Memoria_obligatoria" true (entry.L.cel.Cel.rank = V.Memoria_obligatoria);
+ Alcotest.(check bool) "white" true (entry.L.cel.Cel.colour = Colitur_kernel.Colour.White);
+ Alcotest.(check bool) "subject Bvm" true (entry.L.cel.Cel.subject = Colitur_kernel.Subject.Bvm);
+ List.iter
+ (fun year ->
+ let easter = Computus.gregorian_easter year in
+ let pentecost = D.add_days easter 49 in
+ let expected = D.add_days easter 50 in
+ Alcotest.(check bool)
+ (Printf.sprintf "%d: Pentecost (Easter+49) is a Sunday" year)
+ true (D.weekday pentecost = D.Sun);
+ let resolved =
+ match DS.resolve entry.L.date ~year ~easter with
+ | Some d -> d
+ | None -> Alcotest.failf "%d: Easter_offset 50 did not resolve" year
+ in
+ Alcotest.(check bool)
+ (Printf.sprintf "%d: resolves to exactly Easter+50" year) true (resolved = expected);
+ Alcotest.(check bool)
+ (Printf.sprintf "%d: resolved date is a Monday" year) true (D.weekday resolved = D.Mon);
+ Alcotest.(check bool)
+ (Printf.sprintf "%d: resolved date is the day after Pentecost" year) true
+ (resolved = D.add_days pentecost 1))
+ [ 2026; 2027; 2035 ]
+
+let suite =
+ ( "Amendments_of (data/of/amendments/*.sexp)",
+ [ Alcotest.test_case "every overlay file parses" `Quick test_files_parse;
+ Alcotest.test_case "SHA-256 pinned per file" `Quick test_sha256_pinned;
+ Alcotest.test_case "apply in decree-chronological order: 222 entries, no diagnostics" `Quick
+ test_apply_in_order;
+ Alcotest.test_case "every new/edited slug is present after merge" `Quick
+ test_new_slugs_present;
+ Alcotest.test_case "Martha/Mary/Lazarus: renamed in place, date/rank unchanged" `Quick
+ test_martha_mary_lazarus_renamed;
+ Alcotest.test_case "Mary, Mother of the Church: Monday after Pentecost, 3 real years" `Quick
+ test_mater_ecclesiae_monday_after_pentecost ] )
diff --git a/test/test_colitur.ml b/test/test_colitur.ml
index c750e75..98e08fb 100644
--- a/test/test_colitur.ml
+++ b/test/test_colitur.ml
@@ -12,6 +12,7 @@ let () =
("sigla", Test_citation.sigla_suite);
Test_config.suite;
Test_overlay.suite; Test_overlay_ini.suite; Test_temporal_ef.suite; Test_temporal_of.suite; Test_litcal_of.suite; Test_precedence_of.suite;
+ Test_amendments_of.suite;
Test_validate.suite;
Test_precedence.suite;
Test_calendar.suite; Test_precedence_ef.suite; Test_sanctoral_ef.suite; Test_calendar_of_data.suite;