From 90f6450b2fa0f96c883110420d81fb69fdddea84 Mon Sep 17 00:00:00 2001 From: Will Estes Date: Sun, 6 Sep 2026 08:52:36 -0400 Subject: [PATCH] Give the Matins invitatory antiphon a real weekday cycle The plain ferial fallback was a single fixed year-round text that was actually just Monday's own antiphon, mislabeled in its own comment as live-verified for 2026-09-06 (a Sunday). The real Monastic 1617 source genuinely varies this antiphon Sunday-Saturday, same shape as the Matins hymn's own weekday cycle. Adds the six missing weekday variants and dispatches on weekday in resolveMatinsInvitatoryText. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01W8cttEhwbN3f6hiHQHqCae --- TODO.md | 29 ++++++++++++++++--- .../matins-invitatory-antiphon-friday.yml | 16 ++++++++++ .../matins-invitatory-antiphon-saturday.yml | 14 +++++++++ .../matins-invitatory-antiphon-sunday.yml | 16 ++++++++++ .../matins-invitatory-antiphon-thursday.yml | 11 +++++++ .../matins-invitatory-antiphon-tuesday.yml | 11 +++++++ .../matins-invitatory-antiphon-wednesday.yml | 11 +++++++ .../common/matins-invitatory-antiphon.yml | 20 ++++++++++--- src/hours/matins.ts | 16 +++++++++- tests/hours/matins.test.ts | 11 +++++-- 10 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 src/data/propers/common/matins-invitatory-antiphon-friday.yml create mode 100644 src/data/propers/common/matins-invitatory-antiphon-saturday.yml create mode 100644 src/data/propers/common/matins-invitatory-antiphon-sunday.yml create mode 100644 src/data/propers/common/matins-invitatory-antiphon-thursday.yml create mode 100644 src/data/propers/common/matins-invitatory-antiphon-tuesday.yml create mode 100644 src/data/propers/common/matins-invitatory-antiphon-wednesday.yml diff --git a/TODO.md b/TODO.md index 67b9ce2..15c99e1 100644 --- a/TODO.md +++ b/TODO.md @@ -11,10 +11,6 @@ content in the same shape, not a design change. The dated log below is that pipe ## Open work, in priority order 1. **Mechanism gaps** - - **2026-09-06 invitatory antiphon questioned** — user flagged today's (2026-09-06) - invitatory antiphon as suspect; needs tracing back to its source (override > octave > - Common > season > ferial chain in `hours/matins.ts`'s invitatory resolution) to find - and fix whatever underlying bug or content problem produced it. Not yet investigated. - **Gospel+homily pairing shouldn't carry a responsory** — user, 2026-09-06: when a Matins Gospel pericope is immediately followed by its own patristic homily (the paired `gospel`/homily rendering — see `hours/matins.ts`'s Gospel+homily-fold-in convention), @@ -6445,3 +6441,28 @@ Albis", i.e. Low Sunday, not yet itself named beyond a generic ordinal — a sep still-open gap) carries a name distinct from the plain "Die N" pattern. `npm test` (2066 passed) and `tsc --noEmit` both pass. + +### Matins invitatory antiphon weekday cycle — closed (2026-09-06) + +User flagged 2026-09-06's (a plain Sunday, `post-pentecost-15`) invitatory antiphon as suspect. +Traced it to a real content bug, not a resolution-order bug: `matins-invitatory-antiphon.yml` (the +final ferial fallback in `resolveMatinsInvitatoryText`) held a single fixed year-round text +("Veníte, * Exsultémus Dómino") that its own header claimed was "live-verified... 2026-09-06" — +that was wrong. Querying the live reference engine for that exact date returns a different text +("Adorémus Dóminum, * Qui fecit nos"), and querying a full week showed the real source +(`Psalterium/Special/Matutinum Special.txt`'s `[Invit Trid_]` block) genuinely varies the plain +`{Antiphona ex Psalterio secundum tempora}` invitatory antiphon Sunday-Saturday — same shape as the +Matins hymn's own weekday cycle (`matins-hymn-ferial-tuesday.yml` etc., closed 2026-09-04). The +fixed text turned out to be Monday's own real antiphon, silently standing in for every other +weekday including Sunday. + +Fixed the same way as the hymn cycle: six new weekday-specific files +(`matins-invitatory-antiphon-{sunday,tuesday,wednesday,thursday,friday,saturday}.yml`, full +Latin+English pulled from the reference engine's own `Invit Trid_`/`Invit Trid` blocks, Latin and +English respectively), `matins-invitatory-antiphon.yml` (no day suffix) still used for Monday. +`hours/matins.ts`'s `resolveMatinsInvitatoryText` now dispatches on `day.weekday` for its final +fallback tier, same pattern as `resolveMatinsHymn`'s `weekdayFerialHymnIds`. Two pre-existing tests +in `tests/hours/matins.test.ts` hardcoded "Veníte" as the generic ferial default — both dates are +actually Tuesdays, updated to expect Tuesday's own real text ("Jubilémus Deo"). + +`npm test` (2066 passed) and `tsc --noEmit` both pass. diff --git a/src/data/propers/common/matins-invitatory-antiphon-friday.yml b/src/data/propers/common/matins-invitatory-antiphon-friday.yml new file mode 100644 index 0000000..996f3fb --- /dev/null +++ b/src/data/propers/common/matins-invitatory-antiphon-friday.yml @@ -0,0 +1,16 @@ +# Friday's own plain ferial Matins invitatory antiphon (Psalterium/ +# Special/Matutinum Special.txt's "Invit Trid_" block, `Feria VI=`). Its +# English happens to be byte-identical to Sunday's own +# (matins-invitatory-antiphon-sunday.yml) — confirmed in the source, not +# a copy-paste slip: both weekdays' Latin renders as "Let us worship the +# Lord, for He is our Maker" in the reference engine's own translation +# despite slightly different Latin wording. See matins-invitatory- +# antiphon-sunday.yml's header for the weekday-cycle mechanism this +# belongs to; live-verified 2026-09-06. +id: matins-invitatory-antiphon-friday +text: + la: "Adorémus Dóminum, * Quóniam ipse fecit nos." + en: "Let us worship the Lord, for * He is our Maker." +status: + la: verified + en: verified diff --git a/src/data/propers/common/matins-invitatory-antiphon-saturday.yml b/src/data/propers/common/matins-invitatory-antiphon-saturday.yml new file mode 100644 index 0000000..bf791e6 --- /dev/null +++ b/src/data/propers/common/matins-invitatory-antiphon-saturday.yml @@ -0,0 +1,14 @@ +# Saturday's own plain ferial Matins invitatory antiphon (Psalterium/ +# Special/Matutinum Special.txt's "Invit Trid_" block, `Sabbato=`). +# Reached only when Saturday is neither Marian (see calendar/index.ts's +# applyMarianSaturday) nor covered by a season's own seasonal invitatory +# — same real-world rarity as matins-hymn-ferial-saturday.yml's own case. +# See matins-invitatory-antiphon-sunday.yml's header for the weekday-cycle +# mechanism this belongs to; live-verified 2026-09-06. +id: matins-invitatory-antiphon-saturday +text: + la: "Dóminum, Deum nostrum, * Veníte, adorémus." + en: "The Lord our God: * O come, let us worship Him." +status: + la: verified + en: verified diff --git a/src/data/propers/common/matins-invitatory-antiphon-sunday.yml b/src/data/propers/common/matins-invitatory-antiphon-sunday.yml new file mode 100644 index 0000000..362160f --- /dev/null +++ b/src/data/propers/common/matins-invitatory-antiphon-sunday.yml @@ -0,0 +1,16 @@ +# Sunday's own plain ferial Matins invitatory antiphon (Psalterium/Special/ +# Matutinum Special.txt's "Invit Trid_" block, `Dominica=`) — the plain +# `{Antiphona ex Psalterio secundum tempora}` weekday cycle genuinely +# varies Sunday-Saturday, same shape as the Matins hymn's own weekday +# cycle (see matins-hymn-ferial-tuesday.yml etc.). `matins-invitatory- +# antiphon.yml` (no day suffix) had been standing in for every day +# including Sunday with what's actually Monday's own text — reported by +# the user 2026-09-06 as suspect and live-verified against Monastic +# Tridentinum 1617 directly. +id: matins-invitatory-antiphon-sunday +text: + la: "Adorémus Dóminum, * Qui fecit nos." + en: "Let us worship the Lord, for * He is our Maker." +status: + la: verified + en: verified diff --git a/src/data/propers/common/matins-invitatory-antiphon-thursday.yml b/src/data/propers/common/matins-invitatory-antiphon-thursday.yml new file mode 100644 index 0000000..bc9e6f6 --- /dev/null +++ b/src/data/propers/common/matins-invitatory-antiphon-thursday.yml @@ -0,0 +1,11 @@ +# Thursday's own plain ferial Matins invitatory antiphon (Psalterium/ +# Special/Matutinum Special.txt's "Invit Trid_" block, `Feria V=`). +# See matins-invitatory-antiphon-sunday.yml's header for the weekday-cycle +# mechanism this belongs to; live-verified 2026-09-06. +id: matins-invitatory-antiphon-thursday +text: + la: "Dóminum, qui fecit nos, * Veníte, adorémus." + en: "It is the Lord That hath made us: * O come, let us worship Him." +status: + la: verified + en: verified diff --git a/src/data/propers/common/matins-invitatory-antiphon-tuesday.yml b/src/data/propers/common/matins-invitatory-antiphon-tuesday.yml new file mode 100644 index 0000000..53e33d1 --- /dev/null +++ b/src/data/propers/common/matins-invitatory-antiphon-tuesday.yml @@ -0,0 +1,11 @@ +# Tuesday's own plain ferial Matins invitatory antiphon (Psalterium/ +# Special/Matutinum Special.txt's "Invit Trid_" block, `Feria III=`). +# See matins-invitatory-antiphon-sunday.yml's header for the weekday-cycle +# mechanism this belongs to; live-verified 2026-09-06. +id: matins-invitatory-antiphon-tuesday +text: + la: "Jubilémus Deo, * Salutári nostro." + en: "Let us make a joyful noise to * the God of our salvation." +status: + la: verified + en: verified diff --git a/src/data/propers/common/matins-invitatory-antiphon-wednesday.yml b/src/data/propers/common/matins-invitatory-antiphon-wednesday.yml new file mode 100644 index 0000000..209eb06 --- /dev/null +++ b/src/data/propers/common/matins-invitatory-antiphon-wednesday.yml @@ -0,0 +1,11 @@ +# Wednesday's own plain ferial Matins invitatory antiphon (Psalterium/ +# Special/Matutinum Special.txt's "Invit Trid_" block, `Feria IV=`). +# See matins-invitatory-antiphon-sunday.yml's header for the weekday-cycle +# mechanism this belongs to; live-verified 2026-09-06. +id: matins-invitatory-antiphon-wednesday +text: + la: "In manu tua, Dómine, * Omnes fines terræ." + en: "In Thy hand, O Lord, * are the inmost depths of the earth." +status: + la: verified + en: verified diff --git a/src/data/propers/common/matins-invitatory-antiphon.yml b/src/data/propers/common/matins-invitatory-antiphon.yml index 6472b5c..178f828 100644 --- a/src/data/propers/common/matins-invitatory-antiphon.yml +++ b/src/data/propers/common/matins-invitatory-antiphon.yml @@ -1,13 +1,25 @@ -# Live-verified (Monastic Tridentinum 1617, 2026-09-06 and 2026-12-15). +# This is Monday's own plain ferial Matins invitatory antiphon +# (Psalterium/Special/Matutinum Special.txt's "Invit Trid_" block, `Feria +# II=`). Its original comment claimed this text was "live-verified... +# 2026-09-06" as the year-round default — wrong: that date query actually +# returns Sunday's own distinct text ("Adorémus Dóminum, * Qui fecit +# nos.", matins-invitatory-antiphon-sunday.yml), not this one. The real +# `{Antiphona ex Psalterio secundum tempora}` cycle genuinely varies +# Sunday-Saturday, same shape as the Matins hymn's own weekday cycle (see +# matins-hymn-ferial.yml's own header) — user flagged today's rendering +# as suspect 2026-09-06, traced to this file standing in for every +# weekday including Sunday. `hours/matins.ts`'s +# `resolveMatinsInvitatoryText` now looks up a weekday-specific id +# (matins-invitatory-antiphon-sunday/-tuesday/-wednesday/-thursday/ +# -friday/-saturday) for those six days; this file (no day suffix) is +# still used directly for Monday, same convention as matins-hymn-ferial. +# # Real practice repeats this antiphon as an interspersed refrain between # verse groups of Psalm 94 (the historical "Venite" invitatory shape) — # deliberately not modeled that way here, per direct instruction: this app # frames it like any other psalm antiphon instead, one opening # (incipit-or-full, same rank rule as everywhere else) and one full # repeat after, via hours/matins.ts's plain 'psalm' + 'antiphon' parts. -# Fixed year-round for now — real practice does vary this by season/feast -# (`{Antiphona ex Psalterio secundum tempora}` in the source); not yet -# modeled, a deferred follow-on (see TODO.md). id: matins-invitatory-antiphon text: la: "Veníte, * Exsultémus Dómino." diff --git a/src/hours/matins.ts b/src/hours/matins.ts index 0eb6e9f..ba15fce 100644 --- a/src/hours/matins.ts +++ b/src/hours/matins.ts @@ -345,7 +345,21 @@ function resolveMatinsInvitatoryText(day: LiturgicalDay): ResolvedText { return seasonal; } } - return resolveCommon('matins-invitatory-antiphon'); + // The plain `{Antiphona ex Psalterio secundum tempora}` weekday cycle + // (Psalterium/Special/Matutinum Special.txt's "Invit Trid_" block) — + // same weekday-varying shape as `resolveMatinsHymn`'s own cycle, found + // missing the same way (user flagged 2026-09-06's Sunday rendering as + // suspect; it was silently reusing Monday's own text). Monday's text + // still lives at the unsuffixed `matins-invitatory-antiphon` id. + const weekdayInvitatoryIds: Partial> = { + sunday: 'matins-invitatory-antiphon-sunday', + tuesday: 'matins-invitatory-antiphon-tuesday', + wednesday: 'matins-invitatory-antiphon-wednesday', + thursday: 'matins-invitatory-antiphon-thursday', + friday: 'matins-invitatory-antiphon-friday', + saturday: 'matins-invitatory-antiphon-saturday', + }; + return resolveCommon(weekdayInvitatoryIds[day.weekday] ?? 'matins-invitatory-antiphon'); } /** The Invitatory (Ps 94) — real practice interleaves its antiphon as a diff --git a/tests/hours/matins.test.ts b/tests/hours/matins.test.ts index 6f5d247..58a2109 100644 --- a/tests/hours/matins.test.ts +++ b/tests/hours/matins.test.ts @@ -29,7 +29,11 @@ describe('resolveOrdo("matins", ...) ferial (1-nocturn) branch', () => { expect(ordo.parts[3]).toMatchObject({ kind: 'section-heading', label: 'Invitatory' }); expect(ordo.parts[4]).toMatchObject({ kind: 'psalm', psalmNumber: 94 }); const invitatoryAntiphon = (ordo.parts[4] as { antiphon?: { text: Record } }).antiphon; - expect(invitatoryAntiphon?.text.la).toContain('Veníte'); + // FERIAL_DATE is a Tuesday — its own weekday-specific invitatory + // antiphon (see hours/matins.ts's resolveMatinsInvitatoryText), not + // Monday's "Veníte" text every weekday used to share before the + // weekday cycle was built (2026-09-06). + expect(invitatoryAntiphon?.text.la).toContain('Jubilémus Deo'); // Real practice repeats the invitatory antiphon between verse groups — // deliberately not modeled that way here (see hours/matins.ts's own // header): confirm there's exactly one standalone repeat, not several. @@ -1090,7 +1094,10 @@ describe('resolveOrdo("matins", ...) Common-of-an-Apostle hymn + invitatory (202 // ferial one -- season outranks weekday in resolveMatinsHymn's own // precedence, same as everywhere else. expect(hymnLatin(FERIAL_DATE)).toContain('Verbum supérnum, pródiens'); - expect(invitatoryFullLatin(FERIAL_DATE)).toContain('Veníte'); + // Advent has no seasonal invitatory antiphon authored, so this falls + // through to Tuesday's own weekday text (see hours/matins.ts's + // resolveMatinsInvitatoryText and its 2026-09-06 weekday-cycle fix). + expect(invitatoryFullLatin(FERIAL_DATE)).toContain('Jubilémus Deo'); expect(invitatoryFullLatin(FERIAL_DATE)).not.toContain('Regem Apostolórum'); }); });