Commit Graph

294 Commits

Author SHA1 Message Date
will aba89dc250 Model Trinity Sunday as a real feast, not just a cosmetic label
Trinity Sunday wasn't modeled at all: getDayLabel had a purely
cosmetic "Trinity Sunday" label overlay for the Sunday after
Pentecost, but resolveTemporalId just fell back to post-pentecost-01
(ordinary-sunday category), so any Duplex+ saint assigned that date
(e.g. the Queenship of the BVM, fixed May 31) won outright, real
Trinity Sunday content never appearing anywhere.

Added a real temporal-feasts/trinity-sunday.yml record (Easter+56,
Duplex II. classis, live-verified). Per direct instruction,
unconditional: true (same shape as christ-the-king.yml) -- a
principal Sunday shouldn't lose a same-rank fixed-date collision, and
the one real collision case (Queenship of the BVM) isn't
independently verifiable against Monastic 1617 at all (that calendar
doesn't carry the Queenship feast -- May 31 there is St. Petronilla
instead).

Authored the full office and registered trinity-sunday in
ALWAYS_OVERRIDE_TEMPORAL_IDS -- the same generic mechanism already
built for the Pentecost-cluster fix, no new code needed: collect,
Benedictus/Magnificat antiphons, Matins hymn ("Summæ Deus cleméntiæ"),
Lauds/Vespers chapter (shared, Rom 11:33) and hymn (shared, "O lux
beáta Trínitas", already the pre-Urban VIII text), each hour's own
distinct responsory/versicle -- all live-verified 2026-05-31.

Fixed 3 pre-existing tests written around the old cosmetic-label
behavior, two of which had never-verified guesses baked in as if
correct: day-label.test.ts's "names the anchor day itself" test and
its "outranks an active octave" test (was asserting "Duplex I Class",
a guess -- the real live-verified rank is Duplex II);
transfer.test.ts's St. Felix I test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 14:50:31 -04:00
will 2a611cc17b Mark Lent's own Lauds capitulum/responsory/versicle verified
Not actually homeless, contrary to an earlier session's claim: these
3 files already had the real content (Isa 58:1 / "Ipse liberávit me"
/ "Ángelis suis"), just marked draft since never live-verified.
Live-verified against both a Lenten Ember Saturday (2026-02-28) and a
plain Lenten Wednesday (2026-03-04) -- identical, confirming this is
genuinely season-wide content, not weekday-varying.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 14:50:08 -04:00
will 3d230b34f2 Recombine the remaining 5 Ember-day nocturn-readings files
Same fix as ember-september-friday.yml (already done): each file's
Lectio1-3 turned out to be one continuous, unbroken homily (Bede,
Gregory, or Ambrose's Commentary on Luke for the two Advent cases,
cross-referenced from the Annunciation's own Common and confirmed
contiguous by reading the source file directly), split only to fill
the fixed 3-lesson slot count. Recombined ember-september-wednesday/
-saturday and ember-advent-wednesday/-friday/-saturday into single
readings, keeping each one's first lesson's own responsory.

All 6 Ember days now recombined -- no remaining split-for-no-reason
readings in this family. Updated ember-days.test.ts's lesson-count
table accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 14:49:59 -04:00
will 30b3971190 Give Corpus Christi and Sacred Heart their own hymnody, all octave
Same gap and same generic mechanism fix as Ascension/Pentecost --
just needed the ids added to ALWAYS_OVERRIDE_TEMPORAL_IDS plus real
content. Both feasts have 3 genuinely different hymns, one per hour:
Corpus Christi's own are widely known outside this context too
("Sacris solémniis" at Matins, "Verbum supérnum pródiens" at Lauds
whose last 2 stanzas are "O Salutaris Hostia", "Pange, lingua,
gloriósi Córporis mystérium" at Vespers whose last 2 stanzas are
"Tantum Ergo").

Sacred Heart needed one source-track correction: Monastic Tridentinum
1617 doesn't observe this feast on this date at all (shows St.
Barnabas instead) -- used Divino Afflatu 1954 instead, this project's
own stated rubric track. Also live-verified a genuine structural
difference: Sacred Heart's own Lauds/Vespers have no responsory at
all in the source (straight chapter to hymn) -- not an authoring gap.
Fixed lauds.ts's and vespers.ts's own resolveOffice to omit the
responsory part entirely when its status is missing in both
languages, instead of always rendering an empty section.

Authored matins-hymn-{corpus-christi,sacred-heart}.yml,
lauds-{capitulum,responsory,hymn,versicle}-corpus-christi.yml,
vespers-{responsory,hymn,versicle}-corpus-christi.yml,
lauds-{capitulum,hymn,versicle}-sacred-heart.yml, and
vespers-{hymn,versicle}-sacred-heart.yml -- all live-verified,
2026-06-04 and 2026-06-12.

Fixed 2 pre-existing tests whose own dates now land inside these
newly-modeled octaves and were asserting the old fall-through
behavior as if correct: lauds.test.ts's FERIAL_MONDAY (moved off
2026-06-08) and vespers.test.ts's St. Margaret of Scotland test
(2026-06-09) -- its own title already anticipated this fix, just had
the wrong expected values until now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 12:54:55 -04:00
will 98aa411a1b Author Ascension's own collect
A separate, pre-existing gap: getDayCollect already looked up
ascension-collect via resolveOfficeWinner (the same mechanism this
session's earlier fix already covers), but the content file itself
never existed. Live-verified against Divinum Officium (Monastic
Tridentinum 1617), 2026-05-14.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 12:54:35 -04:00
will 5d500c4e1f Give Pentecost its own hymnody at Matins/Lauds/Vespers, all octave
Same gap as Ascension (pentecost-sunday is a temporal-feast id, not a
saint record) -- the mechanism fix from that commit is generic, so
this only needed the id added to ALWAYS_OVERRIDE_TEMPORAL_IDS plus
real content.

Unlike Ascension, Pentecost has 3 genuinely different hymns, one per
hour: "Jam Christus astra ascénderat" (Matins), "Beáta nobis gáudia"
(Lauds), "Veni Creátor Spíritus" (Vespers), each with its own real,
distinct chapter/responsory/versicle at Lauds vs. Vespers.

Authored matins-hymn-pentecost-sunday.yml, lauds-{capitulum,
responsory,hymn,versicle}-pentecost-sunday.yml, and
vespers-{responsory,hymn,versicle}-pentecost-sunday.yml (Vespers
reuses Lauds' chapter via the existing cross-hour fallback) -- all
live-verified against Divinum Officium (Monastic Tridentinum 1617),
2026-05-24. Confirmed the whole octave end-to-end via resolveOrdo,
including a real winning saint within the window (St. Augustine of
Canterbury) keeping his own hymn at Lauds/Vespers unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 12:07:48 -04:00
will 44dd4bb47a Give Ascension its own hymnody at Matins/Lauds/Vespers, all octave
`ascension` is a temporal-feast id, not a saint record, so
resolveOfficeWinner's octave-synthesis (which already handles
saint-based octaves like Assumption's/St. Lawrence's) never
recognized it -- Ascension Day itself and its whole octave silently
rendered the generic Paschaltide hymn at every hour.

Fixed the mechanism: added `ascension` to ALWAYS_OVERRIDE_TEMPORAL_IDS
(covers the feast day itself), and taught resolveOfficeWinner to also
synthesize a {kind:'temporal'} winner from an active octave with no
saint record but a real temporal-feast record (covers ordinary-feria
octave days; a real winning saint within the octave still correctly
keeps priority).

A third gap surfaced testing this: octaveGoverningPrivilegedDay's
correct-by-design "a privileged Sunday never accepts an octave
override" rule is live-verified wrong specifically for "Dominica
infra Octavam Ascensionis" (keeps the octave's own hymn/responsory,
just with its own distinct proper chapter). Rather than loosen that
shared gate for every octave, gave resolveLaudsHymn/resolveVespersHymn
a narrow, hymn-only intercept guarded to saint-less octaves, checked
before the season/weekday default.

Authored matins-hymn-ascension.yml, lauds-{capitulum,responsory,hymn,
versicle}-ascension.yml, and vespers-{responsory,hymn,versicle}-
ascension.yml (Vespers reuses Lauds' chapter via the existing
cross-hour fallback) -- all live-verified against Divinum Officium
(Monastic Tridentinum 1617), 2026-05-14.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 11:08:11 -04:00
will e7e19c530a Author Sunday's own Matins hymn and every season's (Advent-Paschaltide)
The "genuinely more complex, not-yet-understood two-hymn mechanism"
flagged for Sunday turned out simple: Day0 Hymnus ("Nocte surgéntes")
is just Sunday's plain per-annum hymn, and Day0 Hymnus1 ("Primo
diérum ómnium") is Septuagesima-tide's own separate seasonal hymn --
the same shape Advent/Lent/Passiontide/Paschaltide each already have.
Live-verified these 4 don't vary by weekday within their season (a
Lenten Sunday and a Lenten feria render identically). None of the 6
were authored at all before this -- every Sunday and every season day
not otherwise overridden by a winning saint/octave silently fell
through to Monday's own ferial placeholder text.

Authored matins-hymn-{sunday,septuagesima,advent,lent,passiontide,
paschaltide}.yml, all live-verified, self-contained with their own
real closing doxology baked in. Septuagesima is checked directly by
day.season in resolveMatinsHymn itself, deliberately not folded into
the shared seasonalOfficeSuffix (Lauds/Vespers have no matching
content yet -- resolveOfficeBundle there is all-or-nothing per feast,
so adding it would silently blank their chapter/hymn instead of
falling through to their current weekday default).

Known, flagged simplification: the generic Paschaltide hymn wrongly
applies during the Ascension octave, whose own real hymn isn't
authored anywhere yet -- a same-shape gap Lauds already has, not a
new regression. Updated 2 FERIAL_DATE (a Tuesday in Advent) hymn
assertions that had been asserting Tuesday's own ferial text --
Advent's own seasonal hymn correctly outranks the weekday cycle now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 10:38:05 -04:00
will 0b6a0ad1cc Complete Marian Saturday: proper Matins/Lauds hymns, ferial antiphons
Design (direct instruction): Marian Saturday is its own rank tier,
between simplex and vigil in vu's FeastClass scale -- beats a plain
Simplex saint (commemorated in return), loses cleanly with zero trace
to anything Vigil-or-higher. Deliberately not the full historical
Officium Sabbatorum B.M.V. ("no little office"): ferial psalmody is
kept everywhere, only the antiphons swap to Marian text; Matins and
Lauds each get a real proper Marian hymn; the Marian collect applies
whenever the day wins.

The calendar-side mechanism (calendar/index.ts's applyMarianSaturday)
and a collect/Benedictus antiphon already existed from an earlier
session -- authored what was still missing: matins-hymn-marian-
saturday.yml (Matins had nothing at all) and lauds-{capitulum,
responsory,hymn,versicle}-marian-saturday.yml.

Also found and fixed 3 real bugs from that earlier, unverified pass:
Lauds' own hymn ("O gloriósa Dómina") was sitting under the plain
ferial lauds-hymn-saturday id instead of its own marian-saturday id;
that id's capitulum/responsory/versicle siblings were live-verified
from a different, privileged Lenten Ember Saturday, not a genuine
per-annum ferial Saturday -- corrected to the real content ("Auróra
jam spargit polum" / Rom 13:12-13 / "Sana ánimam meam" / "Repléti
sumus mane misericórdia tua", live-verified against a clean September
Ember Saturday); and the Lauds psalmody override used the real
historical proper psalm set (92/99/62) instead of the ferial one,
rolled back per direct instruction to plain ferial psalms (50, 142,
the split Canticle of Moses) with only the antiphons swapped.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 09:32:25 -04:00
will b8cb636446 Give the Matins ferial hymn its own text per weekday, not one for all
matins-hymn-ferial.yml turned out to already be Monday's own hymn
("Somno reféctis ártubus"), mislabeled as a single fixed year-round
text and used unconditionally for every weekday -- the source
(Psalterium/Special/Matutinum Special.txt) genuinely varies this hymn
Monday through Saturday, the classic "week of hymns". Caught first on
Friday ("Tu Trinitátis Únitas" expected, Monday's text shown), then
again on a real Ember Saturday ("Summæ Deus cleméntiæ" expected).

Authored matins-hymn-ferial-{tuesday,wednesday,thursday,friday,
saturday}.yml (Monastic 1617 text, live-verified against the CGI
instance directly, including Friday's own real M-track word-swaps) and
wired resolveMatinsHymn's final fallback tier to pick by day.weekday.
Sunday is left on the existing placeholder, documented as a real,
more complex not-yet-understood gap (a two-hymn source split).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 09:32:05 -04:00
will 4b6d55d56c Recombine Ember September Friday's split Matins homily into one reading
Lectio1-3 in ember-september-friday.yml were one continuous, unbroken
Gregory homily on Luke 7:36-50, split only to fill the fixed 3-lesson
Nocturn slot count -- the "source doesn't genuinely split" case this
store's own established default (post-pentecost-15.yml) already
recombines elsewhere. User caught this live on /2026-09-18/matins
showing 3 identically-labeled lessons in a row. Keeps Lectio1's own
responsory per the "first one, when several collapse" convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 09:31:51 -04:00
will 03d39dc911 Author Ember days' own Benedictus/Magnificat antiphons
Live-verified (Monastic Tridentinum 1617) that an Ember day's Lauds
psalmody stays on the plain ferial default throughout -- only the
Benedictus antiphon (and, Wednesday/Friday only, the Magnificat
antiphon) is genuinely proper to the day. Adds the 6 Benedictus +
4 Magnificat antiphon files (Ember Saturday's Second Vespers is
always ceded to the following Sunday on both quarters, so no
Magnificat content exists to author there).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 07:12:01 -04:00
will 750bea4cff Add full Gospel pericopes to post-Pentecost Sunday Matins readings
Closes the gap this whole sweep started from: Nocturn 3 on
post-pentecost-13/14 showed St. Augustine's homily with no Gospel
citation or text above it. Fixes all remaining post-pentecost-NN ids
(01-14, 16-24; -15 already had this from the original mechanism proof)
the same way as the rest of the sweep, plus Trinity Sunday's second
Nocturn 3 pair — the "Commemoration of the First Sunday after
Pentecost," whose Gospel (Luke 6:36-42) has no live date to source from
since Trinity always occupies that slot, so it's sourced from the
reference engine's preserved pre-displacement Mass propers file
instead. Also fixes a stray-space formatting glitch in
post-pentecost-19's existing homily text, found while sourcing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 17:07:10 -04:00
will 1dc8e3700a Add full Gospel pericopes to Eastertide Sunday Matins readings
Same gap and fix as the Advent/Christmas and post-Epiphany sweeps, for
easter-octave, easter-3 through -6, and sunday-after-ascension. Also
fixes stray leading "v." verse-marker artifacts left over in three of
the existing English homily texts (easter-4/5/6), found while sourcing
the paired Gospel text alongside them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 17:06:46 -04:00
will 01ffb25057 Add full Gospel pericopes to post-Epiphany through Palm Sunday Matins readings
Same gap as the Advent/Christmas sweep: Nocturn 3's patristic homily
appeared with no Gospel pericope before it. Authors the full text for
post-epiphany-1 through -6, septuagesima/sexagesima/quinquagesima,
lent-1 through -4, passion-sunday, and palm-sunday.

Palm Sunday needed a different source than the rest: its Missale
[Evangelium] tag is the Passion narrative (Matt 26-27) proclaimed at
Mass, not the entry-into-Jerusalem pericope (Matt 21:1-9) its own
Nocturn 3 homily is actually about — that shorter Gospel is instead
read at the Blessing of Palms, sourced from there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 17:06:41 -04:00
will b7b5a63756 Add full Gospel pericopes to Advent/Christmas Sunday Matins readings
Nocturn 3 previously dropped the bare "Et réliqua" Gospel incipit and
kept only the patristic homily, so the Gospel citation and text never
appeared. Authors the full pericope before the homily for advent-1
through advent-4 and christmas-octave-sunday, sourced from the
reference engine's Missale Gospel files. Authoring Advent 4's Gospel
surfaces a genuine second Matins Gospel on the rare Dec-24-as-Advent-4
collision (2023/2028), so the affected test now expects both readings
instead of one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 17:06:33 -04:00
will 46b34493e2 Wire seasonal hymn-doxology into every plain-default Lauds hymn
Lauds' Monastic source never carries the "*" substitution marker anywhere
(audited), so this is purely the same deliberate broadening as the Vespers
commit: every plain-default hymn (Sunday, Mon-Sat, Advent, Lent,
Passiontide, Paschaltide) now routes its closing doxology through
getHymnDoxologyId/appendDoxology instead of a fixed ending, split into
matching per-annum companion files that reproduce the original text
whenever no season/feast override applies.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 15:00:17 -04:00
will 0736c36494 Wire seasonal hymn-doxology into every plain-default Vespers hymn
Sunday's hymn ("Lucis Creator") is the one case whose Monastic source text
carries a real "*" seasonal-substitution marker (live-checked); every other
key (Mon-Sat, Advent, Lent, Passiontide, Paschaltide) is wired the same way
anyway as a deliberate broadening beyond the source, at the user's request
("the doxology is a neat way to stay tuned in to the season... we're doing a
remix, not a copy"). Each hymn's own natural ending is split into a matching
per-annum companion file, so a season/feast with no override reproduces the
original text exactly; only Nat/Epi/Pasch/Asc/Pent/Corp/Heart and the two
feast/date overrides from the previous commit actually change anything.

Real visible effect: hymns shown during Christmastide/Epiphanytide/Corpus
Christi/Sacred Heart (none of which get a distinct seasonal hymn, so these
were always the plain weekday defaults) now pick up the right doxology
instead of a generic ending; Ascensiontide and the Pentecost octave now
diverge from the rest of Paschaltide's doxology mid-season.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 15:00:06 -04:00
will aeda043577 Wire seasonal hymn-doxology into the Matins ferial hymn
The plain ferial hymn's Monastic source (Day1-6 Hymnus,
Psalterium/Special/Matutinum Special.txt) carries a real "*" seasonal-
substitution marker, live-checked against the reference engine. Splits the
hymn's own natural doxology ending into a new per-annum companion file and
swaps it via getHymnDoxologyId/appendDoxology, same pattern already used by
Prime and Compline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 14:59:49 -04:00
will 44feb8c6b1 Widen seasonal hymn-doxology to cover Marian Saturday and the Assumption octave
getHymnDoxologyId now takes the whole LiturgicalDay (needed for a date-window
check) and checks a feast override for a temporal winner's id too, not just
sanctoral — matching Divinum Officium's own Common-of-the-BVM `Doxology=Nat`
rule, which is why Marian Saturdays get the Nativity doxology regardless of
season. Also ports the source's Aug 16-22 (Assumption octave) hardcoded
Nativity-doxology window, confirmed live not excluded for the Monastic/
Tridentine 1617 track.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 14:59:32 -04:00
will d660f9e531 Give post-pentecost-15's homily reading its own Duo Séraphim responsory
Deploy / deploy (push) Successful in 1m46s
Every other post-Pentecost week's own file already attaches "Duo
Séraphim" (the closing responsory before Te Deum) to the hour's *last*
reading, overriding the usual "first one, when several collapse"
convention for exactly this responsory. post-pentecost-15 was the only
week not following that pattern -- its last (homily) reading kept
Lectio 10's own responsory instead. Swapped it in, matching the other
23 weeks; removes the now-resolved "needs an hour-level responsory
slot" note from TODO.md, which was chasing a problem that didn't
actually exist.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 07:42:02 -04:00
will 3794903c68 Alias common-of-a-confessor-pope to common-of-a-confessor-bishop
Deploy / deploy (push) Successful in 1m51s
While auditing the Lauds/Vespers Common-category psalmody note for
staleness, found 3 saints (St. Pius X, St. Leo II, St. Pius V) use
common: common-of-a-confessor-pope, which had no alias in either
category file -- unlike common-of-a-confessor-doctor, which already
does. Live-verified (votive=C4 vs C4b, both Vespers and Lauds,
Monastic Tridentinum 1617): psalms/antiphons are byte-identical to
Confessor-Bishop's, only the Magnificat antiphon and collect differ
(both already handled per-saint, not through this table).

Note: this doesn't change any currently-visible content -- all 3
saints are ranked duplex/semiduplex, below the duplex-majus+ threshold
this psalmody-override tier is gated at, so they correctly fall to the
plain ferial default regardless. It closes a real data-completeness
gap for whenever a duplex-majus+ Confessor Pope is added.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 07:26:19 -04:00
will aa287ab806 Recover isolated single-verse scripture gaps that were transient, not real
Deploy / deploy (push) Successful in 1m57s
33 chapters from the first-pass "Unbound Bible" import each had one lone
missing English verse (matt-12:43's in-file "Transfer interrupted!"
download-corruption artifact among them). Rather than assume these were
genuine source gaps, checked every one against drbo.org's per-verse
text: 33 of 34 turned out to be real, present verses the old scrape had
simply dropped, now filled in.

The remaining 10 are confirmed genuine: drbo.org's own Douay-Rheims
numbering for these chapters stops one verse short of the Vulgate's own
count too (checked each chapter's actual max verse number there) -- a
real versification difference, not a scrape artifact, so these stay
honestly missing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 06:52:40 -04:00
will b29ce0551f Re-source the corrupted/missing scripture chapters from drbo.org
Deploy / deploy (push) Successful in 1m53s
The "Unbound Bible" source used for the previous pass had real defects
in 12 chapters (Douay-Rheims verses shifted/merged under the wrong
number, e.g. "Isaias 25:1" actually holding 25:11's text) and was
missing Daniel 4-14/Esther 11-16 outright.

Found a better source: drbo.org's combined "DR + LV" page per chapter
keeps each verse's Latin and English in the same HTML block, making
the earlier misalignment structurally impossible. Fetched and parsed
all 28 real chapters from it (bar-2; isa-5/25; joan-15; rom-9/11;
sir-10/19/23/41/51; dan-4..14; esth-11..16), spot-checked several
against known-correct text, and confirmed sir-52 isn't a real chapter
at all (Sirach only has 51 -- the old source's "52" was bogus).

Store now at 1185 chapter files with zero remaining gaps against every
book/chapter citation the app actually uses. Repoints
scripture.test.ts's "unauthored chapter" case from dan-14 (now
authored) to gen-51 (Genesis only has 50 chapters).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 06:41:17 -04:00
will 4bc5fdd77f Complete the bulk Vulgate/Douay-Rheims scripture import from the real source
Deploy / deploy (push) Successful in 1m49s
Found 137 chapters missing from src/data/scripture/ despite the recent
bulk import, scattered oddly across ~30 otherwise-covered books. Located
the original "Unbound Bible" source archives (douay_rheims.zip/latinv.zip)
the earlier import must have used but never preserved in-repo, and
re-parsed directly from them.

118 new chapters authored, plus the 3 hand-authored short books (Jude,
Obadiah, Philemon) replaced with source-derived text — small wording
differences from the hand-typed drafts confirm going back to source was
worth it. Store now at 1157 chapter files.

Deliberately left unauthored rather than risk bad content:
- Daniel 4-14 and Esther 11-16: this digitization's Latin side only has
  Daniel 1-3 and Esther 1-10 at all (English has the rest).
- 12 chapters where the Douay-Rheims side has a corrupted, misnumbered
  block (e.g. isa-25's tagged verse 1 actually carries verse 11's text)
  rather than simply missing content -- importing under the source's own
  wrong verse numbers would silently attach mismatched text to real
  citations, worse than leaving them missing.

Widened bulk-import.test.ts's invariant to tolerate up to 2 genuinely
isolated missing-English verses per chapter (extends the pre-existing
isa-33/sir-36 pointing-split-half-verse allowance to also cover true
source gaps, e.g. an in-file "Transfer interrupted!" download-corruption
artifact at matt-12:43), while still failing loudly on anything
resembling the corrupted-block pattern above.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 06:13:56 -04:00
will cd53805c83 Author Jude, Obadiah, and Philemon — books the bulk scripture import missed
Deploy / deploy (push) Successful in 1m45s
Three single-chapter books referenced by bible-plan.ts's readings had no
corresponding file in src/data/scripture/ at all, unlike everything else
covered by the Vulgate/Douay-Rheims bulk import — apparently dropped by
whatever produced the source. Authored by hand (Clementine Vulgate /
Douay-Rheims 1899 American Edition) and wired via new BOOK_ALIASES
entries (jude->jud, obad->abd, philem->phlm) so bible-plan's existing
citations keep their familiar English display form.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 05:51:20 -04:00
will 63f48d26d2 Fix Matins bible-plan readings stuck on stale "translation pending"
resolveReading() in bible-plan.ts preferred each YAML row's hardcoded
status: { la: missing, en: missing } over computing status from the
actually-resolved text. That field was accurate before the Vulgate/
Douay-Rheims bulk import but was never cleared once real text landed,
so every Matins bible-plan reading kept showing as untranslated
regardless. Strip the stale field from all 368 files so status falls
through to the real compute-from-resolved-text path.

Also alias book abbreviations in scripture/index.ts's lookup: the
bulk-imported store uses Vulgate-numbering codes (sap, jac, joan,
1reg..4reg, 1par/2par, 1esdr/2esdr, ...) matching octave-readings.ts's
existing convention, while bible-plan.ts's TSV import used common
English abbreviations (kgs, sam, chr, john, jas, luke, mark, ...) for
the ~30 books where the two conventions diverge. Alias at the lookup
layer so citations keep their familiar English display form.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 05:43:07 -04:00
will 5ebb856de7 Bulk-import the Vulgate/Douay-Rheims scripture text
Deploy / deploy (push) Successful in 1m54s
Adds ~1017 chapter YAML files under src/data/scripture/ carrying verified
bilingual (Latin Vulgate / Douay-Rheims English) verse text, closing out
the bulk scripture import TODO.md has tracked as pending bulk-content
work. Daniel 14 (the Greek deuterocanonical addition) has no counterpart
in the Latin source and stays unauthored.

Raises the PWA precache size cap (8 -> 24 MiB) to fit the larger bundle,
repoints scripture.test.ts's "unauthored chapter" case from Genesis 1
(now authored) to Daniel 14, and adds bulk-import.test.ts asserting every
imported chapter has verified, gap-free, ordered verse text in both
languages -- tolerating the pre-existing isa-33/sir-36 pointing-split
half-verses, whose English intentionally isn't split to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 05:31:11 -04:00
will 90665429ae Author Easter Octave Wednesday-Saturday's shared Matins antiphons
Deploy / deploy (push) Successful in 1m28s
All 4 weekdays share the exact same 2 antiphons verbatim ("Jesum qui
crucifíxus est quǽritis, allelúja..." / "Veníte et vidéte locum ubi
pósitus erat Dóminus, allelúja, allelúja."), live-verified against
Pofficium.pl (Monastic Tridentinum 1617, prayMatutinum) across
2026-04-08/09/10/11 — despite each day drawing on a different Gospel
reading in the nocturn-readings pool, the antiphon layer doesn't vary
by day.

Layered onto vu's own already-fixed per-weekday ferial psalm numbers
rather than the reference engine's own differently-sized (Rule of
Benedict summer-contracted) psalm set for these days, consistent with
this project's deliberate rejection of that contraction.

This closes "Easter's own octave" fully: calendar precedence
(2026-09-01), Sunday/Monday/Tuesday's shared proper psalmody, and now
Wednesday-Saturday's antiphons (both 2026-09-02).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X26BkFT3ARbtUGXuBmzUmD
2026-09-02 07:51:34 -04:00
will 57acbeefe9 Author Easter Sunday/Monday/Tuesday's shared proper Matins
Deploy / deploy (push) Successful in 1m29s
Easter Sunday, Monday, and Tuesday of the Octave share winner {kind:
temporal, id: easter-sunday}, and now share one live-verified proper
Matins psalmody: Nocturn 1 (Ps 1,2,8,15,23,27 under one antiphon),
Nocturn 2 (Ps 29,63,65,75,87,107 under one antiphon), Nocturn 3 (the
same 3 canticles already authored for the ordinary-Paschaltide
seasonal override, under its own antiphon) — sourced from
Pofficium.pl (Monastic Tridentinum 1617, prayMatutinum) against
2026-04-05/06/07. All 3 nocturn-closing versicles are byte-identical
to the ones already authored for the Paschaltide override, confirming
those are shared season-wide rather than coincidentally reused. The
12 patristic lessons were already authored in an earlier sweep
(nocturn-readings/easter-sunday.yml) and needed no new work.

Restricted to just these 3 days via the new weekdays field: the
Octave's other 4 weekdays (Wed-Sat) share the same winner id but have
their own different, not-yet-authored antiphons, tracked as a
separate open item in TODO.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X26BkFT3ARbtUGXuBmzUmD
2026-09-02 07:42:39 -04:00
will 9da5a74301 Remove spurious mid-nocturn versicle from ferial Matins
The 1-nocturn ferial branch was rendering a V./R. versicle stuck
mid-list, as if marking a nocturn boundary that doesn't exist in a
single continuous nocturn. Live-verified against the reference engine
(Pofficium.pl, Monastic Tridentinum 1617) for Wednesday and Thursday:
the real office runs straight from the last psalm to the Capitulum,
with no versicle anywhere in the psalmody. The embedded mid-list V./R.
line in the source Psalmi matutinum.txt is inert there and was never
actually emitted by the engine — matins-ferial-antiphons.yml's
versicle field was a documented-but-unverified assumption, not real
content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X26BkFT3ARbtUGXuBmzUmD
2026-09-02 07:06:21 -04:00
will 9d39d162ec Strip stray Vulgate verse-number markers from psalm text
Deploy / deploy (push) Successful in 1m28s
Several psalm files carried leftover inline markers like (6a), (17a),
(32) from the source text (e.g. Ps 67:2-19). vu doesn't number verses
inline anywhere else, so these were artifacts, not content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015yHHNsbzD8jLkkmVuJpAcC
2026-09-02 06:31:08 -04:00
will b54fcb30e6 Reclassify Passion week ferias from ordinary-feria to privileged-feria
Deploy / deploy (push) Successful in 1m35s
Passion week's ferias (Mon-Sat before Palm Sunday) fell through to
passiontide's bare ordinary-feria default, letting any real feast win
outright regardless of rank. Live-verified against the reference engine:
swept every date that can land in this window across a century of Easter
dates and found zero sub-Duplex winners -- every real winner is Duplex+.
This was letting vu's own low-ranked calendar saints (e.g. Ss. Tiburtius/
Valerian/Maximus, St. Anicetus) trivially win there and wrongly restore
the responsory's closing Gloria on what should stay a penitential day.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015yHHNsbzD8jLkkmVuJpAcC
2026-09-02 06:21:02 -04:00
will db23523a5d Add Domine labia mea aperies (x3) to Matins opening
The Monastic-rite versicle "V. Dómine, lábia mea apéries. R. Et os
meum annuntiábit laudem tuam" was entirely absent from Matins' opening
block — only the shared "Deus in adjutórium" versicle was modeled.
Authored per the reference engine's "iij" rubric (recited three times,
after Deus in adjutórium, before Psalm 3), with the English rendered
as imperative ("O Lord, open Thou my lips") rather than future
indicative.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015yHHNsbzD8jLkkmVuJpAcC
2026-09-02 05:54:10 -04:00
will 5b3dc2e9d5 Redesign the Easter-octave backlog: floor-gated, one per day
Deploy / deploy (push) Successful in 1m28s
Replaced the multi-day cascading queue with the actual intended design:
only candidates at or above duplex-majus are worth carrying out of the
Palm-Sunday-through-Low-Sunday span at all - below that, a candidate
simply lapses for the year. Of those that clear the floor, the Nth day
after Low Sunday celebrates the Nth one (native-date order), winning
outright with no rank fight, demoting whatever's natively there to a
commemoration - one per day, positional, not a free-day search.

Caught a real bug while re-verifying: the ordinary single-hop transfer
check was independently leaking Low Sunday's own signal into the next
day, letting a below-floor candidate bypass the new gate. Fixed by
excluding the whole span from that path.

Inventoried the only duplex-majus+ candidates that can ever fall in the
reachable window (St. Benedict, St. Gabriel the Archangel, the
Annunciation, St. Mark, Ss. Philip & James), then bumped St. Patrick's
own rank to duplex-majus by direct instruction, adding him as the 6th.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 15:06:55 -04:00
will 4adbb71ddf Full precedence sweep of temporal-categories.yml, two more real bugs
Deploy / deploy (push) Successful in 1m27s
Following the Ascensiontide fix, swept every remaining unverified Sunday/
feria precedence tier against the live reference engine:

- commemorations.ts's privileged-sunday rule was itself wrong: a
  duplex-majus+ candidate was given a bare commemoration instead of
  transferring, never actually verified. Live-checked the Immaculate
  Conception (transfers off Advent II) and the Annunciation (transfers
  off Palm/Easter Sunday) - confirmed correct by direct instruction.
  privileged-sunday now transfers every rank unconditionally.

- eastertide's own Sunday tier was backwards (privileged-sunday instead
  of ordinary-sunday) for the ordinary Sundays after Easter - live-
  verified twice (Finding of the Holy Cross, St. Mark both win outright).
  Easter Day itself still needs the stronger tier, now special-cased
  directly since Sundays never consult the offset table.

Six existing tests updated to reflect real, live-verified behavior - each
had the old wrong "commemorated in place" assumption baked into its
expected value. Remaining unverified entries (Vigil of Pentecost/
Christmas, Corpus Christi/Sacred Heart) documented as such rather than
silently assumed correct.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 11:45:04 -04:00
will 6b66999908 Fix Ascensiontide Sunday precedence and give it its own Matins proper
Deploy / deploy (push) Successful in 1m27s
The Sunday within the Octave of Ascension was letting a Duplex saint win
outright (ascensiontide's Sunday was miscategorized ordinary-sunday
instead of privileged-sunday, the only "great octave" season not already
so classed). Live-verified the reference engine keeps the Sunday primary
and transfers the saint instead. Fixed the category, then authored the
Sunday's own wholly proper Matins (a different psalm scheme entirely, not
a seasonal overlay) via a new per-temporalId override layer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 09:58:40 -04:00
will 05f82a3556 Give ordinary Paschaltide Sundays their own Matins Nocturn I-III content
Deploy / deploy (push) Successful in 1m26s
Same seasonal-overlay shape as Advent, live-verified against the reference
engine across 5 Paschaltide Sundays. Generalized sundayNocturnFor to a
season-keyed lookup covering both Advent and Paschaltide.

Confirmed two related non-gaps while investigating: Christmastide/post-
Epiphany Sundays have no seasonal block in the source, and a Duplex+ saint
winning outright on a Sunday deliberately still uses the fixed Sunday
psalmody per this app's own documented design (readings still surface the
saint via the separate pool) — neither needs a fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 09:31:22 -04:00
will c3e540f6c2 Give Advent Sundays their own Matins Nocturn I-III content
Deploy / deploy (push) Successful in 1m27s
Nocturns I-II had no seasonal override mechanism at all, and Nocturn III's
own Septuagesima-Palm override didn't cover Advent — live-verified against
the reference engine that Advent has its own seasonal antiphons/versicles
across all three nocturns, identical on all 4 Advent Sundays.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 09:07:46 -04:00
will 3d221c2a45 Give Sunday Matins Nocturn III its own antiphon Septuagesima-Palm Sunday
It was hardcoded to "Allelúja, allelúja, allelúja" year-round. Each of
the 9 Sundays from Septuagesima through Palm Sunday has its own
Gospel-tied antiphon instead, live-verified against Monastic Tridentinum
1617; Lent 1-4 also swap in their own canticles, and Lent 1-4 plus
Passion/Palm Sunday swap in their own versicle. New
matins-sunday-nocturn3-overrides.yml, keyed by temporalId and merged
over the base nocturn3 group by hours/matins.ts's new
sundayNocturn3For — only the real-Sunday branch uses it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 08:17:14 -04:00
will 36e2cc60cd Add Jeremiah 14, Lamentations 5, and Ezekiel 36 scripture chapters
Lent 1-4's Sunday Matins Nocturn III canticles, transcribed from a live
Divinum Officium query (Monastic Tridentinum 1617). First content under
the `lam` book code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 08:17:04 -04:00
will afff77f75a Split ferial Matins nocturn antiphons to one per psalm
Every cross-psalm pair previously shared one antiphon under just the
first psalm, which read inconsistently once psalter-distribution.yml's
reslice left some pairs intact and split others. Each pair is now two
single-psalm groups: the psalm whose own words the shared antiphon
actually quoted keeps it, and its former partner gets a real antiphon
borrowed from elsewhere in the reference corpus where one exists, else
one composed fresh from its own opening verse.
2026-09-01 07:30:35 -04:00
will b050e523ec Split Terce/Sext/None Preces into always-shown Kyrie/Pater + ferial-only versicles
Kyrie eleison and Pater Noster now render every day regardless of rank
(minor-hour-kyrie-pater); the further Preces V/R versicle pairs are
ferial-only, dropped on Sunday and any sanctoral winner.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 06:39:10 -04:00
will 64271befee Drop St. Giles and Ss. Twelve Brothers from Sept 1
User decision to carry no saints on Sept 1. Data files for both
saints (and their propers/commemoration bundles) are left in place,
restorable by re-adding the sanctoral-calendar.yml list entry, same
pattern used when St. Hermes was dropped from 8/28.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 06:24:14 -04:00
will ccc406003c Author 10 sanctoral Common-category Magnificat antiphons
getMagnificatAntiphon's Common-category fallback
(magnificat-antiphon-${benedictusCommon}) had never been authored for
any of the 11 real Common categories saints fall back to -- only the
temporal-cycle side of this gap had been closed previously. Sourced
each from its Commune file's own [Ant 3] (Second Vespers), live-verified
against Ss. Placid and Companions, St. Blaise, and St. John Gualbert's
real evenings.

common-of-a-vigil (the 11th category) is handled separately, in code --
see the next commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QEe9oTbn1UjQVAYcCoW1a
2026-08-31 22:27:17 -04:00
will 8702955a5f Fix wrong Ant-tag sourced for two Common-category Benedictus antiphons
benedictus-antiphon-common-of-a-confessor.yml and -the-bvm.yml were each
reading their Commune source file's [Ant 1] (the Common's First Vespers
antiphon), not [Ant 2] (the real Lauds antiphon) -- discovered while
sourcing the sibling Magnificat antiphon set. Live-verified wrong via St.
Alexius's real Lauds query (renders "Euge, serve bone", not "Similabo
eum").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QEe9oTbn1UjQVAYcCoW1a
2026-08-31 22:27:08 -04:00
will 06fc8ef0ec Add missing commemoration bundle for St. Rose of Lima
Deploy / deploy (push) Successful in 1m29s
Her Aug 31 commemoration (e.g. under St. Raymond Nonnatus) was falling
back to a bare collect with no Ant./V./R. since she was authored after
the earlier commemoration-bundle sweep and never got her own.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QC6jHsj75xcsTkapqJR6fD
2026-08-31 09:31:58 -04:00
will 1923433a29 Normalize versicle notation to plain V./R. across propers
Deploy / deploy (push) Successful in 1m31s
Unicode ℣/℟ (U+2123/U+211F) were mixed unpredictably with plain V./R.
across ~550 proper YAML files, sometimes within the same file. Screen
readers can't announce the unicode glyphs. Replace all instances with
plain text.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QC6jHsj75xcsTkapqJR6fD
2026-08-31 09:23:30 -04:00
will a1ed3d2f9c Deflate St. Raymond Nonnatus's rank to semiduplex
Canonized 1657, well past the ~1600 late-canonization threshold; per
project policy his source Duplex rank gets deflated one tier, same
treatment already applied to St. Rose of Lima.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013g7AsSvMD9oazR17f3BxLz
2026-08-31 08:23:02 -04:00
will 514300821a Bulk-author nameLa for all 299 remaining saints, close bilingual header backlog
Deploy / deploy (push) Successful in 1m31s
Authors a real Latin nameLa for every saint in src/data/calendar/saints/
except the deliberate example-confessor placeholder (standard
ecclesiastical Latin forms, a lighter sourcing bar than this app's usual
reference-engine verification -- flagged for future spot-check). Fixes a
real mechanism bug found in the process: calendar/index.ts's sanctoral
collision-resolution branch was dropping nameLa for any saint that won
after beating another same-day candidate. Updates ~180 pre-existing test
fixtures across the calendar suite for the new field.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwsZQMjALCvy7u9tFDWmuQ
2026-08-31 06:44:10 -04:00