Add the O Antiphons (Dec 17-23) as an unconditional Vespers Magnificat override
Deploy / deploy (push) Successful in 1m27s

advent-4's own remaining Magnificat-antiphon gap turned out to be a
mechanism problem, not missing content: Dec 17-23 always carries one of
the seven "O Antiphons" at Vespers, keyed to the calendar date itself,
not to whichever Advent week (advent-3 or advent-4, varies by year)
happens to govern that date -- a single per-week file was structurally
the wrong shape.

Added vespers-o-antiphons.yml (MM-DD keyed) and a new lookup tier in
getMagnificatAntiphon, checked unconditionally ahead of both the
per-week temporal file and a real sanctoral winner's own antiphon --
direct instruction: the O Antiphon wins this one text slot on these
seven dates regardless of who otherwise wins the day (e.g. St. Thomas,
Dec 21, still keeps every other part of his own office). Two of the
seven (O Clavis David/O Oriens, Dec 20-21) couldn't be live-verified --
every reference-engine track routes those two dates through St.
Thomas's Vigil/feast instead, which this app's own vigil-of-st-thomas.yml
already documents diverging from -- so they're marked draft rather than
verified.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
This commit is contained in:
2026-08-30 07:04:30 -04:00
parent 66bd970fed
commit b3a7176cb8
5 changed files with 324 additions and 17 deletions
+40
View File
@@ -3,6 +3,7 @@ import { resolveDay } from '../../src/calendar';
import {
getDayCollect,
getBenedictusAntiphon,
getMagnificatAntiphon,
resolveMinorHourAntiphon,
resolveMinorHourChapter,
splitNamedAntiphon,
@@ -305,3 +306,42 @@ describe('Paschaltide alleluia suffix on Common-category antiphons (2026-08)', (
expect(benedictus.text.la?.match(/allelúja/g)?.length).toBe(2);
});
});
describe('getMagnificatAntiphon — classic weekday-default fallback', () => {
it('falls back to the classic weekday-quote antiphon for a plain temporal id with no proper Magnificat antiphon of its own', () => {
// Synthetic day, not a real resolveOrdo/resolveDay date: after the
// full temporal-cycle Magnificat-antiphon sweep (2026-08-30, see
// TODO.md), every real temporal id this app's calendar can actually
// land Vespers on has its own proper antiphon authored (or is covered
// date-by-date by the O Antiphons, Dec 17-23 -- see
// vespers-o-antiphons.yml), so there's no live date left to exercise
// this fallback tier through the real pipeline any more -- see
// tests/hours/vespers.test.ts's own note where this test used to
// live. Tests the mechanism directly instead, the same way this
// file's other synthetic-day cases do.
const day: LiturgicalDay = {
date: '2026-01-01',
weekday: 'tuesday',
season: 'trinitytide',
temporalCategory: 'ordinary-feria',
winner: { kind: 'temporal', id: 'not-a-real-temporal-id' },
commemorations: [],
};
const magnificat = getMagnificatAntiphon(day);
expect(magnificat.text.la).toContain('Exsúltet');
expect(magnificat.status.la).toBe('verified');
});
it('has no weekday default for Sunday (its own antiphon varies by Proper of the Time)', () => {
const day: LiturgicalDay = {
date: '2026-01-04',
weekday: 'sunday',
season: 'trinitytide',
temporalCategory: 'ordinary-sunday',
winner: { kind: 'temporal', id: 'not-a-real-temporal-id' },
commemorations: [],
};
const magnificat = getMagnificatAntiphon(day);
expect(magnificat.status.la).toBe('missing');
});
});