Build All Souls' Day (Nov 2) as a reusable Office of the Dead

Adds the full 8-hour Office of the Dead for All Souls' Day: Matins (3
nocturns, Job/Augustine/1 Cor lessons and their own 9 responsories, no
Te Deum), Lauds, Vespers (Second Vespers only — Nov 1 evening stays
First Vespers of All Saints), and reduced special psalmody at
Prime/Terce/Sext/None/Compline. The "Requiem gloria" rubric substitutes
"Réquiem ætérnam/Et lux perpétua" for the ordinary Gloria Patri all day,
wired centrally into resolve-common.ts's resolveGloriaPatri alongside
its existing Triduum omission.

Content is split into a reusable src/hours/office-of-the-dead.ts engine
(Commune C9's own generic psalmody/lessons/collects, usable for any
future occasion this office is said) and a thin src/hours/all-souls.ts
supplying only what's genuinely Nov 2-specific (the date trigger, the
Augustine + 1 Cor lesson substitution, the Martyrology introduction,
and two day-specific collects). No new calendar trigger, route, or
per-day override table is added — Nov 2 remains the only caller today.

Live-verified hour-by-hour against the reference engine's own
rendering, which caught two things the raw static source alone would
have gotten wrong: Lauds' "Ps 222" is the Canticle of Ezechias, not a
numbered psalm, and Compline's would-be 4th special psalm never
actually renders under any selectable rubric version, so it's dropped
rather than invented.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
This commit is contained in:
2026-09-05 22:35:39 -04:00
parent 5cd4fb69a9
commit a462464f7c
12 changed files with 764 additions and 0 deletions
+4
View File
@@ -20,6 +20,7 @@ import {
isSundayOrFeastOffice,
resolveResponsory,
} from './resolve-common';
import { isAllSouls, buildPrimeParts, DAY_LABEL } from './all-souls';
import primeDefinitionData from '../data/hours/prime.yml';
import antiphonsData from '../data/hours/prime-antiphons.yml';
@@ -141,6 +142,9 @@ function resolvePart(part: HourPart, date: string, day: LiturgicalDay): Resolved
}
export function resolveOrdo(date: string): ResolvedOrdo {
if (isAllSouls(date)) {
return { hourId: 'prime', date, parts: buildPrimeParts(date), dayLabel: DAY_LABEL };
}
const day = resolveDay(date);
const parts = primeDefinition.parts.flatMap((part) => resolvePart(part, date, day));
return { hourId: 'prime', date, parts, dayLabel: getDayLabel(day) };