Add per-feast Vespers office overrides for all 30 duplex-majus+ ids

Same eligibility rule as Lauds' psalmody override (a duplex-majus+
saint, or a named temporal feast), factored out to
resolve-common.ts's getOfficeOverrideId since Vespers has no
psalmody-override table of its own to piggyback eligibility on.

Authored via one live command=prayVespera query per id, reusing the
same clean per-saint dates already established for each one's Lauds
office-bundle override. The capitulum turned out to be byte-identical
between Lauds and Vespers for every one of the 30 ids checked, a real
Monastic-rite fact rather than a coincidence — so no
vespers-capitulum-<id>.yml files exist at all; the chapter falls
through to the already-authored lauds-capitulum-<id> directly instead
of duplicating identical content.

St. Scholastica's Vespers responsory, hymn, and versicle needed a hand
translation (same gap she has at Lauds/Terce/Sext/None — the reference
engine has no English for any of her proper content). Two more
one-line English gaps in the shared Immaculate Conception/Nativity of
the BVM responsory were filled with the standard Douay-Rheims/Ave
Maria wording.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 21:31:59 -04:00
parent 4d88568c42
commit 53582f1ded
94 changed files with 2962 additions and 34 deletions
+25 -1
View File
@@ -3,7 +3,7 @@ import type { Commemoration, DayWinner, LiturgicalDay, Weekday } from '../calend
import type { ProperText } from '../propers';
import { getCommonProper, getTemporalProper } from '../propers';
import { getSaintRecord } from '../calendar/feasts';
import { resolveActiveOctave, activeOctavesFor } from '../calendar';
import { resolveActiveOctave, activeOctavesFor, isAtLeast } from '../calendar';
import { getTemporalFeastRecord } from '../calendar/temporal-feasts';
import { splitAntiphon } from './antiphon';
import vespersMagnificatAntiphonsData from '../data/hours/vespers-magnificat-antiphons.yml';
@@ -131,6 +131,30 @@ export function isFerialOrVigil(day: LiturgicalDay): boolean {
return day.weekday !== 'sunday' && !isWithinAnOctave && (isVigil || isBareFeria);
}
/**
* A duplex-majus+ saint's own id, or one of the named temporal feasts in
* ALWAYS_OVERRIDE_TEMPORAL_IDS — the same rank-eligibility test
* hours/lauds.ts's getPsalmodyOverrideFor uses (and originally
* duplicated), factored out here so hours/vespers.ts's own per-feast
* office override (chapter/responsory/hymn/versicle — Vespers has no
* psalmody-override table of its own to piggyback eligibility on, unlike
* Lauds) can share the identical eligibility rule. Callers still decide
* for themselves whether anything's actually been authored for the id
* returned — same honest incremental-content convention as everywhere
* else; this only answers "is this day's winner eligible to override at
* all," not "does an override exist."
*/
export function getOfficeOverrideId(day: LiturgicalDay): string | undefined {
const winner = resolveOfficeWinner(day);
if (winner.kind === 'temporal' && ALWAYS_OVERRIDE_TEMPORAL_IDS.has(winner.id)) {
return winner.id;
}
if (winner.kind === 'sanctoral' && isAtLeast(winner.rank, 'duplex-majus')) {
return winner.id;
}
return undefined;
}
/**
* The id to look up for today's office winner's (resolveOfficeWinner)
* minor-hour content (antiphon + chapter) — `${hourId}-antiphon-${id}`/