An earlier comment in sanctoral-calendar.yml claimed this app
deliberately avoids modeling the Requiem/funeral rite as a genre at
all. That was wrong — confirmed not sourced from CLAUDE.md, and
corrected per direct instruction: a reusable Office-for-the-Dead
mechanism (funerals, anniversaries, not just Nov 2) is real wanted
future scope. Updates the November sanctoral-calendar.yml header
accordingly and logs the All Souls' Day build + same-day
generalization into office-of-the-dead.ts as a dated TODO.md entry.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
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
Cover the mechanism fix (next commit) end to end via resolveOrdo, one
representative propers:null saint per new category, including the
reported St. Lawrence Justinian bug itself (2026-09-05 Vespers).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016CEDsGWWCEHkZnkNzhX3TD
Add one *-commemoration-antiphon.yml per Common category (14 total,
covering every category used by a propers:null saint) plus two missing
lauds-versicle-common-of-* files (dedication, several women martyrs),
sourced directly from the reference engine's Commune [Ant 2]/[Versum 2]
tags. This is the content half of closing the gap where commemorations
for saints without their own proper file (e.g. St. Lawrence Justinian)
rendered with no antiphon at all.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016CEDsGWWCEHkZnkNzhX3TD
The Octave Day of Ss. Peter and Paul (Jul 6) uses common:
common-of-apostles (the plural id, distinct from the singular
common-of-an-apostle most single-apostle feasts use), but no
matins-hymn-common-of-apostles.yml or matins-invitatory-common-of-
apostles.yml existed, so it fell through to the plain ferial default for
both. Duplicated the singular Common's identical source text under the
plural id, matching the existing convention already used for that
Common's Lauds hymn/capitulum/responsory/versicle files.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
Same gap as All Saints: Finding of the Holy Cross, Exaltation of the
Holy Cross, Most Precious Blood, Transfiguration, and Visitation of the
BVM are all duplex-majus+ feasts with a fake "proper-to-*" common and no
matins-invitatory-<id>.yml of their own, so each fell through to the
plain ferial default. Sourced from each one's own Sancti/MM-DD.txt
[Invit] block (none has a Monastic override).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
The Octave Day of All Saints (Nov 8) and All Saints of the Benedictine
Order (Nov 13) are each their own separate sanctoral record with a fake
"proper-to-*" common, cross-referencing All Saints' own proper text in
the reference source. resolveMatinsInvitatoryText had no octave tier
(unlike resolveMatinsHymn, which already had one), so Nov 8 fell through
to the plain ferial default instead of reusing All Saints' own text.
Restored the tier to match resolveMatinsHymn's, and authored Nov 13's
own file directly since its source cross-references All Saints outright.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
Nov 1 fell through to the generic ferial invitatory antiphon instead of
its own proper text, since neither a matins-invitatory-all-saints.yml
override nor a real Common category existed to catch it. Sourced from
the reference engine's secular Sancti/11-01.txt [Invit] (the Monastic
SanctiM file has no override of its own here).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
temporalLabel's season-fallback branch used day.season, which lumps
Septuagesima/Sexagesima/Quinquagesima into one coarse 'septuagesima'
bucket — so all three Sundays rendered as "Septuagesima Sunday". Now
distinguishes them via resolveTemporalId, the same governing-Sunday id
the content layer already keys collects/propers off of.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
A resumed post-Epiphany Sunday/week (overflow years, e.g. 11/8/2026)
read as plain "after Epiphany", indistinguishable from an ordinary
in-season post-Epiphany Sunday. Append ", resumed" / ", resumpta" so
the label reflects that it's the overflow case.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
An active octave's own reading (data/propers/octave-readings/*.yml) is
a direct Scripture excerpt, not patristic homily commentary -- the same
kind of content as the bible-plan readings, not the winner's/
commemorations' own homiletic pool. It was being appended at the very
end of buildReadingPool unconditionally, landing after every other
reading regardless of who won the day or how many commemorations
piled on. Moved to right after the bible-plan block instead, so it
groups with other Scripture-type content rather than trailing behind
patristic homilies.
Live case: Nov 8, 2026 (All Saints' octave closing day) previously
read [1 Tim 1, St. Cyprian, Gospel, St. Augustine, St. Athanasius,
Gospel, Ezekiel] -- Ezekiel now sits right after 1 Tim 1, ahead of
everything else, per direct instruction.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
Follow-up to All Saints' own fix: audited every duplex-majus+ saint's
nocturn-readings file for a missing Nocturn 3 Gospel entry and checked
each of the 14 gaps found against the real historical source
(Divinum Officium, Monastic Tridentinum 1617 track).
Real Gospel+homily authored (4): Apparition of St. Michael (Matt
18:1-10 + St. Hilary of Poitiers), St. Barnabas (Matt 10:16-22 + St.
John Chrysostom), St. Bartholomew (Luke 6:12-19 + St. Ambrose).
Homily-only, Gospel citation is a bare incipit with no full text
recoverable anywhere in the reference source (2): St. Maurus, St.
Patrick.
Confirmed genuinely absent in the source, header comments corrected to
say so explicitly (8): Conversion of St. Paul, Our Lady of Mount Carmel,
Our Lady of Ransom, Ss. Placid and Companions, St. Ignatius of Loyola,
St. Luke, St. Mark, St. Scholastica.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
Nov 1's own content had several real gaps and one transcription bug,
found live-verifying against Divinum Officium (Monastic Tridentinum
1617, 2026-11-01, clean year):
- Matins Nocturn 3 had no Gospel (Matt 5:1-12, the Beatitudes) or St.
Augustine's homily on it -- a 2026-09-05 pass had wrongly assumed a
duplex-1-classis feast like this one shouldn't carry its own
Gospel/homily pairing. Authored with the full canonical text (chased
down via the Mass propers' own Evangelium, since Matins' own lesson
gives only a bare "Et réliqua" incipit) rather than just the incipit.
- Vespers had no Magnificat antiphon at all ("O quam gloriósum est
regnum...").
- Vespers had no proper psalmody override, so it fell back to the plain
4-psalm Sunday default; the real office uses 5 psalms (109/110/111/
112/115), each with its own proper antiphon.
- Both the Lauds and Vespers hymn files had the right English translation
paired with the WRONG Latin recension (the 1631 Urban VIII revision,
"Jesu Salvátor sæculi"/"Christe Redémptor ómnium") -- the live Monastic
engine actually renders the older pre-Urban VIII text ("Salútis ætérnæ
dator" for Lauds, "Placáre, Christe, sérvulis" for Vespers/Matins,
confirmed identical between those two hours). Corrected both, and
authored Matins' own hymn file (previously missing entirely, silently
falling back to the plain ferial hymn).
- St. Raphael the Archangel's own Nocturn 3 Gospel (John 5:1-4) was
previously left as homily-only because Matins' own lesson gives only a
bare incipit -- same fix as All Saints, full text recovered from the
Mass propers instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
resolveOrdo's Sunday-nocturn branch fired unconditionally whenever
day.weekday === 'sunday', regardless of who actually won the day --
silently making any saint's own proper Matins psalmody override
(getMatinsSaintOverride) unreachable on a Sunday, even when authored.
The source's own "Psalmi Dominica" rubric line reads as if the plain
Sunday psalm cursus always applies whenever a Duplex+ feast wins over a
Sunday, but live-querying All Saints (Nov 1, 2026, a Sunday that year)
shows it actually has its own distinct proper psalms (Ps 1/4/8, 14/23/
31, 33/60/96, each its own antiphon) -- not the plain Sunday Nocturn
psalms this app was falling back to. Checks for a sanctoral proper
override before the Sunday branch now.
That override's own Nocturn 3 is psalms, not the 3-OT-canticle shape
every other saint/category file uses -- added renderOverrideNocturn3 to
dispatch on which field is actually populated instead of assuming
canticles unconditionally (which produced a silently empty antiphon and
no content).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
collectCommemorations dropped the plain temporal commemoration name
unconditionally whenever anything else won the day, treating a
commemorated Sunday the same as a commemorated ferial weekday. But a
Sunday isn't "just an ordinary weekday" the way a ferial Tuesday is --
it's real information a reader can't infer from the winner+rank alone,
and it's exactly why a bare commemoration collect (now a full bundle,
previous commit) is being said in the first place. Divino Afflatu
1954's own commemoration line for a comparable case (St. Joachim
winning a Sunday, Aug 16 2026) confirms this: it names the Sunday, no
octave -- restoring that instead of a 2026-09-05 change that had
over-corrected past the actual rule.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
getDayCollects previously rendered a commemorated Sunday/privileged
feria (calendar/commemorations.ts's ordinary-sunday/privileged-sunday/
privileged-feria-minor branches) as a bare, unlabeled collect -- no
antiphon, no versicle, no indication it was even a commemoration. Only
sanctoral commemorations had gotten the fuller bundle treatment
(2026-08-30 pass). Adds temporalCommemorationPart, reusing the temporal
day's own benedictus/magnificat antiphon and weekday-keyed versicle (the
same content it would use had it won outright), falling back to a
labeled bare collect or honest "missing" block when no antiphon is
authored for that id.
Verified live for Nov 1, 2026 (All Saints on a Sunday): both Lauds and
Vespers now show "Commemoration of The 22nd Sunday after Trinity" with
real antiphon and versicle instead of a silent bare prayer.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
occasionName's fallback reused getDayLabel(day), which is winner-centric
-- when a sanctoral feast wins the day, it returns the winner's own full
label including rank (e.g. "All Saints (Duplex I Class)"), so a reading
tagged with the governing Sunday's temporal id got wrapped as "(for All
Saints (Duplex I Class))" instead of naming the Sunday. Exports
day-label.ts's existing temporalLabel helper (the plain ordinal Sunday/
feria name, independent of who won) and uses it instead whenever a
saint has won the day.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
Cut the intro/priority blurb, dropped the epilogue prose after
"none currently open" (that detail lives in the dated log below),
stripped New Features down to just the features, and removed the
Known Simplifications list entirely since it isn't open work — that
detail already lives as comments in temporal-categories.yml.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
The 2026-08-28 note blocking Lauds' Common-of-a-Dedication file was
based on a mis-targeted live query (plain ferial Thursday's own output,
not actually votive=C8) rather than a real content gap. Fix the
Vespers file's header comment and close out the corresponding TODO.md
backlog entries with a dated log entry.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
Live-verified the real scheme against Divinum Officium (Monastic
Tridentinum 1617, votive=C8) across all 7 weekdays: proper antiphons on
Ps 50/5/35, plus a canticle slot whose antiphon is fixed to this Common
but whose underlying text follows the plain ferial weekday rotation
(all 7 already authored). Required making
LaudsPsalmodyOverride.canticle.id optional and having resolvePsalmody
splice in the day's own ferial canticle when a category omits it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGsATZvfnpQ81HQuoF5JuL
When a Gospel+homily pair is folded into one pool entry, the homily's
own text was never registered in seenReadingText -- only the Gospel
pericope's text was. Not live for any date today, but the same
structural mistake already fixed once for two ids pooling the same
Gregory the Great excerpt: a later pooled id whose solo lesson happens
to share a homily's exact text would render as a visible duplicate.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6rG4RTNqLFYcyjbCGkPFs
The octave-reading branch never called withOccasion/occasionName at
all, so an active octave's own reading always showed a bare source
even when pooled alongside other content on the same day -- the same
missing-annotation gap just fixed for plain-Sunday and saint/temporal
readings, in a fourth branch that predates that helper. octave-readings'
source is bilingual ({la, en}), unlike nocturn-readings' plain string,
so the occasion suffix is appended to both language slots directly
rather than routed through withOccasion itself.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6rG4RTNqLFYcyjbCGkPFs
occasionName() only recognized saints, named temporal feasts, and Ember
days, so any reading pooled under a plain governing-Sunday id
(post-pentecost-15, month-week-092, etc.) -- the most common id shape
in the whole pool -- silently got no "(for ...)" annotation. This is
why Sept 6's Gregory the Great homily and its paired Augustine Gospel
homily showed up with no indication of why they were present. Falls
back to the same getDayLabel() the day's own heading already uses.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T6rG4RTNqLFYcyjbCGkPFs
Unlike the ~110 files fixed previously (a homily present with no
paired Gospel), these 6 had no Nocturn 3 at all: nativity-bvm.yml
(Matt 1:1-16 + St. Jerome), ss-cletus-and-marcellinus.yml/
ss-soter-and-caius.yml (Common-of-Popes, Matt 16:13-19 + Leo's Sermon
2 on his own Election, reused from st-martin-i.yml), ss-cornelius-and-
cyprian.yml (Common-of-Martyrs, Luke 21:9-19 + Gregory's Homily 35),
ss-seven-brothers-rufina-and-secunda.yml (a proper override, Matt
12:46-50 + Gregory's Homily 3), and st-anacletus.yml (an alternate
"rubrica 1570 aut rubrica 1617" variant carrying real content the
file's modern-rubric default lacks entirely -- Luke 14:26-33 +
Gregory's Homily 37, English composed directly from the Latin where
no reference-engine translation lines up with this Lectio split).
npm test (2029 passed) and tsc --noEmit both pass; live-verified via
resolveOrdo on all 6 saints' real dates.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKC2QQGLYo2UTiDjDyWEkW
~110 of 355 nocturn-readings files had a patristic homily with no
paired Gospel-pericope text -- the homily discussing a Gospel that was
never itself transcribed into the file. Closed in two waves (the first
pass's source-string regex missed many real cases where the citation
lived only in a header comment or wasn't named at all), each entry
sourced from divinum-officium-reference's own Missale files (following
Sancti/Commune redirects where a feast reuses another's Gospel) and
verified per file rather than assumed -- several candidates turned out
to be genuine Nocturn 2 content or Common-of-saints cross-references
with no proper Gospel of their own, correctly left untouched.
Includes both live-reported gaps: St. Joseph of Cupertino's own Bk. II
Homily 38 (Matt 22:1-14) and the Vigil of St. Matthew's Ambrose homily
(Luke 5:27-32).
TODO.md logs the closed item plus a new, distinct follow-up: a handful
of files with no Nocturn 3 content authored at all (not just an
unpaired Gospel), found along the way.
npm test (2029 passed) and tsc --noEmit both pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKC2QQGLYo2UTiDjDyWEkW
- nocturnReadingIds no longer lets a demoted commemoration's temporal id
(equal to the plain governing-Sunday temporalId) sneak a Sunday's own
homily into an unrelated weekday's pool via the commemorations loop —
a second code path than the one a prior fix gated, affecting 18
days/year.
- Reading pool order now follows id priority (winner first, then every
temporal commemoration, then every sanctoral commemoration) instead of
raw nocturn-tag/array order, matching the day label's own
temporal-then-sanctoral convention.
- gospelReadingPart now falls back to the paired homily's own responsory
when the Gospel entry has none of its own, instead of silently
dropping it.
- Patristic source labels now show "(for <occasion>)" so a reader can
tell which occasion a pooled reading belongs to on a multi-reading day.
- collectCommemorations no longer restates the plain generic temporal
label (e.g. "Saturday in the 15th week after Trinity") once anything
else is already being celebrated — general, not Ember-specific.
Updated 4 day-label tests that encoded the old behavior.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKC2QQGLYo2UTiDjDyWEkW
post-pentecost-15 and month-week-092 land on the same Sunday
(2026-09-06) and independently reuse the identical Gregory the Great
Moralia in Job excerpt -- a real duplication in the reference engine's
own Tempora files, not a vu authoring error. buildReadingPool pooled
both ids and rendered the reading twice; now dedupes by text.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKC2QQGLYo2UTiDjDyWEkW
No liturgical precedent exists for this book; the verse's antithesis
("the hand of our God is upon all them that seek him in goodness: and
his power and strength, and wrath upon all them that forsake him") is
reordered so the hopeful clause repeats after the V., not the wrath
clause. Closes the per-book pool at 68/72 -- the last 4 have no
sourceable material at all.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALE7phKTAnmRWvWMU9dZa7
Nehemiah was wrongly bundled in with ezra's "ambiguous, not acted on"
reasoning and left unseeded. It actually has a real, unambiguous
citation in the Missa (Ember Wednesday of September's Lectio/Communio,
Neh 8:1-10) that a prior pass never checked. R. from v.3, V. from v.9,
both from that accented Missa Lectio.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALE7phKTAnmRWvWMU9dZa7
User-directed: compose Ruth's own responsory from Ruth 1:16-17 ("thy
people shall be my people, and thy God my God") on the verse's own
merit. Unlike deut/rom/bar, this text has no liturgical precedent
anywhere in the reference source (no Nuptial Mass file even exists
there) -- flagged that distinction before proceeding; user confirmed
explicitly.
Since data/scripture/ruth-1.yml (the usual bulk import) carries no
accents, the Latin was hand-accented rather than transcribed, but
cross-checked word-by-word against already-accented occurrences of
the same words elsewhere in the corpus rather than guessed freehand.
66 of 72 bible-plan books now seeded. npm test (2029 passed) and
tsc --noEmit pass; live-verified through getBiblePlanReadings.
Canonical-key audit re-run, clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
Vulgate "Esdras" numbering is genuinely ambiguous: 1/2 Esdras is
canonical Ezra/Nehemiah, but there's also a separate non-canonical
Greek "Esdras A" (the Vulgate appendix's own 3 Esdras, sometimes
itself called "1 Esdras" in Septuagint/Orthodox numbering) -- a
different text this project has never digitized. The reference
engine's own citation never disambiguates, so this can't be
confirmed, but it cleanly explains why the Pasc7-2.txt Introit's
"Esdr 2:36-37" citation doesn't match our canonical Ezra text.
Practical outcome unchanged (ezra stays unseeded), now documented
with a clear reason rather than an open mystery.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
User pointed to missa/Latin/Tempora/Quad6-6.txt -- the Mass propers, a
directory tree this whole responsory search had never once checked
(everything so far searched horas/, the Divine Office proper). The
Easter Vigil Mass's own fourth prophecy ([Proph_Baruch3], Bar 3:9-38,
"Audi, Israel, mandata vitae") is genuine, real, accented liturgical
Latin -- just never part of Matins at all.
Composed bar the same way as deut/rom: built from that prophecy's own
climactic close ("Hic est Deus noster... Post haec in terris visus
est, et cum hominibus conversatus est" -- read at the Vigil because
early exegetes saw "seen upon earth, and conversed with men" as a
prophecy of the Incarnation).
Extended the Missa check to the other 6 already-absent books too --
genuinely zero citations anywhere. Ezra turned up one thin, ambiguous
Missa Introit citation that doesn't match its own cited verse; left
unseeded rather than force it.
65 of 72 bible-plan books now seeded -- this closes the per-book
responsory pool. npm test (2029 passed) and tsc --noEmit pass;
live-verified through getBiblePlanReadings. Canonical-key audit
re-run, clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
Composed rom from Rom 13:11-12 ("the night is past, the day is at
hand... let us cast off the works of darkness, and put on the armour
of light") -- the standing year-round ferial Lauds Capitulum, also
used at Advent I's own Capitulum. Genuine accented Vulgate/
Douay-Rheims text, never historically assembled into its own Matins
responsory, same approach as deut. User-confirmed before adding.
64 of 72 bible-plan books now seeded -- every book actually used in
the bible-plan has a real responsory, whether transcribed (62) or
composed from genuine already-liturgical text (deut, rom). The
remaining 8 have no citation anywhere in the source at all; there's
nothing further to check.
npm test (2029 passed) and tsc --noEmit pass; live-verified through
getBiblePlanReadings. Canonical-key audit re-run, clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
User found a lead reading a patristic homily (English/Sancti/01-02.txt)
that quotes Deut 32:11's eagle image. Deuteronomy has no historical
Matins responsory anywhere in the reference source, so unlike every
other entry in this pool, this one is composed rather than
transcribed: a real R./V. pairing built from the Canticle of Moses'
own genuine verses (Latin/Psalterium/Psalmorum/Psalm226.txt, sung at
Lauds), verified against data/scripture/deut-32.yml to confirm the
citation is standard verse 11 and not the breviary's own internal
chant-verse-numbering (32:15-16) for the same text. Documented plainly
in the data file's own header as vu's composition, not presented as
historically attested.
63 of 72 bible-plan books now seeded. npm test (2029 passed) and
tsc --noEmit pass; live-verified through getBiblePlanReadings.
Canonical-key audit re-run, clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
Advent's own reading plan (advent-1-sunday through advent-4-saturday,
28 rows for a full 4-week Advent) is always longer than real Advent
runs. Advent's last real day is always Dec 23 (Dec 24 is the Vigil of
Christmas's own temporal id), while Advent 1 Sunday lands anywhere
from Nov 27 to Dec 3 -- even the longest possible Advent is one row
short of the full plan, and the shortest is a whole week short. Every
year, at least the plan's last row never reaches its own natural date.
Added adventCarryoverReadings to propers/bible-plan.ts: whatever
doesn't land on its own natural date now carries forward one reading
per day starting Christmas Day, pooled alongside whatever
Christmastide's own calendar-dated rows already have -- never
replacing them. This is the one place in bible-plan.ts that needs
real calendar-year awareness (calendar/temporal.ts's adventStart).
4 new tests covering the shortest (2028) and a long (2027) Advent,
pooling behavior, and the Dec-24 boundary. npm test (2029 passed) and
tsc --noEmit pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
User pushback on Canticles being "confirmed absent" -- right instinct
to check the Commune files, which redirected productively: the same
Lectio-citation survey run against Sancti (individual saint/feast
files) rather than just Tempora found real, genuine content:
- cant: the Visitation (July 2) reads straight through the Song of
Songs, blending it with the Visitation narrative itself.
- lev: the Purification of the BVM's own Leviticus purification-law
reading is the feast's actual reason for being.
- num: the Exaltation of the Holy Cross's bronze-serpent/Cross
typology (Num 21:6-9).
Re-checked the other 9 already-"confirmed absent" books against
Sancti too -- still genuinely absent, no alternate abbreviation
missed.
62 of 72 bible-plan books now seeded -- the real final count. Only
Romans and 9 books with no citation anywhere (Tempora or Sancti)
remain. npm test (2025 passed) and tsc --noEmit pass; live-verified
through getBiblePlanReadings. Canonical-key audit re-run, clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
Asked to translate the 15 remaining "real Latin, no English" books.
None needed translation: the whole post-Epiphany reading season
(Galatians/Ephesians/Philippians/Colossians/1-2 Timothy/Titus/
Philemon/2 Thessalonians) turns out to have no distinct responsory
content of its own -- every feria file references 2 Corinthians' own
week (already bilingual) by weekday position. Same for 2 Peter/2-3
John/Jude, which reference Ascension Day's own responsories (act).
Only Romans genuinely has nothing: every citing file borrows an
unrelated feast's own proper responsory (Circumcision, Christmas Day,
a January saint), never anything Romans-specific. Left unseeded --
using one would repeat the Sacred Heart/Jeremiah mismatch this pool
already avoids elsewhere.
59 of 72 books now seeded -- every book with any usable Latin content
in the source at all. The remaining 13 (Romans plus 12 books with no
citation anywhere) are the real, final gap.
Ran the full canonical-key audit again; confirmed clean. npm test
(2025 passed) and tsc --noEmit pass; live-verified through
getBiblePlanReadings.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
getResponsoryForBook's joinResponsory concatenated the r/v text with a
bare newline and no "R."/"V." labels at all, unlike every other
responsory source in the app (octave-readings' own responsory field,
nocturn-readings' inline responsory, and the new per-Common-category
pool) which all include the full "R. ...\n* ...\nV. ...\nR. ..."
convention. User caught this looking at the rendered Judith entry.
Fixed by computing the repeat line from the existing "*" marker
already present in the pool's r text. npm test (2025 passed) and
tsc --noEmit pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
Confirmed Leviticus/Numbers/Deuteronomy genuinely absent from Tempora
(precise awk-based survey, not a loose grep). Added 1cor (Maundy
Thursday's own Institution-narrative Nocturn 3), 2cor (Epiphany II
Sunday), 1pet and 1joan (Paschaltide Sunday sets already partly used
for jac/jas).
Caught a repeat of the same canonical-key mistake from the previous
commit: the jas entry should have been keyed jac (BOOK_ALIASES maps
jas->jac). Fixed, and this time audited every single key in the file
programmatically against BOOK_ALIASES rather than just the keys
touched this pass -- confirmed clean.
45 of 72 books now seeded. npm test (2025 passed) and tsc --noEmit
pass; live-verified through getBiblePlanReadings.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
Surveyed Tempora precisely with an awk one-liner reading the line after
every [LectioN] tag (two lines deep for Gospel citations) rather than a
loose grep-for-book-prefix, which had already produced one false
positive this session.
Added act (Ascension Day's own Matins), marc (Easter Sunday's own),
heb (Good Friday's own Tenebrae), apoc (Easter III Sunday), jas
(Easter IV Sunday), and luc/matt/joan (Advent I/II/III Sundays, one
entry each). 41 of 72 bible-plan books now seeded.
Confirmed no English exists anywhere in the reference engine for
Galatians/Ephesians/Philippians/Colossians/Titus/Philemon or Romans --
real Latin exists, no bilingual source; left unseeded.
npm test (2025 passed) and tsc --noEmit pass; live-verified through
the real getBiblePlanReadings call chain (not a direct
getResponsoryForBook call, per the previous commit's lesson).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
bible-plan.ts normalizes a reading's book through canonicalBook()
(scripture/index.ts's BOOK_ALIASES map) before calling
getResponsoryForBook -- so the pool must be keyed by the canonical
form, not the bible-plan YAML's own raw book code. 12 of the 33 keys
seeded earlier today used the raw form and would have silently
resolved to undefined in the real app despite passing an initial
"live verification" that called getResponsoryForBook directly
(bypassing the normalization the real call site always applies).
Renamed: 1macc->1mach, 2macc->2mach, 1sam->1reg, 2sam->2reg,
1kgs->3reg, 2kgs->4reg, jdt->jdth, zeph->soph, obad->abd, jonah->jon,
hos->osee, mic->mich.
Re-verified through the actual getBiblePlanReadings call chain this
time (2026-06-04, post-pentecost-01/Thursday, "1sam 9-10" now
resolves a real responsory). npm test (2025 passed) and
tsc --noEmit pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
User caught jdt (Judith) listed as unseeded despite having real
responsory content directly visible in the reference source -- and
already flagged present in this same session's own citation dump,
never followed up on. Self-audit after that catch found job had also
been extracted earlier this session but never committed to the file.
Added jdt, esth, job, eccl, hab, joel, zeph, obad, jonah, mal, hos, mic,
nah, and lam (Maundy Thursday's own Tenebrae responsories). 33 of 72
bible-plan books now seeded, up from 19.
npm test (2025 passed) and tsc --noEmit pass; live-verified via
getResponsoryForBook resolving real text for every new key.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
"~66" was an eyeballed guess from a sort|uniq -c list, never actually
counted -- and coincidentally echoes the 66-book Protestant canon count,
a bad number to leave uncorrected in a Catholic office project's own
docs. The real count (grep -c distinct `book:` values across
data/hours/bible-plan/*.yml) is 72.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
The per-book pool extraction script only matched a bare [ResponsoryN]
tag, missing the reference engine's underscore-suffixed [ResponsoryN_]
template convention that holds the real text (a bare tag often just
@:-references it, alongside a Cistercian-rubric variant). This wrongly
made 1sam/2sam/1kgs/2kgs/2macc look untranslated in English.
Fixed the script and hand-followed @Tempora/X:ResponsoryN cross-file
references to add 1sam, 2sam, 1kgs, 2kgs, 2macc, zach, amos, and agg --
19 of ~66 bible-plan books now seeded (up from 11).
npm test (2025 passed) and tsc --noEmit pass; live-verified via
getResponsoryForBook resolving real text for every new key at every
pool index.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
Added exod, prov, sir, sap, tob, ezek, dan, 1macc (11 of ~66 total now
seeded), each sourced from a genuine, non-overridden reference-engine
Tempora file with real bilingual Responsory text. sir/sap and dan reuse
prov's/ezek's own entries respectively, confirmed by the reference
engine's own week files @-referencing that same pool -- real evidence
this app's loose book-level responsory match is historically authentic,
not invented.
Skipped 1sam (macro-only responsory text, not worth resolving for one
book) and 2sam/1kgs/2kgs/2macc/zach/amos/agg (real Latin but no
reference-engine English translation at all).
npm test (2025 passed) and tsc --noEmit pass; live-verified via
getResponsoryForBook resolving real text for every new key.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
The per-book responsory pool (Nocturn 1 scripture readings) only had `isa`
seeded; the much bigger, previously untracked gap was that 272 of 355
nocturn-readings/*.yml files (Nocturn 2/3 patristic readings) had no
responsory at all. Added a sibling per-Common-category pool, sourced from
the reference engine's static Commune text files, covering all 19 of vu's
real `common:` category ids (several confirmed aliases of the same
underlying file). Wired into matins.ts's reading assembly as a fallback
when a reading has no proper responsory of its own. Also expanded the
per-book pool with `gen` and `jer`.
Live-verified end-to-end (St. Francis de Sales, Ss. Cornelius/Cyprian, Ss.
Euphemia/Lucy/Geminianus). npm test (2025 passed) and tsc --noEmit pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak