Author full Christmas-Octave Sunday content, fix a temporal-id override gap
Deploy / deploy (push) Successful in 57s

christmas-octave-sunday previously had only its Benedictus antiphon
authored -- no Lauds psalmody override or office bundle, no Prime/Terce/
Sext/None content at all. Adds the full set: Lauds psalmody (3 psalms +
Canticle of the Three Young Men + Laudate, all distinct antiphons),
Lauds capitulum/versicle/hymn ("A solis ortus cardine"), and Prime/Terce/
Sext/None antiphons+chapters (Terce/Sext/None only, matching Gal
4:1-2/4:4-5/4:7 -- the same reading the raw Monastic Tridentinum 1617
source file gives for this Sunday).

Real code gap found and fixed along the way: getMinorHourOverrideId
(hours/resolve-common.ts) only checked the sanctoral branch of
resolveOfficeWinner's result, so a named temporal feast in
ALWAYS_OVERRIDE_TEMPORAL_IDS (marian-saturday, christ-the-king) got a
Lauds psalmody override but silently never a Prime/Terce/Sext/None one,
however much was authored for it. Fixed by mirroring
getPsalmodyOverrideFor's own temporal-id branch (hours/lauds.ts), and
christmas-octave-sunday added to that set.

Content sourced from a "Divino Afflatu 1954" live query rather than
Monastic Tridentinum 1617, since 1617 has no real identity of its own for
this Sunday under its own calendar rules on most Dec 26-29 dates (only
the collect, already authored separately, happened to be pulled from a
date where 1617 did render it) -- consistent with this app's stated
precedent of following D.A. for calendar/precedence even while keeping
1617's shape for the hours themselves elsewhere.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 16:16:33 -04:00
parent bcae61568a
commit 6bab6047c1
14 changed files with 304 additions and 1 deletions
+12 -1
View File
@@ -20,7 +20,7 @@ export function resolveCommon(id: string): ResolvedText {
// override-eligible — see hours/lauds.ts's getPsalmodyOverrideFor, which
// shares this set (imported from here, not duplicated) since it's the
// same "does this temporal identity carry its own real office" question.
export const ALWAYS_OVERRIDE_TEMPORAL_IDS = new Set(['marian-saturday', 'christ-the-king']);
export const ALWAYS_OVERRIDE_TEMPORAL_IDS = new Set(['marian-saturday', 'christ-the-king', 'christmas-octave-sunday']);
/**
* Which identity's own propers actually supply the office's content
@@ -100,11 +100,22 @@ export function isSundayOrFeastOffice(day: LiturgicalDay): boolean {
* as each remaining duplex-majus+ saint gets a Lauds override authored,
* the same id is what Prime/Terce/Sext/None would look for too, so it's
* one shared backlog (see TODO.md), not per-hour lists that can drift.
* Also honors ALWAYS_OVERRIDE_TEMPORAL_IDS the same way
* getPsalmodyOverrideFor does — a named temporal feast (`christ-the-
* king`, `christmas-octave-sunday`) is eligible regardless of rank, since
* it has no FeastClass to compare against duplex-majus in the first
* place. Missing until 2026-08: this function only checked the sanctoral
* branch, so a temporal id in that set got a Lauds psalmody override but
* silently no Prime/Terce/Sext/None one, however much was authored for
* it — a real gap, not by design.
* Returns the id to look up (`${hourId}-antiphon-${id}` etc.), or
* `undefined` when nothing eligible is happening today.
*/
export function getMinorHourOverrideId(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;
}