Port seasonal office content to Lauds, closing the same pre-existing gap
Deploy / deploy (push) Successful in 56s

Lauds had the identical issue Vespers started with: resolveOffice only
ever rendered the plain weekday chapter/responsory/hymn/versicle,
year-round, with no Advent/Lent/Passiontide/Paschaltide override —
same source file (Major Special.txt) as Vespers', just never wired up.
Ports the same seasonalOfficeSuffix-based precedence (per-feast/octave
override -> season -> weekday default) and the matching seasonal
content, transcribed the same way as Vespers' own (Monastic hymn
variants applied from the source's substitution notation against each
base Roman text). Paschaltide's chapter is byte-identical to Vespers'
own — the source aliases "[Pasch Vespera] = @:Pasch Laudes" — so both
hours' data files intentionally carry the same text rather than one
importing the other's id.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 20:15:29 -04:00
parent de83786793
commit f14d00bd73
18 changed files with 536 additions and 5 deletions
@@ -0,0 +1,13 @@
# Sourced from Divinum Officium's Monastic block ("[Adv Laudes_]",
# Psalterium/Special/Major Special.txt). Not live-query-verified (see
# TODO.md) — read directly from source.
id: lauds-capitulum-advent
text:
la: "Veníte, et ascendámus ad montem Dómini, et ad domum Dei Jacob, et docébit nos vias suas, et ambulábimus in sémitis ejus: quia de Sion exíbit lex, et verbum Dómini de Jerúsalem."
en: "Come and let us go up to the mountain of the Lord, and to the house of the God of Jacob, and he will teach us his ways, and we will walk in his paths: for the law shall come forth from Sion, and the word of the Lord from Jerusalem."
citation:
la: "Isa 2:3"
en: "Isa 2:3"
status:
la: draft
en: draft
@@ -0,0 +1,13 @@
# Sourced from Divinum Officium's Monastic block ("[Quad Laudes_]",
# Psalterium/Special/Major Special.txt). Not live-query-verified (see
# TODO.md) — read directly from source.
id: lauds-capitulum-lent
text:
la: "Clama, ne cesses, quasi tuba exálta vocem tuam, et annúntia pópulo meo scélera eórum, et dómui Jacob peccáta eórum."
en: "Cry, cease not, lift up thy voice like a trumpet, and show my people their wicked doings, and the house of Jacob their sins."
citation:
la: "Isa 58:1"
en: "Isa 58:1"
status:
la: draft
en: draft
@@ -0,0 +1,16 @@
# Sourced from Divinum Officium's Monastic block ("[Pasch Laudes]",
# Psalterium/Special/Major Special.txt) — Vespers shares this exact text
# (see vespers-capitulum-paschaltide.yml, "[Pasch Vespera] = @:Pasch
# Laudes" in the source). Covers the whole Easter-to-Pentecost span
# uniformly. Not live-query-verified (see TODO.md) — read directly from
# source.
id: lauds-capitulum-paschaltide
text:
la: "Christus resúrgens ex mórtuis jam non móritur, mors illi ultra non dominábitur. Quod enim mórtuus est peccáto, mórtuus est semel: quod autem vivit, vivit Deo."
en: "Knowing that Christ rising again from the dead, dieth now no more, death shall no more have dominion over him. For in that he died to sin, he died once; but in that he liveth, he liveth unto God."
citation:
la: "Rom 6:9-10"
en: "Rom 6:9-10"
status:
la: draft
en: draft
@@ -0,0 +1,13 @@
# Sourced from Divinum Officium's Monastic block ("[Quad5 Laudes_]",
# Psalterium/Special/Major Special.txt). Not live-query-verified (see
# TODO.md) — read directly from source.
id: lauds-capitulum-passiontide
text:
la: "Veníte, mittámus lignum in panem ejus, et eradámus eum de terra vivéntium, et nomen ejus non memorétur ámplius."
en: "Come, let us put wood on his bread, and cut him off from the land of the living, and let his name be remembered no more."
citation:
la: "Jer 11:19"
en: "Jer 11:19"
status:
la: draft
en: draft
@@ -0,0 +1,66 @@
# Sourced from Divinum Officium's Monastic block ("[HymnusM Adv Laudes]",
# resolving to "[HymnusM Adv Laudes_]" on the non-Cistercian branch —
# Psalterium/Special/Major Special.txt) — full separate Monastic text
# ("Vox clara ecce íntonat"), not a substitution against the Roman "En
# clara vox redárguit". English is the familiar John Mason Neale
# translation ("Hark! a herald voice is calling"), traditionally used for
# both this hymn's Roman and Monastic/Sarum recensions — a closer match
# than the Advent Vespers hymn's English got. Not live-query-verified (see
# TODO.md).
id: lauds-hymn-advent
text:
la: |
Vox clara ecce íntonat,
Obscúra quæque íncrepat:
Pellántur éminus sómnia;
Ab æthre Christus prómicat.
Mens jam resúrgat tórpida
Quæ sorde exstat sáucia;
Sidus refúlget jam novum,
Ut tollat omne nóxium.
E sursum Agnus míttitur
Laxáre gratis débitum:
Omnes pro indulgéntia
Vocem demus cum lácrimis,
Secúndo ut cum fúlserit,
Mundúmque horror cínxerit,
Non pro reátu púniat,
Sed nos pius tunc prótegat.
Laus, honor, virtus, glória,
Deo Patri, et Fílio,
Sancto simul Paráclito,
In sæculórum sǽcula.
Amen.
en: |
Hark, a herald voice is calling;
"Christ is nigh," it seems to say;
"Cast away the dreams of darkness,
O ye children of the day."
Startled at the solemn warning,
Let the earth-bound soul arise;
Christ, her sun, all sloth dispelling,
Shines upon the morning skies.
Lo, the Lamb, so long expected,
Comes with pardon down from heaven;
Let us haste, with tears of sorrow,
One and all to be forgiven.
So when next he comes with glory,
Wrapping all the earth in fear,
May he then as our defender
On the clouds of heaven appear.
Honour, glory, virtue, merit,
To the Father and the Son,
With the co-eternal Spirit,
While eternal ages run.
Amen.
status:
la: draft
en: draft
@@ -0,0 +1,62 @@
# Sourced from Divinum Officium's Monastic block ("[HymnusM Quad
# Laudes]", Psalterium/Special/Major Special.txt) — full separate
# Monastic text ("Jam Christe sol justítiæ"), not a substitution against
# the Roman "O sol salútis, íntimis". Not live-query-verified (see
# TODO.md).
id: lauds-hymn-lent
text:
la: |
Jam Christe sol justítiæ,
Mentis diéscant ténebræ:
Virtútum ut lux rédeat,
Terris diem cum réparas.
Dans tempus acceptábile,
Et pǽnitens cor tríbue,
Convértat ut benígnitas
Quos longa suffert píetas.
Quiddámque pæniténtiæ
Da ferre, quamvis grávium,
Majóre tuo múnere,
Quo démptio fit críminum.
Dies venit, dies tua,
In qua reflórent ómnia:
Lætémur in hac ad tuam
Per hanc redúcti grátiam.
Te rerum univérsitas,
Clemens, adóret, Trínitas,
Et nos novi per véniam,
Novum canámus cánticum.
Amen.
en: |
Jesu, salvation's Sun Divine,
Within our inmost bosoms shine,
With light all darkness drive away
And give the world a better day.
Now days of grace with mercy flow,
O Lord, the gift of tears bestow,
To wash our stains in every part,
Whilst heavenly fire consumes the heart.
Rise, crystal tears, from that same source
From whence our sins derive their course;
Nor cease, till hardened hearts relent,
And softened by your streams, repent.
Behold, the happy days return,
The days of joy for them that mourn;
May we of their indulgence share,
And bless the God that grants our prayer.
May heaven and earth aloud proclaim
The Trinity's almighty fame;
And we, restored to grace, rejoice
In newness both of heart and voice.
Amen.
status:
la: draft
en: draft
@@ -0,0 +1,72 @@
# Sourced from Divinum Officium's Monastic block ("[HymnusM Pasch
# Laudes_]", the non-Dominican branch "[HymnusM Pasch Laudes]" resolves
# to — Psalterium/Special/Major Special.txt) — "Auróra lucis rútilat",
# full separate Monastic text (not a substitution against the Roman
# "Auróra cælum púrpurat"). Not live-query-verified (see TODO.md).
id: lauds-hymn-paschaltide
text:
la: |
Auróra lucis rútilat,
Cælum láudibus íntonat,
Mundus exsúltans júbilat,
Gemens inférnus úlulat:
Cum Rex ille fortíssimus,
Mortis confráctis víribus,
Pede concúlcans tártara,
Solvit a pœna míseros.
Ille qui clausus lápide
Custodítur sub mílite,
Triúmphans pompa nóbili,
Victor surgit de fúnere.
Solútis jam gemítibus,
Et inférni dolóribus,
Quia surréxit Dóminus,
Respléndens clamat Ángelus.
Quǽsumus, Auctor ómnium,
In hoc pascháli gáudio,
Ab omni mortis ímpetu
Tuum defénde pópulum.
Glória tibi Dómine,
Qui surrexísti a mórtuis,
Cum Patre et Sancto Spíritu,
In sempitérna sǽcula.
Amen.
en: |
The morn had spread her crimson rays,
When rang the skies with shouts of praise;
Earth joined the joyful hymn to swell,
That brought despair to vanquished hell.
He comes victorious from the grave,
The Lord omnipotent to save,
And brings with him to light of day
The saints who long imprisoned lay.
Vain is the cavern's three-fold ward —
The stone, the seal, the armed guard;
O death, no more thine arm we fear,
The Victor's tomb is now thy bier.
Let hymns of joy to grief succeed,
We know that Christ is risen indeed;
We hear his white-robed angel's voice,
And in our risen Lord rejoice.
With Christ we died, with Christ we rose,
When at the font his name we chose;
Oh, let not sin our robes defile,
And turn to grief the paschal smile.
To God the Father let us sing,
To God the Son, our risen King,
And equally let us adore
The Spirit, God forevermore.
Amen.
status:
la: draft
en: draft
@@ -0,0 +1,96 @@
# Sourced from Divinum Officium's Monastic block ("[HymnusM Quad5
# Laudes]", Psalterium/Special/Major Special.txt) — "Lustris sex qui jam
# peráctis", full separate Monastic text (not a substitution against the
# Roman "Lustra sex qui jam perégit" — the two differ throughout, not
# just in wording). Not live-query-verified (see TODO.md).
id: lauds-hymn-passiontide
text:
la: |
Lustris sex qui jam peráctis,
Tempus implens córporis,
Se volénte natus ad hoc,
Passióni déditus,
Agnus in Crucis levátur
Immolándus stípite.
Hic acétum, fel, arúndo,
Sputa, clavi, láncea:
Mite corpus perforátur,
Sanguis, unda prófluit:
Terra, pontus, astra, mundus,
Quo lavántur flúmine!
Crux fidélis, inter omnes
Arbor una nóbilis:
Nulla silva talem profert
Fronde, flore, gérmine:
Dulce lignum, dulces clavos,
Dulce pondus sústinet.
Flecte ramos, arbor alta,
Tensa laxa víscera,
Et rigor lentéscat ille,
Quem dedit natívitas:
Ut supérni membra Regis
Miti tendas stípite.
Sola digna tu fuísti
Ferre sæcli prétium,
Atque portum præparáre
Nauta mundo náufrago,
Quem sacer cruor perúnxit,
Fusus Agni córpore.
Glória et honor Deo
Usquequáque altíssimo:
Una Patri, Filióque,
Inclyto Paráclito:
Cui laus est et potéstas
Per ætérna sǽcula.
Amen.
en: |
Thirty years among us dwelling,
His appointed time fulfilled,
Born for this, he meets his passion,
For that this he freely willed:
On the cross the Lamb is lifted,
Where his life-blood shall be spilled.
He endured the nails, the spitting,
Vinegar, and spear, and reed;
From that holy body broken
Blood and water forth proceed:
Earth, and stars, and sky, and ocean,
By that flood from stain are free.
Faithful cross! above all other,
One and only noble tree!
None in foliage, none in blossom,
None in fruit thy peers may be;
Sweetest wood and sweetest iron!
Sweetest weight is hung on thee.
Bend thy boughs, O tree of glory!
Thy relaxing sinews bend;
For awhile the ancient rigour,
That thy birth bestowed, suspend;
And the King of heavenly beauty
On thy bosom gently tend!
Thou alone wast counted worthy
This world's ransom to uphold;
For a shipwrecked race preparing
Harbour, like the ark of old;
With the sacred blood anointed
From the smitten Lamb that rolled.
To the Trinity be glory
Everlasting, as is meet;
Equal to the Father, equal
To the Son, and Paraclete:
Trinal Unity, whose praises
All created things repeat.
Amen.
status:
la: draft
en: draft
@@ -0,0 +1,22 @@
# Sourced from Divinum Officium's Monastic block ("[Responsory Adv
# Laudes]", Psalterium/Special/Major Special.txt). Not live-query-verified
# (see TODO.md) — read directly from source.
id: lauds-responsory-advent
text:
la: |
R.br. Veni ad liberándum nos * Dómine Deus virtútum.
R. Veni ad liberándum nos * Dómine Deus virtútum.
V. Osténde fáciem tuam et salvi érimus.
R. Dómine Deus virtútum.
V. Glória Patri, et Fílio, * et Spirítui Sancto.
R. Veni ad liberándum nos * Dómine Deus virtútum.
en: |
R.br. Come to my rescue, * O God, Lord of hosts.
R. Come to my rescue, * O God, Lord of hosts.
V. Show us thy face, and we shall be saved.
R. O God, Lord of hosts.
V. Glory be to the Father, and to the Son, * and to the Holy Ghost.
R. Come to my rescue, * O God, Lord of hosts.
status:
la: draft
en: draft
@@ -0,0 +1,22 @@
# Sourced from Divinum Officium's Monastic block ("[Responsory Quad
# Laudes]", Psalterium/Special/Major Special.txt). Not live-query-verified
# (see TODO.md) — read directly from source.
id: lauds-responsory-lent
text:
la: |
R.br. Ipse liberávit me * de láqueo venántium.
R. Ipse liberávit me * de láqueo venántium.
V. Et a verbo áspero.
R. De láqueo venántium.
V. Glória Patri, et Fílio, * et Spirítui Sancto.
R. Ipse liberávit me * de láqueo venántium.
en: |
R.br. For he hath delivered me * from the snare of the hunters.
R. For he hath delivered me * from the snare of the hunters.
V. And from the sharp word.
R. From the snare of the hunters.
V. Glory be to the Father, and to the Son, * and to the Holy Ghost.
R. For he hath delivered me * from the snare of the hunters.
status:
la: draft
en: draft
@@ -0,0 +1,26 @@
# Sourced from Divinum Officium's Monastic block: "[Responsory Pasch
# Laudes]" resolves (non-Cistercian branch) to "@Psalterium/Special/Minor
# Special:Responsory breve Pasch Tertia" -> "[Responsory breve Pasch
# Tertia_]" (Psalterium/Special/Minor Special.txt) — distinct from
# Vespers' own Paschaltide responsory (see
# vespers-responsory-paschaltide.yml). Not live-query-verified (see
# TODO.md) — read directly from source.
id: lauds-responsory-paschaltide
text:
la: |
R.br. Surréxit Dóminus de sepúlcro, * Allelúja, allelúja.
R. Surréxit Dóminus de sepúlcro, * Allelúja, allelúja.
V. Qui pro nobis pepéndit in ligno.
R. Allelúja, allelúja.
V. Glória Patri, et Fílio, * et Spirítui Sancto.
R. Surréxit Dóminus de sepúlcro, * Allelúja, allelúja.
en: |
R.br. The Lord is risen from the sepulchre, * alleluia, alleluia.
R. The Lord is risen from the sepulchre, * alleluia, alleluia.
V. Who for us was hanged on the tree.
R. Alleluia, alleluia.
V. Glory be to the Father, and to the Son, * and to the Holy Ghost.
R. The Lord is risen from the sepulchre, * alleluia, alleluia.
status:
la: draft
en: draft
@@ -0,0 +1,23 @@
# Sourced from Divinum Officium's Monastic block ("[Responsory Quad5
# Laudes_]", the non-Cistercian branch "[Responsory Quad5 Laudes]"
# resolves to — Psalterium/Special/Major Special.txt). Real Passiontide
# practice omits the Gloria Patri here too — matches the source exactly
# (see vespers-responsory-passiontide.yml). Not live-query-verified (see
# TODO.md).
id: lauds-responsory-passiontide
text:
la: |
R.br. Érue a frámea * Deus ánimam meam.
R. Érue a frámea * Deus ánimam meam.
V. Et de manu canis únicam meam.
R. Deus ánimam meam.
R. Érue a frámea * Deus ánimam meam.
en: |
R.br. Deliver, * O God, my soul from the sword.
R. Deliver, * O God, my soul from the sword.
V. My only one from the hand of the dog.
R. O God, my soul from the sword.
R. Deliver, * O God, my soul from the sword.
status:
la: draft
en: draft
@@ -0,0 +1,14 @@
# Sourced from Divinum Officium's Monastic block ("[Adv Versum 2_]",
# Psalterium/Special/Major Special.txt). Not live-query-verified (see
# TODO.md) — read directly from source.
id: lauds-versicle-advent
text:
la: |
V. Vox clamántis in desérto: Paráte viam Dómini.
R. Rectas fácite sémitas ejus.
en: |
V. A voice of one crying in the wilderness: Prepare the way of the Lord.
R. Make straight his paths.
status:
la: draft
en: draft
@@ -0,0 +1,15 @@
# The versicle right before the Benedictus, in Lent. Sourced from Divinum
# Officium's Monastic block: "[Quad Versum 2] = @:Quad Versum 3" — a bare
# alias to the same text used at Vespers (see vespers-versicle-lent.yml).
# Not live-query-verified (see TODO.md) — read directly from source.
id: lauds-versicle-lent
text:
la: |
V. Ángelis suis Deus mandávit de te.
R. Ut custódiant te in ómnibus viis tuis.
en: |
V. God hath given His Angels charge over thee.
R. To keep thee in all thy ways.
status:
la: draft
en: draft
@@ -0,0 +1,16 @@
# Sourced from Divinum Officium's Monastic block ("[Pasch Versum 2_]",
# the non-Cistercian/non-Dominican branch "[Pasch Versum 2]" resolves to
# — Psalterium/Special/Major Special.txt). Distinct from Vespers' own
# Paschaltide versicle (see vespers-versicle-paschaltide.yml). Not
# live-query-verified (see TODO.md) — read directly from source.
id: lauds-versicle-paschaltide
text:
la: |
V. In resurrectióne tua, Christe, allelúja.
R. Cæli et terra læténtur, allelúja.
en: |
V. Christ, in thy resurrection, alleluia.
R. Let heaven and earth rejoice, alleluia.
status:
la: draft
en: draft
@@ -0,0 +1,14 @@
# Sourced from Divinum Officium's Monastic block ("[Quad5 Versum 2_]",
# Psalterium/Special/Major Special.txt). Not live-query-verified (see
# TODO.md) — read directly from source.
id: lauds-versicle-passiontide
text:
la: |
V. Éripe me de inimícis meis, Deus meus.
R. Et ab insurgéntibus in me líbera me.
en: |
V. Deliver me from my enemies, O my God.
R. And defend me from them that rise up against me.
status:
la: draft
en: draft
+12 -5
View File
@@ -17,6 +17,7 @@ import {
resolveOfficeWinner,
ALWAYS_OVERRIDE_TEMPORAL_IDS,
verifiedText,
seasonalOfficeSuffix,
} from './resolve-common';
import laudsDefinitionData from '../data/hours/lauds.yml';
import laudsAntiphonsData from '../data/hours/lauds-antiphons.yml';
@@ -187,7 +188,11 @@ function resolvePsalmody(day: LiturgicalDay): ResolvedPart[] {
* getPsalmodyOverrideFor) and leave this bundle at its plain weekday
* default, which is exactly what falls back here when the id-keyed
* capitulum doesn't exist (same dual-missing-status "not authored"
* signal used throughout this codebase, not a special case). */
* signal used throughout this codebase, not a special case). Falls to a
* *seasonal* default next (Advent/Lent/Passiontide/Paschaltide — see
* resolve-common.ts's seasonalOfficeSuffix), and only then the plain
* weekday default — a feast's own override always wins over the season
* it happens to fall in, same as everywhere else in this codebase. */
function resolveOffice(day: LiturgicalDay): ResolvedPart[] {
const overrideId = getPsalmodyOverrideFor(day)?.id;
if (overrideId) {
@@ -201,11 +206,13 @@ function resolveOffice(day: LiturgicalDay): ResolvedPart[] {
];
}
}
const seasonSuffix = seasonalOfficeSuffix(day.season);
const key = seasonSuffix ?? day.weekday;
return [
{ kind: 'chapter', text: resolveCommon(capitulumId(day.weekday)) },
{ kind: 'responsory', text: resolveCommon(`lauds-responsory-${day.weekday}`) },
{ kind: 'hymn', text: resolveCommon(`lauds-hymn-${day.weekday}`) },
{ kind: 'versicle', text: resolveCommon(`lauds-versicle-${day.weekday}`) },
{ kind: 'chapter', text: resolveCommon(seasonSuffix ? `lauds-capitulum-${key}` : capitulumId(day.weekday)) },
{ kind: 'responsory', text: resolveCommon(`lauds-responsory-${key}`) },
{ kind: 'hymn', text: resolveCommon(`lauds-hymn-${key}`) },
{ kind: 'versicle', text: resolveCommon(`lauds-versicle-${key}`) },
];
}
+21
View File
@@ -298,4 +298,25 @@ describe('resolveOrdo("lauds", ...)', () => {
expect(last?.kind).toBe('preces');
expect(last?.kind === 'preces' ? last.label : undefined).toBe('Salve Regina');
});
it("renders Advent's seasonal chapter/hymn/versicle instead of the plain weekday default", () => {
// 2025-12-02 is a Tuesday in Advent (St. Bibiana, Simplex, merely
// commemorated — the day's own winner stays temporal either way).
const ordo = resolveOrdo('lauds', '2025-12-02');
const chapter = ordo.parts.find((p) => p.kind === 'chapter');
expect(chapter?.kind === 'chapter' ? chapter.text.citation?.en : undefined).toBe('Isa 2:3');
const hymn = ordo.parts.find((p) => p.kind === 'hymn');
expect(hymn?.kind === 'hymn' ? hymn.text.text.la : undefined).toContain('Vox clara ecce íntonat');
const versicle = ordo.parts.find((p) => p.kind === 'versicle' && p.text.text.la?.includes('Vox clamántis'));
expect(versicle).toBeDefined();
});
it("renders Paschaltide's seasonal office, sharing its chapter with Vespers", () => {
// 2026-04-20 is in eastertide (Easter 2026-04-05).
const ordo = resolveOrdo('lauds', '2026-04-20');
const chapter = ordo.parts.find((p) => p.kind === 'chapter');
expect(chapter?.kind === 'chapter' ? chapter.text.citation?.en : undefined).toBe('Rom 6:9-10');
const hymn = ordo.parts.find((p) => p.kind === 'hymn');
expect(hymn?.kind === 'hymn' ? hymn.text.text.la : undefined).toContain('Auróra lucis rútilat');
});
});