Finish the last 5 vigils: weekday-keyed commemoration antiphons
Deploy / deploy (push) Successful in 1m32s
Deploy / deploy (push) Successful in 1m32s
Corrected an earlier "no source exists" claim by live-querying real
commemorated instances of the Vigils of St. Lawrence and the Assumption
across six different weekdays. Their source files' own [Rule] block
("Versum Feria") turns out to be a real, sourced mechanism, not an
absence: a mere commemoration doesn't reuse the vigil's own antiphon at
all -- it borrows the plain ferial day's antiphon/versicle instead, and
that antiphon quotes the Benedictus canticle in weekday sequence (same
shape vespers-magnificat-antiphons.yml already uses for the Magnificat).
The versicle is a single fixed text. Sunday has no entry: a Vigil
transfers off an ordinary Sunday rather than ever reaching a
commemoration there, confirmed live as well as already true in this
app's own precedence rules.
sanctoralCommemorationPart now takes weekday and resolves this
dynamically for common-of-a-vigil saints, rather than needing a static
per-saint file. All 218 saints with an authored collect now have a real
commemoration antiphon.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# A mere commemoration of a Vigil (`common: common-of-a-vigil` — St.
|
||||
# Lawrence's, the Assumption's, All Saints', Ss. Simon and Jude's, St.
|
||||
# John the Baptist's) does NOT reuse that vigil's own antiphon (the one
|
||||
# used when it wins outright, e.g. vigil-of-st-lawrence-antiphon.yml) —
|
||||
# its own source file's [Rule] block says "Versum Feria" (borrow the
|
||||
# plain ferial day's own versicle/antiphon instead), confirmed live
|
||||
# (Monastic Tridentinum 1617): the Vigil of St. Lawrence's commemoration
|
||||
# on a real Monday (2027-08-09) and the Vigil of the Assumption's on six
|
||||
# different real weekdays (2026 Fri/2027 Sat/2028 Mon/2029 Tue/2030
|
||||
# Wed/2031 Thu) all gave the exact same result for their weekday — the
|
||||
# antiphon quotes the Benedictus canticle's own text in weekday sequence
|
||||
# (same "quote the framing canticle in order through the week" pattern
|
||||
# vespers-magnificat-antiphons.yml already uses for Vespers), same text
|
||||
# regardless of *which* vigil. Sunday has no entry: a Vigil (`FeastClass:
|
||||
# 'vigil'`, weaker than Semiduplex) never actually reaches a commemoration
|
||||
# on an ordinary Sunday in this app's own precedence rules either — it
|
||||
# transfers instead (calendar/commemorations.ts's `ordinary-sunday`
|
||||
# branch) — confirmed live too (2033-08-14, a real Sunday: the Vigil of
|
||||
# the Assumption doesn't appear at all, only the Lawrence-octave day is
|
||||
# commemorated).
|
||||
#
|
||||
# English: the reference engine's own English files have no translation
|
||||
# for this specific commemoration antiphon at all (checked across every
|
||||
# weekday) -- these are direct translations, informed by the Benedictus
|
||||
# canticle's own already-verified English (propers/common/benedictus.yml)
|
||||
# for vocabulary consistency, but not independently sourced -- `status`
|
||||
# marks them `draft` for that reason.
|
||||
|
||||
monday:
|
||||
antiphon:
|
||||
la: "Benedíctus Dóminus, Deus Israël."
|
||||
en: "Blessed be the Lord God of Israel."
|
||||
status: { la: verified, en: draft }
|
||||
|
||||
tuesday:
|
||||
antiphon:
|
||||
la: "Eréxit nobis * Dóminus cornu salútis in domo David púeri sui."
|
||||
en: "The Lord hath raised up for us * a horn of salvation in the house of David his servant."
|
||||
status: { la: verified, en: draft }
|
||||
|
||||
wednesday:
|
||||
antiphon:
|
||||
la: "De manu ómnium qui odérunt nos, líbera nos Dómine."
|
||||
en: "From the hand of all that hate us, deliver us, O Lord."
|
||||
status: { la: verified, en: draft }
|
||||
|
||||
thursday:
|
||||
antiphon:
|
||||
la: "In sanctitáte serviámus Dómino, et liberábit nos ab inimícis nostris."
|
||||
en: "Let us serve the Lord in holiness, and he will deliver us from our enemies."
|
||||
status: { la: verified, en: draft }
|
||||
|
||||
friday:
|
||||
antiphon:
|
||||
la: "Per víscera misericórdiæ Dei nostri visitávit nos Óriens ex alto."
|
||||
en: "Through the tender mercy of our God, the Dayspring from on high hath visited us."
|
||||
status: { la: verified, en: draft }
|
||||
|
||||
saturday:
|
||||
antiphon:
|
||||
la: "Illumináre, Dómine, his qui in ténebris sedent: et dírige pedes nostros in viam pacis, Deus Israël."
|
||||
en: "Give light, O Lord, to them that sit in darkness: and direct our feet into the way of peace, O God of Israel."
|
||||
status: { la: verified, en: draft }
|
||||
@@ -10,6 +10,7 @@ import { splitAntiphon, isDoubleOrHigher } from './antiphon';
|
||||
import { getLaudsSaintOverride } from './lauds-psalmody-overrides';
|
||||
import vespersMagnificatAntiphonsData from '../data/hours/vespers-magnificat-antiphons.yml';
|
||||
import vespersOAntiphonsData from '../data/hours/vespers-o-antiphons.yml';
|
||||
import laudsVigilCommemorationAntiphonsData from '../data/hours/lauds-vigil-commemoration-antiphons.yml';
|
||||
|
||||
type BilingualText = Partial<Record<string, string>>;
|
||||
type TranslationStatus = 'verified' | 'draft' | 'missing';
|
||||
@@ -26,6 +27,10 @@ const vespersMagnificatAntiphons = vespersMagnificatAntiphonsData as Partial<
|
||||
// these seven can't live in a per-Advent-week temporal-proper file the
|
||||
// way every other week's Magnificat antiphon does.
|
||||
const vespersOAntiphons = vespersOAntiphonsData as Partial<Record<string, MagnificatWeekdayDefault>>;
|
||||
// Monday-Saturday only — see lauds-vigil-commemoration-antiphons.yml's own
|
||||
// header for why Sunday has no entry (a Vigil never reaches a
|
||||
// commemoration on an ordinary Sunday in the first place).
|
||||
const vigilCommemorationAntiphons = laudsVigilCommemorationAntiphonsData as Partial<Record<Weekday, MagnificatWeekdayDefault>>;
|
||||
|
||||
function toResolvedText(proper: ProperText): ResolvedText {
|
||||
return { text: proper.text, status: proper.status, citation: proper.citation };
|
||||
@@ -597,6 +602,41 @@ export function getDayCollect(day: LiturgicalDay): ResolvedText {
|
||||
return { text: {}, status: { la: 'missing', en: 'missing' } };
|
||||
}
|
||||
|
||||
/** A Vigil (`common: common-of-a-vigil`) doesn't reuse its own antiphon
|
||||
* when merely commemorated — its own source file's `[Rule]` says "Versum
|
||||
* Feria" (borrow the plain ferial day's own antiphon/versicle instead),
|
||||
* confirmed live across six different real weekdays (see
|
||||
* data/hours/lauds-vigil-commemoration-antiphons.yml's own header for the
|
||||
* dates checked) — the antiphon quotes the Benedictus canticle in weekday
|
||||
* sequence (same pattern vespers-magnificat-antiphons.yml already uses
|
||||
* for the Magnificat), same text regardless of *which* vigil, and the
|
||||
* versicle is a single fixed text (`lauds-versicle-monday.yml`'s own,
|
||||
* confirmed identical even on a live Saturday, so genuinely constant, not
|
||||
* itself weekday-keyed despite superficially matching most weekdays'
|
||||
* plain ferial versicle). Sunday has no entry — a Vigil never reaches a
|
||||
* commemoration on an ordinary Sunday in this app's own precedence rules
|
||||
* either (calendar/commemorations.ts's `ordinary-sunday` branch
|
||||
* transfers it instead), confirmed live too. */
|
||||
function vigilCommemorationAntiphon(weekday: Weekday): ResolvedText | undefined {
|
||||
const entry = vigilCommemorationAntiphons[weekday];
|
||||
return entry ? (entry.status ? { text: entry.antiphon, status: entry.status } : verifiedText(entry.antiphon)) : undefined;
|
||||
}
|
||||
|
||||
function combineCommemorationBundle(antiphon: ResolvedText, versicle: ResolvedText, collect: ResolvedText): ResolvedText {
|
||||
const text: Partial<Record<string, string>> = {};
|
||||
const status: Partial<Record<string, 'verified' | 'draft' | 'missing'>> = {};
|
||||
for (const lang of new Set([...Object.keys(antiphon.text), ...Object.keys(versicle.text), ...Object.keys(collect.text)])) {
|
||||
const parts = [antiphon, versicle, collect].map((t) => t.text[lang]).filter((t): t is string => !!t);
|
||||
if (parts.length === 0) continue;
|
||||
text[lang] = `Ant. ${parts[0] ?? ''}\n${parts[1] ?? ''}\n${parts[2] ?? ''}`.trim();
|
||||
const statuses = [antiphon.status[lang], versicle.status[lang], collect.status[lang]].filter(
|
||||
(s): s is 'verified' | 'draft' | 'missing' => !!s,
|
||||
);
|
||||
status[lang] = statuses.reduce((worst, s) => (STATUS_RANK[s] > STATUS_RANK[worst] ? s : worst), 'verified' as const);
|
||||
}
|
||||
return { text, status };
|
||||
}
|
||||
|
||||
/** A sanctoral commemoration's own rendering: the fuller Ant+V/R+collect
|
||||
* bundle (`${propers}-commemoration`, e.g. st-clare-commemoration.yml)
|
||||
* when authored — live-verified this is the real shape a commemoration
|
||||
@@ -605,8 +645,13 @@ export function getDayCollect(day: LiturgicalDay): ResolvedText {
|
||||
* replaces) when only that's been authored, and to an honestly labeled
|
||||
* "missing" block when neither has. Always labeled ("Commemoration of St.
|
||||
* X") so an unauthored one reads as "this saint's commemoration isn't
|
||||
* written up yet," not as a mystery blank prayer. */
|
||||
function sanctoralCommemorationPart(commemoration: Extract<Commemoration, { kind: 'sanctoral' }>): ResolvedPart {
|
||||
* written up yet," not as a mystery blank prayer. A Vigil is a special
|
||||
* case within this same fallback chain: see vigilCommemorationAntiphon's
|
||||
* own doc comment. */
|
||||
function sanctoralCommemorationPart(
|
||||
commemoration: Extract<Commemoration, { kind: 'sanctoral' }>,
|
||||
weekday: Weekday,
|
||||
): ResolvedPart {
|
||||
const label = `Commemoration of ${commemoration.name}`;
|
||||
const saint = getSaintRecord(commemoration.id);
|
||||
if (saint?.propers) {
|
||||
@@ -616,6 +661,13 @@ function sanctoralCommemorationPart(commemoration: Extract<Commemoration, { kind
|
||||
}
|
||||
const properCollect = resolveCommon(`${saint.propers}-collect`);
|
||||
if (properCollect.status.la !== 'missing' || properCollect.status.en !== 'missing') {
|
||||
if (saint.common === 'common-of-a-vigil') {
|
||||
const antiphon = vigilCommemorationAntiphon(weekday);
|
||||
if (antiphon) {
|
||||
const versicle = resolveCommon('lauds-versicle-monday');
|
||||
return { kind: 'preces', text: combineCommemorationBundle(antiphon, versicle, properCollect), label };
|
||||
}
|
||||
}
|
||||
return { kind: 'preces', text: properCollect, label };
|
||||
}
|
||||
}
|
||||
@@ -693,7 +745,7 @@ export function getDayCollects(day: LiturgicalDay): ResolvedPart[] {
|
||||
if (commemoration.kind === 'temporal') {
|
||||
parts.push({ kind: 'prayer', text: toResolvedText(getTemporalProper(`${commemoration.id}-collect`)) });
|
||||
} else if (commemoration.kind === 'sanctoral') {
|
||||
parts.push(sanctoralCommemorationPart(commemoration));
|
||||
parts.push(sanctoralCommemorationPart(commemoration, day.weekday));
|
||||
} else if (commemoration.kind === 'octave' && commemoration.id !== substitutedOctaveId) {
|
||||
parts.push(octaveCommemorationPart(commemoration));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user