Label Vespers cross-day commemorations and add feast-side privilege

A commemoration that only exists because Vespers/Compline crossed a day
boundary now renders as "(of today)"/"(of tomorrow)" in English and the
real Divino Afflatu "de præcedenti"/"de sequenti" in Latin, instead of
showing silently with no indication it's a cross-day artifact.

Also adds forbidsSuccessorCommemoration to SaintRecord and
TemporalFeastRecord: a feast can now refuse to commemorate whatever wins
the next day at its own kept Second Vespers, the feast-side mirror of the
day-side privilege calendar/commemorations.ts already modeled. Left unset
everywhere for now (a no-op) -- it exists so the next commit's Sacred
Heart record has somewhere to carry the real, live-sourced exclusion
against Most Precious Blood.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014axryJBrRswYh2niA7WCUc
This commit is contained in:
2026-08-26 15:20:10 -04:00
parent 9067faf1fd
commit 2f7b421558
6 changed files with 125 additions and 6 deletions
+19 -1
View File
@@ -376,6 +376,19 @@ function octaveCommemorationLabel(octave: ActiveOctave): Bi {
return octaveCoreName(octave);
}
/** Real Divino Afflatu phrasing for a commemoration that only exists
* because Vespers/Compline crossed a day boundary — "commemoratio de
* præcedenti" (today, riding along on tomorrow's anticipated First
* Vespers) or "commemoratio de sequenti" (tomorrow, riding along on
* today's kept Second Vespers), per horascommon.pl. See
* `Commemoration`'s `vespersNote` field (calendar/types.ts) and
* calendar/vespers.ts's two `commemorationOfDisplaced*` functions, the
* only place that sets it. */
const CROSS_DAY_VESPERS_LABELS: Record<'today' | 'tomorrow', Bi> = {
today: bi('of today', 'de præcedenti'),
tomorrow: bi('of tomorrow', 'de sequenti'),
};
/** Every commemoration on `day`, resolved to display strings and grouped
* by kind — the single place that decides both "is this commemoration
* eligible to show at all here" and "how is it formatted", so every
@@ -425,7 +438,12 @@ function collectCommemorations(
const octaves: Bi[] = [];
for (const c of day.commemorations) {
if (c.kind === 'sanctoral') {
sanctoral.push(biFallback(c.name));
const name = biFallback(c.name);
sanctoral.push(
c.vespersNote
? bi(`${name.en} (${CROSS_DAY_VESPERS_LABELS[c.vespersNote].en})`, `${name.la} (${CROSS_DAY_VESPERS_LABELS[c.vespersNote].la})`)
: name,
);
} else if (c.kind === 'temporal') {
if (c.id === temporalId) {
temporal.push(anchorDayName(day, false) ?? temporalLabel(day));