Add Paschaltide-variant fallback for minor-hour Commons
Deploy / deploy (push) Failing after 57s

Confirms and formalizes what TODO.md had flagged as an open question:
the reference engine's own source has explicit Paschaltide variants
(Commune/C1p.txt, C2p.txt, C3p.txt -- "tempore Paschali") for exactly 3
of its 12 Common categories -- Apostles, a Martyr-Bishop, Several
Martyrs -- a real liturgical restriction of Alleluia/victory imagery to
apostles and martyrs, not a coincidence.

resolveMinorHourAntiphon/resolveMinorHourChapter now try a
`${minorHoursCommon}-paschaltide` variant first whenever day.season is
eastertide/ascensiontide/pentecost (the same three-season window as
Compline's own Regina Caeli table, since "tempore paschali" runs through
the Pentecost octave in both), falling back to the plain Common when no
variant is authored.

common-of-apostles-paschaltide (7 files) ported directly from the
reference engine's own Commune/C1p.txt source files rather than
live-queried, then cross-checked against st-mark's already-authored,
live-queried content -- identical except one antiphon's asterisk, which
the source places one word earlier; corrected to match. st-mark and
st-john-before-the-latin-gate's duplicate per-saint files removed
entirely; ss-philip-and-james's chapter files removed (its antiphons
stay proper).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 16:03:06 -04:00
parent 735f677815
commit bcae61568a
26 changed files with 151 additions and 202 deletions
@@ -6,3 +6,4 @@ name: "Ss. Philip and James, Apostles"
rank: duplex-2-classis
common: common-of-an-apostle
propers: "ss-philip-and-james"
minorHoursCommon: common-of-apostles
@@ -9,3 +9,4 @@ name: "St. John Before the Latin Gate"
rank: duplex-majus
common: common-of-an-apostle
propers: "st-john-before-the-latin-gate"
minorHoursCommon: common-of-apostles
+1
View File
@@ -11,3 +11,4 @@ name: "St. Mark, Evangelist"
rank: duplex-2-classis
common: common-of-an-evangelist
propers: "st-mark"
minorHoursCommon: common-of-apostles
@@ -0,0 +1,12 @@
# Verified against the reference engine's own source data files:
# web/www/horas/Latin/Commune/C1p.txt and English/Commune/C1p.txt, 2026-08
# -- see prime-antiphon-common-of-apostles-paschaltide.yml's header. C1p's
# own [Ant Vespera] has 5 antiphons cycled across the hours; this is the
# 5th (4th, "Spíritus et ánimæ...", is used elsewhere, not at None).
id: none-antiphon-common-of-apostles-paschaltide
text:
la: "Fulgébunt justi * sicut sol in conspéctu Dei, allelúja."
en: "The just shine * like the sun at the face of God, alleluia."
status:
la: verified
en: verified
@@ -1,11 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), None
# live query, St. John Before the Latin Gate's own day (2026-05-06,
# clean year) -- same Common-of-Martyrs text as St. Mark's own, confirmed
# identical directly.
id: none-antiphon-st-john-before-the-latin-gate
text:
la: "Fulgébunt justi * sicut sol in conspéctu Dei, allelúja."
en: "The just shine * like the sun at the face of God, alleluia."
status:
la: verified
en: verified
@@ -1,9 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), None
# live query, St. Mark's own day (2026-04-25, clean year).
id: none-antiphon-st-mark
text:
la: "Fulgébunt justi * sicut sol in conspéctu Dei, allelúja."
en: "The just shine * like the sun at the face of God, alleluia."
status:
la: verified
en: verified
@@ -1,6 +1,9 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), None
# live query, St. Mark's own day (2026-04-25, clean year).
id: none-capitulum-st-mark
# Verified against the reference engine's own source data files:
# web/www/horas/Latin/Commune/C1p.txt and English/Commune/C1p.txt, 2026-08
# -- see prime-antiphon-common-of-apostles-paschaltide.yml's header (C1p's
# own [Lectio Prima]/[Nocturn 3 Versum] sections, reached at None via
# [Capitulum Nona]'s `@:Lectio Prima` reference).
id: none-capitulum-common-of-apostles-paschaltide
text:
la: "Scimus quóniam diligéntibus Deum ómnia cooperántur in bonum, iis qui secúndum propósitum vocáti sunt sancti. R. Deo grátias. V. Lætítia sempitérna super cápita eórum, allelúja. R. Gáudium et exsultatiónem obtinébunt, allelúja."
en: "And we know that to them that love God, all things work together unto good, to such as, according to his purpose, are called to be saints. R. Thanks be to God. V. Everlasting joy shall be upon their heads, alleluia. R. They shall obtain joy and gladness, alleluia."
@@ -1,13 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), None
# live query, Ss. Philip and James's own day (2026-05-01, clean year) --
# same Common-of-Apostles text as St. Mark's own.
id: none-capitulum-ss-philip-and-james
text:
la: "Scimus quóniam diligéntibus Deum ómnia cooperántur in bonum, iis qui secúndum propósitum vocáti sunt sancti. R. Deo grátias. V. Lætítia sempitérna super cápita eórum, allelúja. R. Gáudium et exsultatiónem obtinébunt, allelúja."
en: "And we know that to them that love God, all things work together unto good, to such as, according to his purpose, are called to be saints. R. Thanks be to God. V. Everlasting joy shall be upon their heads, alleluia. R. They shall obtain joy and gladness, alleluia."
citation:
la: "Rom 8:28"
en: "Rom 8:28"
status:
la: verified
en: verified
@@ -1,14 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), None
# live query, St. John Before the Latin Gate's own day (2026-05-06,
# clean year) -- same Common-of-Martyrs text as St. Mark's own, confirmed
# identical directly.
id: none-capitulum-st-john-before-the-latin-gate
text:
la: "Scimus quóniam diligéntibus Deum ómnia cooperántur in bonum, iis qui secúndum propósitum vocáti sunt sancti. R. Deo grátias. V. Lætítia sempitérna super cápita eórum, allelúja. R. Gáudium et exsultatiónem obtinébunt, allelúja."
en: "And we know that to them that love God, all things work together unto good, to such as, according to his purpose, are called to be saints. R. Thanks be to God. V. Everlasting joy shall be upon their heads, alleluia. R. They shall obtain joy and gladness, alleluia."
citation:
la: "Rom 8:28"
en: "Rom 8:28"
status:
la: verified
en: verified
@@ -0,0 +1,19 @@
# Verified against the reference engine's own source data files (not a
# live query): web/www/horas/Latin/Commune/C1p.txt and English/Commune/
# C1p.txt ("Commune Apostolorum tempore Paschali"), 2026-08. Cross-checked
# against st-mark's already-authored, live-queried content (2026-04-25) --
# identical except this source's own asterisk falls one word earlier
# ("Sancti tui, * Dómine..." not "Sancti tui, Dómine, * ...") -- trusted
# over the live-rendered incipit split, per resolveMinorHourAntiphon's own
# Paschaltide-variant fallback (hours/resolve-common.ts) and
# SaintRecord.minorHoursCommon (calendar/feasts.ts). See TODO.md for which
# saints (st-mark, st-john-before-the-latin-gate, ss-philip-and-james)
# reach this file and why only Apostles/Martyr-Bishop/Several-Martyrs
# commons have a Paschaltide variant at all.
id: prime-antiphon-common-of-apostles-paschaltide
text:
la: "Sancti tui, * Dómine, florébunt sicut lílium, allelúja: et sicut odor bálsami erunt ante te, allelúja."
en: "Your saints, O Lord, * flourish like lilies, alleluia: and like the smell of balsam are before you, alleluia."
status:
la: verified
en: verified
@@ -1,11 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Prime
# live query, St. John Before the Latin Gate's own day (2026-05-06,
# clean year) -- same Common-of-Martyrs text as St. Mark's own
# (2026-04-25), confirmed identical directly, not assumed.
id: prime-antiphon-st-john-before-the-latin-gate
text:
la: "Sancti tui, Dómine, * florébunt sicut lílium, allelúja: et sicut odor bálsami erunt ante te, allelúja."
en: "Your saints, O Lord, * flourish like lilies, alleluia: and like the smell of balsam are before you, alleluia."
status:
la: verified
en: verified
@@ -1,9 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Prime
# live query, St. Mark's own day (2026-04-25, clean year).
id: prime-antiphon-st-mark
text:
la: "Sancti tui, Dómine, * florébunt sicut lílium, allelúja: et sicut odor bálsami erunt ante te, allelúja."
en: "Your saints, O Lord, * flourish like lilies, alleluia: and like the smell of balsam are before you, alleluia."
status:
la: verified
en: verified
@@ -0,0 +1,10 @@
# Verified against the reference engine's own source data files:
# web/www/horas/Latin/Commune/C1p.txt and English/Commune/C1p.txt, 2026-08
# -- see prime-antiphon-common-of-apostles-paschaltide.yml's header.
id: sext-antiphon-common-of-apostles-paschaltide
text:
la: "In velaménto * clamábant Sancti tui, Dómine, allelúja, allelúja, allelúja."
en: "Protected by a veil * your saints turn to you, O Lord, alleluia, alleluia."
status:
la: verified
en: verified
@@ -1,11 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Sext
# live query, St. John Before the Latin Gate's own day (2026-05-06,
# clean year) -- same Common-of-Martyrs text as St. Mark's own, confirmed
# identical directly.
id: sext-antiphon-st-john-before-the-latin-gate
text:
la: "In velaménto * clamábant Sancti tui, Dómine, allelúja, allelúja, allelúja."
en: "Protected by a veil * your saints turn to you, O Lord, alleluia, alleluia."
status:
la: verified
en: verified
@@ -1,9 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Sext
# live query, St. Mark's own day (2026-04-25, clean year).
id: sext-antiphon-st-mark
text:
la: "In velaménto * clamábant Sancti tui, Dómine, allelúja, allelúja, allelúja."
en: "Protected by a veil * your saints turn to you, O Lord, alleluia, alleluia."
status:
la: verified
en: verified
@@ -1,7 +1,8 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Sext
# live query, Ss. Philip and James's own day (2026-05-01, clean year) --
# same Common-of-Apostles text as St. Mark's own.
id: sext-capitulum-ss-philip-and-james
# Verified against the reference engine's own source data files:
# web/www/horas/Latin/Commune/C1p.txt and English/Commune/C1p.txt, 2026-08
# -- see prime-antiphon-common-of-apostles-paschaltide.yml's header (C1p's
# own [Capitulum Sexta]/[Nocturn 2 Versum] sections).
id: sext-capitulum-common-of-apostles-paschaltide
text:
la: "Ecce quómodo computáti sunt inter fílios Dei, et inter sanctos sors illórum est. R. Deo grátias. V. Lux perpétua lucébit Sanctis tuis, Dómine, allelúja. R. Et ætérnitas témporum, allelúja."
en: "Behold how they are numbered among the children of God, and their lot is among the saints. R. Thanks be to God. V. Eternal light will shine over your saints, O Lord, alleluia. R. And the eternity of times, alleluia."
@@ -1,14 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Sext
# live query, St. John Before the Latin Gate's own day (2026-05-06,
# clean year) -- same Common-of-Martyrs text as St. Mark's own, confirmed
# identical directly.
id: sext-capitulum-st-john-before-the-latin-gate
text:
la: "Ecce quómodo computáti sunt inter fílios Dei, et inter sanctos sors illórum est. R. Deo grátias. V. Lux perpétua lucébit Sanctis tuis, Dómine, allelúja. R. Et ætérnitas témporum, allelúja."
en: "Behold how they are numbered among the children of God, and their lot is among the saints. R. Thanks be to God. V. Eternal light will shine over your saints, O Lord, alleluia. R. And the eternity of times, alleluia."
citation:
la: "Sap 5:5"
en: "Wis 5:5"
status:
la: verified
en: verified
@@ -1,12 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Sext
# live query, St. Mark's own day (2026-04-25, clean year).
id: sext-capitulum-st-mark
text:
la: "Ecce quómodo computáti sunt inter fílios Dei, et inter sanctos sors illórum est. R. Deo grátias. V. Lux perpétua lucébit Sanctis tuis, Dómine, allelúja. R. Et ætérnitas témporum, allelúja."
en: "Behold how they are numbered among the children of God, and their lot is among the saints. R. Thanks be to God. V. Eternal light will shine over your saints, O Lord, alleluia. R. And the eternity of times, alleluia."
citation:
la: "Sap 5:5"
en: "Wis 5:5"
status:
la: verified
en: verified
@@ -0,0 +1,14 @@
# Verified against the reference engine's own source data files:
# web/www/horas/Latin/Commune/C1p.txt and English/Commune/C1p.txt, 2026-08
# -- see prime-antiphon-common-of-apostles-paschaltide.yml's header. The
# source's own English rendering has no asterisk at all for this line (a
# real gap in that file, not a capture error) -- placed here to match the
# Latin split's own sense, same as st-mark's already-authored terce
# antiphon this matches exactly.
id: terce-antiphon-common-of-apostles-paschaltide
text:
la: "In cæléstibus regnis * Sanctórum habitátio est, allelúja: et in ætérnum réquies eórum, allelúja."
en: "In the heavenly kingdom * is the habitation of the saints, alleluia: and they rest in the eternity, alleluia."
status:
la: verified
en: verified
@@ -1,11 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Terce
# live query, St. John Before the Latin Gate's own day (2026-05-06,
# clean year) -- same Common-of-Martyrs text as St. Mark's own, confirmed
# identical directly.
id: terce-antiphon-st-john-before-the-latin-gate
text:
la: "In cæléstibus regnis * Sanctórum habitátio est, allelúja: et in ætérnum réquies eórum, allelúja."
en: "In the heavenly kingdom * is the habitation of the saints, alleluia: and they rest in the eternity, alleluia."
status:
la: verified
en: verified
@@ -1,13 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Terce
# live query, St. Mark's own day (2026-04-25, clean year). The source's
# own English rendered the same full sentence for both its "incipit" and
# full lines (no separate truncation there, unlike the Latin) -- the "*"
# position below is placed to match the Latin split's own sense, not a
# second source line.
id: terce-antiphon-st-mark
text:
la: "In cæléstibus regnis * Sanctórum habitátio est, allelúja: et in ætérnum réquies eórum, allelúja."
en: "In the heavenly kingdom * is the habitation of the saints, alleluia: and they rest in the eternity, alleluia."
status:
la: verified
en: verified
@@ -1,9 +1,9 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Terce
# live query, Ss. Philip and James's own day (2026-05-01, clean year) --
# same Common-of-Apostles text as St. Mark's own (2026-04-25), a
# separate file per this codebase's usual per-saint convention even
# where the underlying Common produces identical wording.
id: terce-capitulum-ss-philip-and-james
# Verified against the reference engine's own source data files:
# web/www/horas/Latin/Commune/C1p.txt and English/Commune/C1p.txt, 2026-08
# -- see prime-antiphon-common-of-apostles-paschaltide.yml's header (C1p's
# own [Capitulum Laudes]/[Versum 1] sections -- Terce's chapter equals
# Lauds' in the Monastic tradition).
id: terce-capitulum-common-of-apostles-paschaltide
text:
la: "Stabunt justi in magna constántia advérsus eos qui se angustiavérunt et qui abstulérunt labóres eórum. R. Deo grátias. V. Sancti et justi in Dómino gaudéte, allelúja. R. Vos elégit Deus in hereditátem sibi, allelúja."
en: "Then shall the just stand with great constancy against those that have afflicted them, and taken away their labours. R. Thanks be to God. V. Saints and just, rejoice in the Lord, alleluia. R. The Lord has chosen you for his inheritance, alleluia."
@@ -1,14 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Terce
# live query, St. John Before the Latin Gate's own day (2026-05-06,
# clean year) -- same Common-of-Martyrs text as St. Mark's own, confirmed
# identical directly.
id: terce-capitulum-st-john-before-the-latin-gate
text:
la: "Stabunt justi in magna constántia advérsus eos qui se angustiavérunt et qui abstulérunt labóres eórum. R. Deo grátias. V. Sancti et justi in Dómino gaudéte, allelúja. R. Vos elégit Deus in hereditátem sibi, allelúja."
en: "Then shall the just stand with great constancy against those that have afflicted them, and taken away their labours. R. Thanks be to God. V. Saints and just, rejoice in the Lord, alleluia. R. The Lord has chosen you for his inheritance, alleluia."
citation:
la: "Sap 5:1"
en: "Wis 5:1"
status:
la: verified
en: verified
@@ -1,12 +0,0 @@
# Verified against Divinum Officium (Monastic Tridentinum 1617), Terce
# live query, St. Mark's own day (2026-04-25, clean year).
id: terce-capitulum-st-mark
text:
la: "Stabunt justi in magna constántia advérsus eos qui se angustiavérunt et qui abstulérunt labóres eórum. R. Deo grátias. V. Sancti et justi in Dómino gaudéte, allelúja. R. Vos elégit Deus in hereditátem sibi, allelúja."
en: "Then shall the just stand with great constancy against those that have afflicted them, and taken away their labours. R. Thanks be to God. V. Saints and just, rejoice in the Lord, alleluia. R. The Lord has chosen you for his inheritance, alleluia."
citation:
la: "Sap 5:1"
en: "Wis 5:1"
status:
la: verified
en: verified
+38 -8
View File
@@ -111,14 +111,31 @@ export function getMinorHourOverrideId(day: LiturgicalDay): string | undefined {
return undefined;
}
/**
* "Tempore Paschali" — the reference engine's own window for a Common's
* Paschaltide variant (Commune/C1p.txt etc.: only Apostles, a Martyr-
* Bishop, and Several Martyrs get one — Confessors/Virgins/Doctors never
* do, matching the real tradition's own restriction of Alleluia/victory
* imagery to apostles and martyrs specifically). Deliberately the same
* three-season set as Compline's own Marian-antiphon table
* (`data/hours/marian-antiphon-by-season.yml`'s `eastertide`/
* `ascensiontide`/`pentecost` all mapping to Regina Caeli, not just
* `eastertide` alone) — "Paschalis" runs through the end of the Pentecost
* octave in both cases, not just to Ascension.
*/
const PASCHALTIDE_SEASONS = new Set(['eastertide', 'ascensiontide', 'pentecost']);
/** A Little Hour's (or Prime's) plain per-weekday antiphon, overridden by
* a duplex-majus+ feast's own proper (`${hourId}-antiphon-${id}`) when
* authored, then by that saint's shared Common (`${hourId}-antiphon-
* ${minorHoursCommon}`, see SaintRecord's own doc comment) when a proper
* one hasn't been authored — same honest "not gated behind whether
* content exists, just eligible to override at all" fallback as every
* other override in this codebase: an eligible feast with neither
* authored yet just falls through to the plain weekday default silently.
* ${minorHoursCommon}`, see SaintRecord's own doc comment) — tried first
* in its Paschaltide-variant form (`${minorHoursCommon}-paschaltide`)
* when the day falls in Paschaltide and that variant has been authored,
* per PASCHALTIDE_SEASONS's own doc comment — when a proper one hasn't
* been authored — same honest "not gated behind whether content exists,
* just eligible to override at all" fallback as every other override in
* this codebase: an eligible feast with none of these authored yet just
* falls through to the plain weekday default silently.
*/
export function resolveMinorHourAntiphon(
hourId: string,
@@ -133,6 +150,12 @@ export function resolveMinorHourAntiphon(
}
const commonId = getSaintRecord(overrideId)?.minorHoursCommon;
if (commonId) {
if (PASCHALTIDE_SEASONS.has(day.season)) {
const paschal = resolveCommon(`${hourId}-antiphon-${commonId}-paschaltide`);
if (paschal.status.la !== 'missing' || paschal.status.en !== 'missing') {
return paschal;
}
}
const common = resolveCommon(`${hourId}-antiphon-${commonId}`);
if (common.status.la !== 'missing' || common.status.en !== 'missing') {
return common;
@@ -147,9 +170,10 @@ export function resolveMinorHourAntiphon(
/** Same idea as resolveMinorHourAntiphon, for the chapter
* (`${hourId}-capitulum-${id}`, then `${hourId}-capitulum-
* ${minorHoursCommon}`) — falls back to `fallbackId` (the plain
* per-annum/per-weekday one already in place for that hour) when nothing
* eligible is authored, either proper or shared-Common. */
* ${minorHoursCommon}`, tried Paschaltide-variant-first the same way) —
* falls back to `fallbackId` (the plain per-annum/per-weekday one already
* in place for that hour) when nothing eligible is authored, either
* proper or shared-Common. */
export function resolveMinorHourChapter(hourId: string, day: LiturgicalDay, fallbackId: string): ResolvedText {
const overrideId = getMinorHourOverrideId(day);
if (overrideId) {
@@ -159,6 +183,12 @@ export function resolveMinorHourChapter(hourId: string, day: LiturgicalDay, fall
}
const commonId = getSaintRecord(overrideId)?.minorHoursCommon;
if (commonId) {
if (PASCHALTIDE_SEASONS.has(day.season)) {
const paschal = resolveCommon(`${hourId}-capitulum-${commonId}-paschaltide`);
if (paschal.status.la !== 'missing' || paschal.status.en !== 'missing') {
return paschal;
}
}
const common = resolveCommon(`${hourId}-capitulum-${commonId}`);
if (common.status.la !== 'missing' || common.status.en !== 'missing') {
return common;