Compare commits
5 Commits
33c9b2415b
...
943aead9ae
| Author | SHA1 | Date | |
|---|---|---|---|
| 943aead9ae | |||
| ba4a5c70db | |||
| fbb3a2cfc7 | |||
| e7fc70bf77 | |||
| 15cc76dacf |
@@ -48,14 +48,21 @@ across every hour and content type in this app.
|
|||||||
- The bulk Vulgate (Latin) + Douay-Rheims (English) scripture import into
|
- The bulk Vulgate (Latin) + Douay-Rheims (English) scripture import into
|
||||||
`src/data/scripture/` — long-term project, explicitly deferred; Matins scripture
|
`src/data/scripture/` — long-term project, explicitly deferred; Matins scripture
|
||||||
citations resolve to `missing` text until it lands.
|
citations resolve to `missing` text until it lands.
|
||||||
- Lauds/Vespers duplex-majus+ Common-category psalmody: 8 of 24 `SaintRecord.common`
|
- Lauds/Vespers duplex-majus+ Common-category psalmody: 10 of 24 `SaintRecord.common`
|
||||||
categories authored (covering 16 ids via aliases) for both hours — see "Lauds/Vespers
|
categories authored (covering 19 ids via aliases) for Vespers, 9 of 24 (18 ids) for Lauds —
|
||||||
duplex-majus+ Common-category psalmody" below. Remaining: `common-of-a-dedication`,
|
see "Lauds/Vespers duplex-majus+ Common-category psalmody" below and its follow-up entry.
|
||||||
`common-of-an-angel`, `common-of-an-evangelist`, `common-of-a-vigil`,
|
Genuinely still open: `common-of-a-dedication`'s **Lauds** file specifically (Vespers is
|
||||||
`common-of-several-women-martyrs` (no votive code confirmed yet for any of these), plus
|
done) — blocked on a real content gap, not a mechanism gap: its OT canticle ("Canticum
|
||||||
Vespers' own per-feast **proper** tier (`data/hours/vespers-psalmody-overrides/saints/`)
|
Ieremiæ") has never been transcribed anywhere in this app (the 7 existing Lauds canticles,
|
||||||
is mechanism-only, zero saints authored — unlike Lauds, no majus+ saint currently on the
|
`hours/lauds-canticles.ts`, are only the plain weekday rotation) — needs sourcing before
|
||||||
calendar is known to have proper Vespers psalm antiphons distinct from their Common's.
|
that one file can be authored without guessing. `common-of-a-vigil` is not a gap at all:
|
||||||
|
the `vigil` `FeastClass` sits structurally below `duplex-majus` on the rank ladder (see
|
||||||
|
`calendar/commemorations.ts`'s `FEAST_CLASS_ORDER`), so `getOfficeOverrideId` can never
|
||||||
|
return a Vigil's id — this category is permanently unreachable by design, not worth
|
||||||
|
authoring. Vespers' own per-feast **proper** tier
|
||||||
|
(`data/hours/vespers-psalmody-overrides/saints/`) is mechanism-only, zero saints authored —
|
||||||
|
unlike Lauds, no majus+ saint currently on the calendar is known to have proper Vespers
|
||||||
|
psalm antiphons distinct from their Common's.
|
||||||
|
|
||||||
3. **Known, deliberate simplifications** — intentional, not bugs, no plan to revisit unless
|
3. **Known, deliberate simplifications** — intentional, not bugs, no plan to revisit unless
|
||||||
priorities change:
|
priorities change:
|
||||||
@@ -3997,3 +4004,73 @@ Monday") had to move to a different date: that Monday turned out to be the closi
|
|||||||
Lawrence's own octave, which now correctly picks up Common-of-a-Martyr's psalms instead of the
|
Lawrence's own octave, which now correctly picks up Common-of-a-Martyr's psalms instead of the
|
||||||
plain ferial set it was (incidentally, not intentionally) relying on before this mechanism
|
plain ferial set it was (incidentally, not intentionally) relying on before this mechanism
|
||||||
existed. `npm test` (535 passed) and `npm run build` both pass.
|
existed. `npm test` (535 passed) and `npm run build` both pass.
|
||||||
|
|
||||||
|
### Lauds/Vespers duplex-majus+ Common-category psalmody — remaining categories authored, one real gap surfaced (2026-08-28)
|
||||||
|
|
||||||
|
Follow-up to the previous entry, closing most of the "8 of 24" gap it left open. Went
|
||||||
|
category by category through the reference engine's votive-code space (the full `CommuneM/`
|
||||||
|
directory listing, `C1` through `C12` and their season-variant suffixes) to identify each
|
||||||
|
remaining `SaintRecord.common` value's real scheme, rather than assuming one exists:
|
||||||
|
|
||||||
|
- **`common-of-an-evangelist` is an alias, not its own scheme.** St. Mark's and St. Luke's own
|
||||||
|
reference-engine rule files both say "ex C1a", and `votive=C1a` returned byte-identical
|
||||||
|
Lauds/Vespers psalmody to plain `votive=C1` — an Evangelist-not-Apostle genuinely reuses the
|
||||||
|
Apostles' own scheme in the Monastic tradition. Registered as an alias on
|
||||||
|
`common-of-an-apostle`'s existing category files for both hours.
|
||||||
|
- **`common-of-several-women-martyrs` is also an alias, not its own scheme** — but only once the
|
||||||
|
actual Vespers/Lauds *psalmody* slots are isolated from the Magnificat/Benedictus antiphon
|
||||||
|
that follows them. Ss. Perpetua and Felicity's own file says "vide C7b"; `votive=C7b` returned
|
||||||
|
the *same* four psalm numbers and group/canticle/Laudate antiphons as plain `votive=C7`
|
||||||
|
(Common-of-a-Holy-Woman) for both hours — C7b's only real difference is its own proper
|
||||||
|
Magnificat/Benedictus antiphon, which belongs to a separate, already-existing mechanism
|
||||||
|
(`getMagnificatAntiphon`/`getBenedictusAntiphon`), not the psalmody-override table this pass
|
||||||
|
is building. First-draft category files for this id were written as full duplicates before
|
||||||
|
this was caught by diffing against the live output line-by-line — deleted in favor of an
|
||||||
|
alias on `common-of-a-holy-woman`'s existing files instead. Neither this id nor
|
||||||
|
`common-of-a-vigil` (see below) can currently be exercised via `resolveOrdo`/a real calendar
|
||||||
|
date (Perpetua and Felicity are plain Duplex, below this override's threshold, and no other
|
||||||
|
saint carries this Common) — verified via a direct `getLaudsCommonOverride`/
|
||||||
|
`getVespersCommonOverride` unit test instead of a date-based one.
|
||||||
|
- **`common-of-an-angel` has no real numbered Common in the source at all** — confirmed via the
|
||||||
|
full `CommuneM/` directory listing (no angel-specific code exists) and St. Michael's own
|
||||||
|
SanctiM rule, which says plain "Psalmi Dominica" (Sunday's own Vespers psalm numbers, 109-112,
|
||||||
|
not a Common-specific set) rather than citing any `Cx` file. Live-verified that Guardian
|
||||||
|
Angels (Oct 2, Duplex Majus, no proper text of her own) reuses Michael's own antiphons
|
||||||
|
byte-for-byte at both Lauds and Vespers — i.e. Michael's own proper *is* the de facto generic
|
||||||
|
Angel scheme any other Angel-Common saint without their own proper falls back to. (St. Gabriel
|
||||||
|
and St. Raphael each have their own genuinely distinct proper antiphons, matching this file's
|
||||||
|
own earlier finding for the *office bundle* that Guardian Angels/Gabriel/Raphael's
|
||||||
|
chapter/responsory/hymn/versicle content is duplicated per-saint from St. Michael's Apparition,
|
||||||
|
not drawn from a shared Common — the same absence of a real Angel Common, independently
|
||||||
|
confirmed for a different content type.) Authored as a genuine `common-of-an-angel` category
|
||||||
|
(an app-side generalization the source data doesn't literally have a file for, but a real,
|
||||||
|
reusable scheme in practice) rather than duplicating Michael's antiphons into a
|
||||||
|
Guardian-Angels-specific file, so any future proper-less Angel addition benefits automatically.
|
||||||
|
Lauds keeps the usual fixed 92/99/62 + Canticum Trium Puerorum numbers; Vespers substitutes
|
||||||
|
"Psalmi Dominica" (109-112) instead of a Common-specific set.
|
||||||
|
- **`common-of-a-dedication` is genuinely its own scheme** (`votive=C8`) for both hours — unlike
|
||||||
|
every other Common authored so far, Vespers' numbers (109/110/111/147) don't share a pattern
|
||||||
|
with any other category, and Lauds' (50/87/89 + "Canticum Ieremiæ") aren't even the usual
|
||||||
|
fixed 92/99/62 set. **Only the Vespers file was authored**: Lauds' own canticle text has never
|
||||||
|
been transcribed anywhere in this app (the 7 existing Lauds OT canticles, `hours/
|
||||||
|
lauds-canticles.ts`, are only the plain weekday rotation) — left open rather than guessed at,
|
||||||
|
see the Open-work list above.
|
||||||
|
- **`common-of-a-vigil` is not an authorable gap at all.** The `vigil` `FeastClass` sits
|
||||||
|
structurally below `duplex-majus` on `calendar/commemorations.ts`'s `FEAST_CLASS_ORDER`
|
||||||
|
ladder, so `getOfficeOverrideId`'s `isAtLeast(winner.rank, 'duplex-majus')` test can never
|
||||||
|
return true for a Vigil — this category is permanently unreachable by the mechanism as gated,
|
||||||
|
not a missing-content gap to close later.
|
||||||
|
|
||||||
|
Regression tests added to both `lauds.test.ts` and `vespers.test.ts`: a real calendar date for
|
||||||
|
each reachable category (Guardian Angels for Angel, both hours; the Dedication's own day for
|
||||||
|
Vespers), a real date via the alias for `common-of-an-evangelist` on Vespers (St. Mark, whose
|
||||||
|
own per-feast Lauds override shadows the category tier for Lauds specifically, so that one used
|
||||||
|
a direct unit test instead), and direct unit tests for the two currently-unreachable-by-date
|
||||||
|
aliases (`common-of-several-women-martyrs` for both hours). Two more pre-existing Vespers test
|
||||||
|
dates needed to move for the same reason as the previous entry's `2026-08-17` fix:
|
||||||
|
`2026-09-28` (anticipates St. Michael's own First Vespers, once his Common-of-an-Angel override
|
||||||
|
started applying) moved to `2026-10-12`; Guardian Angels' own initial test date (Oct 2, her own
|
||||||
|
day) had to move to Oct 1 (her First Vespers) once tracing `resolveEveningDay` showed she
|
||||||
|
doesn't keep her own Second Vespers (falls short of the `duplex-2-classis` floor) and Oct 3 (St.
|
||||||
|
Therese, plain Duplex, below this override's own threshold) claims her evening instead. `npm
|
||||||
|
test` (542 passed), `tsc --noEmit`, and `npm run build` all pass.
|
||||||
|
|||||||
@@ -9,8 +9,16 @@
|
|||||||
# votive=C7 is the shared source for both ids' existing matins-hymn-*.yml
|
# votive=C7 is the shared source for both ids' existing matins-hymn-*.yml
|
||||||
# office-bundle files (see matins-hymn-common-of-a-widow.yml's own
|
# office-bundle files (see matins-hymn-common-of-a-widow.yml's own
|
||||||
# header).
|
# header).
|
||||||
|
#
|
||||||
|
# Also registers `common-of-several-women-martyrs`: Ss. Perpetua and
|
||||||
|
# Felicity's own reference-engine file says "vide C7b", and `votive=C7b`
|
||||||
|
# returned these exact same psalm numbers and group/canticle/Laudate
|
||||||
|
# antiphons (2026-08-28) -- C7b's only real difference from plain C7 is
|
||||||
|
# its own proper Benedictus antiphon ("Istárum est enim regnum
|
||||||
|
# cælórum..."), which belongs to a separate mechanism
|
||||||
|
# (getBenedictusAntiphon/`benedictusCommon`), not this psalmody table.
|
||||||
id: common-of-a-holy-woman
|
id: common-of-a-holy-woman
|
||||||
aliases: [common-of-a-widow]
|
aliases: [common-of-a-widow, common-of-several-women-martyrs]
|
||||||
groups:
|
groups:
|
||||||
- psalms: [92]
|
- psalms: [92]
|
||||||
antiphon:
|
antiphon:
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Generic Common-of-an-Angel Lauds psalmody. Unlike every other Common
|
||||||
|
# here, there is no dedicated numbered "Cx" Common file for Angels in the
|
||||||
|
# Monastic reference engine at all (checked the full CommuneM directory
|
||||||
|
# listing) -- St. Michael's own SanctiM rule instead says plain "Psalmi
|
||||||
|
# Dominica" (Sunday's own psalmody) and carries his own proper antiphons
|
||||||
|
# directly. Live-verified (2026-08-28) that Guardian Angels (Oct 2, no
|
||||||
|
# proper text of her own) reuses Michael's own antiphons byte-for-byte at
|
||||||
|
# both Lauds and Vespers -- i.e. Michael's proper *is* the de facto
|
||||||
|
# generic Angel scheme any other Angel-Common saint without proper text
|
||||||
|
# of their own falls back to. St. Gabriel and St. Raphael each have their
|
||||||
|
# own genuinely distinct proper antiphons (not this generic scheme, and
|
||||||
|
# not each other's) -- not modeled here since a per-feast Lauds override
|
||||||
|
# would be the correct home for those, not this category.
|
||||||
|
#
|
||||||
|
# Psalm numbers here (92, 99, 62, Canticum Trium Puerorum) are still the
|
||||||
|
# usual fixed Duplex-majus+ set, confirmed against Michael's own live
|
||||||
|
# Lauds -- only Vespers substitutes "Psalmi Dominica" (109-112) instead,
|
||||||
|
# see the Vespers category file's own note.
|
||||||
|
id: common-of-an-angel
|
||||||
|
groups:
|
||||||
|
- psalms: [92]
|
||||||
|
antiphon:
|
||||||
|
la: "Stetit Angelus * iuxta aram templi, habens thuríbulum áureum in manu sua."
|
||||||
|
en: "An Angel stood at the Altar * of the Temple, having a golden censer in his hand."
|
||||||
|
- psalms: [99]
|
||||||
|
antiphon:
|
||||||
|
la: "Dum præliarétur * Míchaël Archángelus cum dracóne, audíta est vox dicéntium: Salus Deo nostro, allelúia."
|
||||||
|
en: "While as the Archangel Michael fought against the dragon, * I heard voices saying: Salvation unto our God. Alleluia."
|
||||||
|
- psalms: [62]
|
||||||
|
antiphon:
|
||||||
|
la: "Archángele Míchaël, * constítui te príncipem super omnes ánimas suscipiéndas."
|
||||||
|
en: "Michael Mine Archangel, * I have appointed thee for a prince over the ingathering of souls."
|
||||||
|
canticle:
|
||||||
|
id: canticum-trium-puerorum
|
||||||
|
antiphon:
|
||||||
|
la: "Angeli Dómini, * Dóminum benedícite in ætérnum."
|
||||||
|
en: "O ye Angels of the Lord, * bless ye the Lord always."
|
||||||
|
laudate:
|
||||||
|
antiphon:
|
||||||
|
la: "Angeli, Archángeli, * Throni et Dominatiónes, Principátus et Potestátes, Virtútes cælórum, laudáte Dóminum de cælis, allelúia."
|
||||||
|
en: "O ye Angels and Archangels, * O ye Thrones and Dominions, O ye Principalities and Powers, O ye mighty Ones of heaven, praise ye the Lord from the heavens. Alleluia."
|
||||||
@@ -9,8 +9,14 @@
|
|||||||
# group of Apostles, e.g. Ss. Philip and James) under this same scheme --
|
# group of Apostles, e.g. Ss. Philip and James) under this same scheme --
|
||||||
# both ids' existing lauds-capitulum-*.yml office-bundle files already
|
# both ids' existing lauds-capitulum-*.yml office-bundle files already
|
||||||
# cite the identical `votive=C1` source, so this is one scheme, not two.
|
# cite the identical `votive=C1` source, so this is one scheme, not two.
|
||||||
|
#
|
||||||
|
# Also registers `common-of-an-evangelist`: St. Mark's and St. Luke's own
|
||||||
|
# reference-engine rule files both say "ex C1a", and `votive=C1a` returned
|
||||||
|
# byte-identical Lauds/Vespers psalmody to plain `votive=C1` (2026-08-28)
|
||||||
|
# -- an Evangelist-not-Apostle genuinely reuses the Apostles' own scheme
|
||||||
|
# in the Monastic tradition, not a separate Evangelist Common.
|
||||||
id: common-of-an-apostle
|
id: common-of-an-apostle
|
||||||
aliases: [common-of-apostles]
|
aliases: [common-of-apostles, common-of-an-evangelist]
|
||||||
groups:
|
groups:
|
||||||
- psalms: [92]
|
- psalms: [92]
|
||||||
antiphon:
|
antiphon:
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Generic Common-of-a-Dedication (of a Church) Vespers psalmody, live-
|
||||||
|
# verified against Divinum Officium (Monastic Tridentinum 1617, command=
|
||||||
|
# prayVespera, votive=C8, 2026-08-28). Genuinely its own scheme, unlike
|
||||||
|
# every other Common authored so far: 109/110/111/147 (Ps 147, not the
|
||||||
|
# expected next-in-sequence 112, for the 4th slot).
|
||||||
|
#
|
||||||
|
# NOTE: no matching Lauds category file exists yet -- Lauds' own
|
||||||
|
# Dedication scheme (votive=C8, live-verified the same session) uses Ps
|
||||||
|
# 50/87/89 plus a "Canticum Ieremiæ" this app has never transcribed (the
|
||||||
|
# 7 existing Lauds OT canticles, hours/lauds-canticles.ts, are only the
|
||||||
|
# plain weekday rotation) -- a real content gap, not an oversight, left
|
||||||
|
# open rather than guessed at. See TODO.md.
|
||||||
|
id: common-of-a-dedication
|
||||||
|
groups:
|
||||||
|
- psalms: [109]
|
||||||
|
antiphon:
|
||||||
|
la: "Domum tuam, Dómine, * decet sanctitúdo in longitúdinem diérum."
|
||||||
|
en: "Holiness becometh thine house, * O Lord, for ever."
|
||||||
|
- psalms: [110]
|
||||||
|
antiphon:
|
||||||
|
la: "Domus mea, * domus oratiónis vocábitur."
|
||||||
|
en: "My house * shall be called the house of prayer."
|
||||||
|
- psalms: [111]
|
||||||
|
antiphon:
|
||||||
|
la: "Hæc est domus Dómini * fírmiter ædificáta, bene fundáta est supra firmam petram."
|
||||||
|
en: "This is the Lord's house * stoutly builded, well founded upon a sure rock."
|
||||||
|
- psalms: [147]
|
||||||
|
antiphon:
|
||||||
|
la: "Lápides pretiósi * omnes muri tui, et turres Ierúsalem gemmis ædificabúntur."
|
||||||
|
en: "All thy walls are of stones most precious, * and the towers of Jerusalem shall be built up with jewels."
|
||||||
@@ -9,8 +9,16 @@
|
|||||||
# votive=C7 is the shared source for both ids' existing matins-hymn-*.yml
|
# votive=C7 is the shared source for both ids' existing matins-hymn-*.yml
|
||||||
# office-bundle files (see matins-hymn-common-of-a-widow.yml's own
|
# office-bundle files (see matins-hymn-common-of-a-widow.yml's own
|
||||||
# header).
|
# header).
|
||||||
|
#
|
||||||
|
# Also registers `common-of-several-women-martyrs`: Ss. Perpetua and
|
||||||
|
# Felicity's own reference-engine file says "vide C7b", and `votive=C7b`
|
||||||
|
# returned these exact same four psalm numbers and antiphons (2026-08-28)
|
||||||
|
# -- C7b's only real difference from plain C7 is its own proper
|
||||||
|
# Magnificat antiphon ("Istárum est enim regnum cælórum..."), which
|
||||||
|
# belongs to a separate mechanism (getMagnificatAntiphon), not this
|
||||||
|
# psalmody table.
|
||||||
id: common-of-a-holy-woman
|
id: common-of-a-holy-woman
|
||||||
aliases: [common-of-a-widow]
|
aliases: [common-of-a-widow, common-of-several-women-martyrs]
|
||||||
groups:
|
groups:
|
||||||
- psalms: [109]
|
- psalms: [109]
|
||||||
antiphon:
|
antiphon:
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Generic Common-of-an-Angel Vespers psalmody. Unlike every other Common
|
||||||
|
# here, there is no dedicated numbered "Cx" Common file for Angels in the
|
||||||
|
# Monastic reference engine (checked the full CommuneM directory listing)
|
||||||
|
# -- St. Michael's own SanctiM rule instead says plain "Psalmi Dominica",
|
||||||
|
# i.e. Sunday's own Vespers psalm numbers (109-112, not a Common-specific
|
||||||
|
# set), carrying his own proper antiphons directly. Live-verified
|
||||||
|
# (2026-08-28) that Guardian Angels (Oct 2, no proper text of her own)
|
||||||
|
# reuses Michael's own antiphons byte-for-byte -- i.e. Michael's proper
|
||||||
|
# *is* the de facto generic Angel scheme any other Angel-Common saint
|
||||||
|
# without proper text of their own falls back to. St. Gabriel and St.
|
||||||
|
# Raphael each have their own genuinely distinct proper antiphons (not
|
||||||
|
# this generic scheme, and not each other's) -- not modeled here since a
|
||||||
|
# per-feast Vespers override would be the correct home for those, not
|
||||||
|
# this category.
|
||||||
|
id: common-of-an-angel
|
||||||
|
groups:
|
||||||
|
- psalms: [109]
|
||||||
|
antiphon:
|
||||||
|
la: "Stetit Angelus * iuxta aram templi, habens thuríbulum áureum in manu sua."
|
||||||
|
en: "An Angel stood at the Altar * of the Temple, having a golden censer in his hand."
|
||||||
|
- psalms: [110]
|
||||||
|
antiphon:
|
||||||
|
la: "Dum præliarétur * Míchaël Archángelus cum dracóne, audíta est vox dicéntium: Salus Deo nostro, allelúia."
|
||||||
|
en: "While as the Archangel Michael fought against the dragon, * I heard voices saying: Salvation unto our God. Alleluia."
|
||||||
|
- psalms: [111]
|
||||||
|
antiphon:
|
||||||
|
la: "Archángele Míchaël, * constítui te príncipem super omnes ánimas suscipiéndas."
|
||||||
|
en: "Michael Mine Archangel, * I have appointed thee for a prince over the ingathering of souls."
|
||||||
|
- psalms: [112]
|
||||||
|
antiphon:
|
||||||
|
la: "Angeli, Archángeli, * Throni et Dominatiónes, Principátus et Potestátes, Virtútes cælórum, laudáte Dóminum de cælis, allelúia."
|
||||||
|
en: "O ye Angels and Archangels, * O ye Thrones and Dominions, O ye Principalities and Powers, O ye mighty Ones of heaven, praise ye the Lord from the heavens. Alleluia."
|
||||||
@@ -6,8 +6,14 @@
|
|||||||
# group of Apostles, e.g. Ss. Philip and James) under this same scheme --
|
# group of Apostles, e.g. Ss. Philip and James) under this same scheme --
|
||||||
# both ids' existing vespers-hymn-*.yml office-bundle files already cite
|
# both ids' existing vespers-hymn-*.yml office-bundle files already cite
|
||||||
# the identical `votive=C1` source, so this is one scheme, not two.
|
# the identical `votive=C1` source, so this is one scheme, not two.
|
||||||
|
#
|
||||||
|
# Also registers `common-of-an-evangelist`: St. Mark's and St. Luke's own
|
||||||
|
# reference-engine rule files both say "ex C1a", and `votive=C1a` returned
|
||||||
|
# byte-identical Lauds/Vespers psalmody to plain `votive=C1` (2026-08-28)
|
||||||
|
# -- an Evangelist-not-Apostle genuinely reuses the Apostles' own scheme
|
||||||
|
# in the Monastic tradition, not a separate Evangelist Common.
|
||||||
id: common-of-an-apostle
|
id: common-of-an-apostle
|
||||||
aliases: [common-of-apostles]
|
aliases: [common-of-apostles, common-of-an-evangelist]
|
||||||
groups:
|
groups:
|
||||||
- psalms: [109]
|
- psalms: [109]
|
||||||
antiphon:
|
antiphon:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { resolveOrdo } from '../../src/hours';
|
import { resolveOrdo } from '../../src/hours';
|
||||||
|
import { getLaudsCommonOverride } from '../../src/hours/lauds-psalmody-overrides';
|
||||||
|
|
||||||
// Clean ferial dates, one per weekday — see data/psalter-distribution.yml
|
// Clean ferial dates, one per weekday — see data/psalter-distribution.yml
|
||||||
// and src/hours/lauds.ts's own generation-script provenance comments for
|
// and src/hours/lauds.ts's own generation-script provenance comments for
|
||||||
@@ -361,6 +362,49 @@ describe('resolveOrdo("lauds", ...)', () => {
|
|||||||
expect(numbers).toEqual([66, 50, 63, 64, 148, 149, 150]);
|
expect(numbers).toEqual([66, 50, 63, 64, 148, 149, 150]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses Common-of-an-Angel's own psalmody (reusing St. Michael's own proper text) on Guardian Angels' own day", () => {
|
||||||
|
// Guardian Angels (Oct 2, Duplex Majus) has no proper text of her own
|
||||||
|
// -- live-verified (2026-08-28) that her real Lauds antiphons are St.
|
||||||
|
// Michael's own, byte-for-byte, which is exactly what this category's
|
||||||
|
// content is (see data/hours/lauds-psalmody-overrides/categories/
|
||||||
|
// common-of-an-angel.yml's own header). Psalm numbers stay the usual
|
||||||
|
// fixed Duplex-majus+ set (92, 99, 62), unlike this Common's Vespers
|
||||||
|
// psalmody, which substitutes "Psalmi Dominica" instead.
|
||||||
|
const ordo = resolveOrdo('lauds', '2026-10-02');
|
||||||
|
const numbers = ordo.parts.filter((p) => p.kind === 'psalm').map((p) => (p.kind === 'psalm' ? p.psalmNumber : undefined));
|
||||||
|
expect(numbers).toEqual([66, 92, 99, 62, 148, 149, 150]);
|
||||||
|
const secondPsalm = ordo.parts.filter((p) => p.kind === 'psalm')[1];
|
||||||
|
expect(secondPsalm?.kind === 'psalm' ? secondPsalm.antiphon?.text.la : undefined).toContain('Stetit Angelus');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('aliases common-of-an-evangelist onto common-of-an-apostle for Lauds psalmody', () => {
|
||||||
|
// Every Evangelist on this calendar (St. John Apostle, St. Luke, St.
|
||||||
|
// Mark) already has their own per-feast Lauds override authored, so
|
||||||
|
// the Common-category tier can never actually surface via
|
||||||
|
// resolveOrdo/a real date for Lauds specifically (unlike Vespers, see
|
||||||
|
// vespers.test.ts's own St. Mark test) -- test the alias wiring
|
||||||
|
// directly instead. St. Mark's and St. Luke's own reference-engine
|
||||||
|
// rule files both say "ex C1a", and votive=C1a returned byte-identical
|
||||||
|
// Lauds psalmody to plain votive=C1 (2026-08-28).
|
||||||
|
const override = getLaudsCommonOverride('st-mark');
|
||||||
|
expect(override?.id).toBe('common-of-an-apostle');
|
||||||
|
expect(override?.groups.map((g) => g.psalms)).toEqual([[92], [99], [62]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('aliases common-of-several-women-martyrs onto common-of-a-holy-woman for Lauds psalmody', () => {
|
||||||
|
// No majus+ saint on this calendar actually carries this Common yet
|
||||||
|
// (Ss. Perpetua and Felicity, the only one, are plain Duplex -- below
|
||||||
|
// this override's threshold), so this can't be exercised via
|
||||||
|
// resolveOrdo/a real date; test the alias wiring directly instead.
|
||||||
|
// Ss. Perpetua and Felicity's own reference-engine file says "vide
|
||||||
|
// C7b", and votive=C7b returned these same groups/canticle/Laudate
|
||||||
|
// antiphons as plain votive=C7 (2026-08-28) -- only the Benedictus
|
||||||
|
// antiphon differs, a separate mechanism from this psalmody table.
|
||||||
|
const override = getLaudsCommonOverride('ss-perpetua-and-felicity');
|
||||||
|
expect(override?.id).toBe('common-of-a-holy-woman');
|
||||||
|
expect(override?.groups.map((g) => g.psalms)).toEqual([[92], [99], [62]]);
|
||||||
|
});
|
||||||
|
|
||||||
it("resolves St. Gregory the Great's own proper chapter/hymn, not a Common fallback", () => {
|
it("resolves St. Gregory the Great's own proper chapter/hymn, not a Common fallback", () => {
|
||||||
// Live-verified against Divinum Officium (Monastic Tridentinum
|
// Live-verified against Divinum Officium (Monastic Tridentinum
|
||||||
// 1617), 2033-03-12 (clean year). See lauds-capitulum-st-gregory-
|
// 1617), 2033-03-12 (clean year). See lauds-capitulum-st-gregory-
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { resolveOrdo } from '../../src/hours';
|
import { resolveOrdo } from '../../src/hours';
|
||||||
|
import { getVespersCommonOverride } from '../../src/hours/vespers-psalmody-overrides';
|
||||||
|
|
||||||
// Every id with an authored Vespers office override (2026-08 sweep) —
|
// Every id with an authored Vespers office override (2026-08 sweep) —
|
||||||
// same ids, same clean per-saint dates already established for each
|
// same ids, same clean per-saint dates already established for each
|
||||||
@@ -75,14 +76,15 @@ describe('resolveOrdo("vespers", ...)', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('joins Ps 115 and 116 under one shared antiphon on Monday', () => {
|
it('joins Ps 115 and 116 under one shared antiphon on Monday', () => {
|
||||||
// Not 2026-08-17: that Monday is actually the closing day of St.
|
// Not 2026-08-17 (the closing day of St. Lawrence's own octave, Aug
|
||||||
// Lawrence's own octave (Aug 10-17, Duplex II. classis) -- now that
|
// 10-17, Duplex II. classis) and not 2026-09-28 either (that Monday
|
||||||
// Vespers has its own duplex-majus+ psalmody override (2026-08-28),
|
// evening anticipates St. Michael's own First Vespers, Sept 29,
|
||||||
// that evening correctly gets Common-of-a-Martyr's own psalms
|
// Duplex I. classis) -- now that Vespers has its own duplex-majus+
|
||||||
// instead of the plain ferial Monday set, same as Lauds' own
|
// psalmody override (2026-08-28), both evenings correctly pick up a
|
||||||
// octave-day override already did. 2026-09-28 is a Monday clear of
|
// Common's own psalms instead of the plain ferial Monday set, same as
|
||||||
// any such collision.
|
// Lauds' own octave-day override already did. 2026-10-12 is a Monday
|
||||||
const ordo = resolveOrdo('vespers', '2026-09-28');
|
// clear of any such collision.
|
||||||
|
const ordo = resolveOrdo('vespers', '2026-10-12');
|
||||||
const psalmParts = ordo.parts.filter((p) => p.kind === 'psalm');
|
const psalmParts = ordo.parts.filter((p) => p.kind === 'psalm');
|
||||||
const numbers = psalmParts.map((p) => (p.kind === 'psalm' ? p.psalmNumber : undefined));
|
const numbers = psalmParts.map((p) => (p.kind === 'psalm' ? p.psalmNumber : undefined));
|
||||||
expect(numbers).toEqual([113, 114, 115, 116, 128]);
|
expect(numbers).toEqual([113, 114, 115, 116, 128]);
|
||||||
@@ -155,6 +157,66 @@ describe('resolveOrdo("vespers", ...)', () => {
|
|||||||
expect(numbers).toEqual([109, 111, 112, 131]);
|
expect(numbers).toEqual([109, 111, 112, 131]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses Common-of-an-Angel's own psalmody (reusing St. Michael's own proper text) on Guardian Angels' First Vespers", () => {
|
||||||
|
// Not Guardian Angels' own day itself (Oct 2, Duplex Majus): she
|
||||||
|
// falls short of keepsOwnSecondVespers's duplex-2-classis+ floor, and
|
||||||
|
// Oct 3 (St. Therese of Lisieux, plain Duplex, below this override's
|
||||||
|
// own threshold) claims First Vespers over her own evening, so Oct 2
|
||||||
|
// itself resolves to the plain ferial Friday default instead. Oct 1
|
||||||
|
// (St. Remigius, Simplex, doesn't keep his own evening either)
|
||||||
|
// anticipates Guardian Angels' own First Vespers instead, which does
|
||||||
|
// carry the override. Live-verified (2026-08-28) that her real
|
||||||
|
// Vespers antiphons are St. Michael's own, byte-for-byte, which is
|
||||||
|
// exactly what this category's content is (see data/hours/
|
||||||
|
// vespers-psalmody-overrides/categories/common-of-an-angel.yml's own
|
||||||
|
// header). Psalm numbers here are "Psalmi Dominica" (109-112), not a
|
||||||
|
// Common-specific set.
|
||||||
|
const ordo = resolveOrdo('vespers', '2026-10-01');
|
||||||
|
const numbers = ordo.parts.filter((p) => p.kind === 'psalm').map((p) => (p.kind === 'psalm' ? p.psalmNumber : undefined));
|
||||||
|
expect(numbers).toEqual([109, 110, 111, 112]);
|
||||||
|
const firstPsalm = ordo.parts.find((p) => p.kind === 'psalm');
|
||||||
|
expect(firstPsalm?.kind === 'psalm' ? firstPsalm.antiphon?.text.la : undefined).toContain('Stetit Angelus');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses Common-of-a-Dedication's own psalmody on the Dedication of the Basilica of the Most Holy Saviour's own day", () => {
|
||||||
|
// Nov 9, Duplex II. classis -- keeps its own evening regardless of
|
||||||
|
// tomorrow (Ss. Tryphon and Companions, Simplex). Live-verified
|
||||||
|
// against Divinum Officium (Monastic Tridentinum 1617, votive=C8),
|
||||||
|
// 2026-08-28 -- genuinely its own scheme, not shared with any other
|
||||||
|
// Common (see the category file's own header).
|
||||||
|
const ordo = resolveOrdo('vespers', '2026-11-09');
|
||||||
|
const numbers = ordo.parts.filter((p) => p.kind === 'psalm').map((p) => (p.kind === 'psalm' ? p.psalmNumber : undefined));
|
||||||
|
expect(numbers).toEqual([109, 110, 111, 147]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses Common-of-an-Apostle's own psalmody on St. Mark Evangelist's own day, via the common-of-an-evangelist alias", () => {
|
||||||
|
// St. Mark (Apr 25, Duplex II. classis, common: common-of-an-
|
||||||
|
// evangelist) has no per-feast Vespers override authored -- his own
|
||||||
|
// reference-engine rule file says "ex C1a", and votive=C1a returned
|
||||||
|
// byte-identical Lauds/Vespers psalmody to plain votive=C1
|
||||||
|
// (2026-08-28), so common-of-an-evangelist is aliased onto
|
||||||
|
// common-of-an-apostle rather than duplicated (see
|
||||||
|
// data/hours/vespers-psalmody-overrides/categories/
|
||||||
|
// common-of-an-apostle.yml's own header).
|
||||||
|
const ordo = resolveOrdo('vespers', '2026-04-25');
|
||||||
|
const numbers = ordo.parts.filter((p) => p.kind === 'psalm').map((p) => (p.kind === 'psalm' ? p.psalmNumber : undefined));
|
||||||
|
expect(numbers).toEqual([109, 112, 115, 138]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('aliases common-of-several-women-martyrs onto common-of-a-holy-woman for Vespers psalmody', () => {
|
||||||
|
// No majus+ saint on this calendar actually carries this Common yet
|
||||||
|
// (Ss. Perpetua and Felicity, the only one, are plain Duplex --
|
||||||
|
// below this override's threshold), so this can't be exercised via
|
||||||
|
// resolveOrdo/a real date; test the alias wiring directly instead.
|
||||||
|
// Ss. Perpetua and Felicity's own reference-engine file says "vide
|
||||||
|
// C7b", and votive=C7b returned these same four psalm numbers/
|
||||||
|
// antiphons as plain votive=C7 (2026-08-28) -- only the Magnificat
|
||||||
|
// antiphon differs, a separate mechanism from this psalmody table.
|
||||||
|
const override = getVespersCommonOverride('ss-perpetua-and-felicity');
|
||||||
|
expect(override?.id).toBe('common-of-a-holy-woman');
|
||||||
|
expect(override?.groups.map((g) => g.psalms)).toEqual([[109], [112], [121], [126]]);
|
||||||
|
});
|
||||||
|
|
||||||
it('stays on the plain ferial default for a below-threshold feast (Semiduplex), even on its own kept evening', () => {
|
it('stays on the plain ferial default for a below-threshold feast (Semiduplex), even on its own kept evening', () => {
|
||||||
// 2026-08-08 (Ss. Cyriacus/Largus/Smaragdus, Semiduplex) is below the
|
// 2026-08-08 (Ss. Cyriacus/Largus/Smaragdus, Semiduplex) is below the
|
||||||
// duplex-majus+ override threshold -- confirmed live against Divinum
|
// duplex-majus+ override threshold -- confirmed live against Divinum
|
||||||
|
|||||||
Reference in New Issue
Block a user