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
+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;