205 Commits

Author SHA1 Message Date
will d39359e5ac Carry over unreached Advent bible-plan readings into Christmastide
Deploy / deploy (push) Successful in 1m55s
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
2026-09-04 19:17:24 -04:00
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 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 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 290bbac1b5 Route bible-plan incipit/responsory lookup through the book-alias table
bible-plan.ts's *.yml import uses English-style book abbreviations
("jdt", "1kgs", "luke", ...) for ~30 books where that diverges from
this store's canonical form ("jdth", "3reg", "luc", ...).
scripture/index.ts's own BOOK_ALIASES already normalized this for
verse-text lookup, but the incipit (bible-book-incipits.ts) and
responsory (matins-responsories.ts) lookups used the raw abbreviation
directly, silently missing on any canonically-keyed book and falling
back to a bare "Reading" heading. The 3 Gospel aliases self-healed via
a separate citation-regex fallback that only exists for Gospels; every
other aliased book (Judith, Kings, Samuel, Esdras, Osee, Jonas, Josue,
Micheas, Abdias, Judges, the Johannine epistles, James, Jude, Philemon,
Titus, Zacharias, Sophonias) had no such fallback. Exports
canonicalBook from scripture/index.ts and routes both lookups through
it -- one shared normalization instead of two independently-aliased
ones that can drift again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 07:12:55 -04:00
will 88e8a5b404 Name Ember days in the day label, demoted or winning outright
calendar/day-label.ts never surfaced an Ember day's own identity
anywhere: collectCommemorations only matched a temporal commemoration
against resolveTemporalId(day.date), never an Ember-relabeled id, and
the winning-outright fallback used the generic ordinal weekday label
with no id awareness at all. Adds a standalone emberDayLabel lookup,
deliberately kept out of temporal-feasts.ts since that table doubles
as isFerialOrVigil's bareness check and would have silently turned
off Ember days' own ferial Preces.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-04 07:12:32 -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 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 d8bb32bf45 Label unattributed hagiographic Matins readings by saint, not "Reading"
Deploy / deploy (push) Successful in 1m54s
A saint's vita reading (Nocturn 2, no patristic `source` attribution)
fell through to the UI's generic "Reading" heading. Add
fallbackHagiographicLabel, which looks up the contributing id's own
saint/temporal-feast record and produces "On St. Pius X, Pope and
Confessor" style labels instead — same plain-string convention as an
authored `source`.

Updates two matins.test.ts assertions that used label shape (string
vs object) as a proxy for "not a bible-plan reading" — no longer
reliable now that vita readings also carry a string label, so they
key off citation presence instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 16:16:46 -04:00
will 998c549e51 Replace generic "Reading"/"Gospel" headings with real incipits
Deploy / deploy (push) Successful in 1m50s
Bible-plan readings now carry a generated bilingual incipit label
(bible-book-incipits.ts) instead of falling through to the UI's generic
"Reading" heading. Gospel pericopes (whether from the user's own plan
or nocturn-readings.ts's proper content) get the same treatment via a
new label field on the 'gospel' ResolvedPart, recovering the book from
the reading's own citation when no raw book code is available.

Updates 3 matins.test.ts assertions that used "no label" as a stand-in
for "this is a bible-plan reading" — no longer true now that these
readings carry a real label, so they now key off the label's shape
(string = patristic attribution, object = generated incipit) instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 14:02:58 -04:00
will 64a5634557 Collapse consecutive bible-plan chapters into a citation range
Deploy / deploy (push) Successful in 1m51s
Multi-chapter readings (e.g. Job 34-37, authored as one YAML entry per
chapter) were rendering as "Job 34; Job 35; Job 36; Job 37" instead of
the compact "Job 34-37". Verse-qualified and non-consecutive citations
are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AGjUyhUZJaSjiniEmnLdak
2026-09-03 11:46:34 -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 493c532469 Drop verse-number prefixes from scripture-sourced Matins readings
Deploy / deploy (push) Successful in 1m47s
resolvePassages() prepended each verse's number ("1 Et factum est...")
when joining scripture verses into continuous reading text — visible
today in Job's Matins reading. Not wanted; join the verse text alone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Je2mXNHoXmi1DS3xEL67rH
2026-09-03 05:43:12 -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 f4d4eb3738 Lower Matins 3-nocturn threshold from Duplex to Semiduplex
Deploy / deploy (push) Successful in 1m31s
Semiduplex and Duplex should share the same 3-nocturn/3-psalms-each
shape (distinct from Sunday/Duplex-majus+'s 6/6/3-plus-canticles
scheme) — the previous Duplex floor meant a Semiduplex winner like
St. Stephen of Hungary wrongly fell all the way through to the
1-nocturn ferial branch.

New threshold is a separate check from isDoubleOrHigher, which drives
the unrelated antiphon-doubling rule elsewhere and stays floored at
Duplex — the two thresholds only coincided by accident before this
change. No new content authoring was needed: ferialPsalmodyThreeNocturns
already chunks the ferial 9-psalm pool into 3/3/3 as the fallback for
a plain-Duplex winner with no override authored, and Semiduplex
winners now route into that same already-working branch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X26BkFT3ARbtUGXuBmzUmD
2026-09-02 07:07:12 -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 3f9b748e4a Fix Matins test part-index offsets for new opening versicle
Deploy / deploy (push) Successful in 1m28s
Inserting the new Domine-labia versicle shifted every downstream
ordo.parts index/destructure by one. Pure index-shift fixups, no
behavioral assertions changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015yHHNsbzD8jLkkmVuJpAcC
2026-09-02 05:54:15 -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 fc4ac33903 Fix privileged-feria-major: nothing is ever commemorated, any rank
Deploy / deploy (push) Successful in 1m32s
The Easter octave cascade built last commit reused the existing
"duplex-majus+ still gets a bare commemoration" branch unchanged,
trusting its own citation (St. Mark within the Easter Octave). That
citation was a misreading. Live-verified: the Annunciation (Duplex I.
classis) transfers with zero commemoration on Holy Thursday itself, and
Chair of St. Peter at Antioch does the same on Ash Wednesday - the
exception was wrong everywhere this category is used, not just Holy
Week. privileged-feria-major now matches privileged-sunday exactly:
unconditional transfer, no exceptions, any rank.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 14:08:15 -04:00
will d6c8e8b7a8 Build the Easter octave transfer cascade
Deploy / deploy (push) Successful in 1m32s
Closes the tabled "Easter's own octave" mechanism gap. resolveDay only
ever checked yesterday/tomorrow for an inbound transfer - a single hop -
so anything impeded in Holy Week just vanished rather than reappearing
after the Octave. Live-verified the real behavior first (2033 proof
year): a candidate skips the whole privileged span and keeps walking
forward, FIFO by native date, until it lands; a transferred-in candidate
never gets the "still gets a nod" commemoration a native occurrence of
the same rank would along the way (confirmed with the Annunciation, zero
commemoration anywhere in the span). Also fixed Low Sunday itself, which
needed the same privileged-sunday treatment as Easter Day.

Built resolveForwardTransferLanding: a bounded queue simulation that
reuses applyIncomingTransfer unchanged per hop - its existing
privileged-feria-major no-op was already the right single-hop refusal,
it just needed a real cascade around it instead of a dead end.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 12:25:21 -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 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 8919497d24 Update tests for ferial Matins Sunday-leak fix
Deploy / deploy (push) Successful in 1m28s
The rest-of-year temporal nocturn-readings sweep was testing the Monday
after each named Sunday, relying on the now-removed leak to prove content
reachability for dates with no separately-authored ferial content -
repointed to the actual Sunday date. Updated the 2026-08-24 suppression
test's ferial case to assert the leak no longer happens, and added a
regression test pinning the original 2026-09-01 bug report.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 07:06:20 -04:00
will 54d1d6190e Update tests for T/S/N Preces ferial split
Deploy / deploy (push) Successful in 1m27s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 06:39:14 -04:00
will 45c1f4e958 Update tests for Sept 1 saints removal
Deploy / deploy (push) Successful in 1m28s
september-sanctoral.test.ts: Sept 1 now resolves to a plain temporal
day with no commemorations; the Raymond Nonnatus transfer-collision
case now wins uncontested since the native Sept 1 saints are gone.

vespers.test.ts: the semiduplex-keeps-its-own-Vespers-against-a-
lower-ranked-tomorrow regression test used Raymond Nonnatus vs. St.
Giles as its example pair; re-pointed to St. Agatha (semiduplex) vs.
St. Dorothea (simplex), a different adjacent pair that exercises the
same concurrentia rule.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XMSokiTD2Qc5vPP2YQu3Q
2026-09-01 06:24:20 -04:00
will e0156c1512 Fix Vespers concurrentia to compare today's rank against tomorrow's directly
Deploy / deploy (push) Successful in 1m27s
keepsOwnSecondVespers used a fixed duplex-2-classis floor on today's rank
alone, so a lower-ranked but still-real sanctoral winner (e.g. Simplex)
tomorrow could still steal First Vespers from a higher-ranked-but-below-the-
floor winner today (semiduplex St. Raymond Nonnatus losing to simplex St.
Giles on 2026-08-31). The real "De Concurrentia Officii" rubric compares the
two days' ranks directly, with ties going to tomorrow — replace the floor
with that comparison when both sides have a real sanctoral winner, keeping
the floor only as a fallback against a plain Sunday.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QEe9oTbn1UjQVAYcCoW1a
2026-08-31 22:01:33 -04:00
will a339068f81 Show a transferred saint's status in the day label
Deploy / deploy (push) Successful in 1m32s
getDayLabel now surfaces the transfer signal added in the previous
commit: a transferred-in winner gets "(Rank, transferred)" instead of
just "(Rank)"; a transferred-in commemoration gets "(transferred)"
appended to its bare name; and the date a saint transferred away from
gets a trailing "St. X (transferred away)" note so a reader isn't left
wondering why an expected saint is missing that day. Deliberately worded
differently on the two sides (plain "transferred" reads as "arrived via
transfer" next to a rank parenthetical; "transferred away" spells out the
direction on the origin date, where there's no rank alongside it to
anchor that reading) and deliberately omits a landing date on the away
note, per direct instruction, since a real landing can chain further than
the single adjacent day resolveDay actually checks (an unmodeled case,
e.g. a transfer running into Holy Week).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013g7AsSvMD9oazR17f3BxLz
2026-08-31 08:53:12 -04:00
will db9c844caf Track a transferred saint's origin date on DayWinner and Commemoration
Adds transferredFrom to both DayWinner's sanctoral variant and
Commemoration's sanctoral variant, set in calendar/index.ts's
applyIncomingTransfer whenever a transferred-in candidate actually lands
(wins outright) or ends up merely commemorated (lost a collision, or fell
below the landing day's own threshold) — previously this signal was
discarded after resolveDay used it once to decide the winner, so nothing
downstream could tell a transferred feast apart from a native one.

Also adds transferredAway to LiturgicalDay, set from a date's own native
occurrence when its candidate couldn't be kept there at all, so a UI can
note "this office moved elsewhere" without asserting a specific landing
date (which a later, unmodeled multi-hop chain — e.g. into Holy Week —
could get wrong).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013g7AsSvMD9oazR17f3BxLz
2026-08-31 08:53:02 -04:00
will cb60039ab2 Fix Sept sanctoral test for Raymond's new semiduplex rank
Deploy / deploy (push) Successful in 1m28s
Raymond's rank deflation (a1ed3d2) changes cascading behavior in years
where Aug 31 is a Sunday: he now loses to the Sunday outright (needs
duplex+ to win, per Divino Afflatu's ordinary-sunday threshold) and
transfers forward onto Sept 1, winning the collision there over St.
Giles. Move the original clean-year Giles test to 2026 and add a new
test documenting the 2025 transfer/collision case explicitly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013g7AsSvMD9oazR17f3BxLz
2026-08-31 08:23:08 -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
will a6261f044a Add nameLa mechanism for bilingual header, proof set of 11 feasts + St. Lawrence
Deploy / deploy (push) Successful in 1m32s
Threads an optional nameLa field through SanctoralIdentity/SaintRecord/
TemporalFeastRecord/ActiveOctave so day-label.ts can render real Latin
proper names instead of always falling back to English. Authors the
proof set: all 11 named temporal feasts plus St. Lawrence (chosen to
exercise the octave-headline and octave-commemoration code paths too).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwsZQMjALCvy7u9tFDWmuQ
2026-08-31 06:30:48 -04:00
will 2df1fd0d3b Add St. Rose of Lima (Aug 30), rank deflated for late canonization
Deploy / deploy (push) Successful in 1m37s
She was previously excluded on a mistaken "post-1617, out of scope"
reading that conflated vu's hour-structure track (Monastic 1617) with
its calendar/saints track (Tridentine 1906 + Divino Afflatu 1954,
which has included her since her 1671 canonization). Her source rank
of Duplex is deliberately deflated to semiduplex, correcting for the
rank creep that made "new canonization" and "Duplex" a near-automatic
pairing from the Baroque period on. She wins Aug 30 outright over Ss.
Felix and Adauctus, who keep their existing commemoration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwsZQMjALCvy7u9tFDWmuQ
2026-08-31 05:41:16 -04:00
will efb1717e27 Add test coverage and TODO.md log for the full temporal-cycle sweep
Deploy / deploy (push) Successful in 1m31s
Extends tests/hours/matins.test.ts's proof-date table to cover all 28
newly-authored temporal ids end-to-end, including Easter and Pentecost
Sunday. Documents the full sweep in TODO.md, including the
easter-sunday/pentecost-sunday misdiagnosis and correction so the
"1 nocturn in the source" vs. "no content" distinction doesn't get
re-litigated later.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
2026-08-30 23:21:03 -04:00
will 04a8686551 Finish the last 5 vigils: weekday-keyed commemoration antiphons
Deploy / deploy (push) Successful in 1m32s
Corrected an earlier "no source exists" claim by live-querying real
commemorated instances of the Vigils of St. Lawrence and the Assumption
across six different weekdays. Their source files' own [Rule] block
("Versum Feria") turns out to be a real, sourced mechanism, not an
absence: a mere commemoration doesn't reuse the vigil's own antiphon at
all -- it borrows the plain ferial day's antiphon/versicle instead, and
that antiphon quotes the Benedictus canticle in weekday sequence (same
shape vespers-magnificat-antiphons.yml already uses for the Magnificat).
The versicle is a single fixed text. Sunday has no entry: a Vigil
transfers off an ordinary Sunday rather than ever reaching a
commemoration there, confirmed live as well as already true in this
app's own precedence rules.

sanctoralCommemorationPart now takes weekday and resolves this
dynamically for common-of-a-vigil saints, rather than needing a static
per-saint file. All 218 saints with an authored collect now have a real
commemoration antiphon.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
2026-08-30 18:12:12 -04:00
will b5f16ceb23 Finish the sanctoral commemoration bundle sweep (213/218 saints)
Deploy / deploy (push) Successful in 1m29s
Follow-up to the earlier bulk pass. Sourced the remaining category
templates: BVM feasts (13, reused the already-verified BVM suffrage
versicle plus each feast's own antiphon), angels (4, versicle inferred
from a saint file's own "structural category" note), Confessor-Doctor/
-Pope (7, resolved to C4a/C5a/C4b -- each inheriting its base category's
Ant2/Versum2 unchanged, no new content needed), several confessors and
apostles-plural (2, reusing already-sourced category versicles), and 5
fully-proper feasts (All Saints x2, Finding of the Holy Cross, Most
Precious Blood, Transfiguration, Our Lady of Ransom) given their own
real Ant2/Versum2 straight from their Sancti files.

213 of ~218 real saints now covered. Only the 5 Vigils remain open --
no dedicated Commune template exists for that category in the reference
engine, and FeastClass 'vigil' rarely reaches the commemoration code
path anyway.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
2026-08-30 17:10:34 -04:00
will 2c3f63ef97 Bulk-author sanctoral commemoration antiphon+versicle bundles
Deploy / deploy (push) Successful in 1m28s
Found that 217 of 220 saints with an authored collect had no
${propers}-commemoration.yml bundle, so sanctoralCommemorationPart was
silently falling back to a bare collect with no antiphon whenever that
saint was merely commemorated rather than winning outright (user-reported
for St. Raymond Nonnatus and the Decollation of St. John the Baptist).

Bulk-fixed: reused each saint's own proper antiphon where authored, else
the standard de-Communi [Ant 2]/[Versum 2] for that saint's own Common
category. Confirmed via three already live-verified commemorations
(Ss. Felix and Adauctus, St. Clare, St. Sabina) that [Ant 2]/[Versum 2]
are the real tags used for a mere commemoration, not [Ant 1]/[Nocturn 2
Versum] as first assumed -- corrected St. Raymond Nonnatus's file
accordingly. 182 of ~218 real saints now covered; entries not
independently live-verified are marked draft. Remaining ~36 (BVM feasts,
angels, confessor-doctors/popes, vigils) tracked in TODO.md.

New tests/propers/commemoration-sweep.test.ts (182 cases) asserts every
bundle has a real antiphon+versicle+collect, never bare/missing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
2026-08-30 16:42:20 -04:00
will 6334b3eaaa Give Ss. Felix and Adauctus a real commemoration antiphon
Deploy / deploy (push) Successful in 1m29s
Their commemoration was falling back to a bare collect (only
ss-felix-and-adauctus-collect.yml existed, no combined Ant+V/R bundle),
so it rendered with no antiphon at Lauds when they're commemorated on a
Sunday (today, 2026-08-30). Live-verified against that exact date.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
2026-08-30 08:59:22 -04:00
will a18ad7f57c Resolve Advent IV landing on Dec 24 as the Vigil, with Advent IV commemorated
Deploy / deploy (push) Successful in 1m25s
When Advent 4's own Sunday lands on Dec 24, the Vigil of Christmas's
identity (rank, collect, Lauds antiphons, Matins Gospel nocturn) now
governs the day, matching the reference engine's own rule that a
privileged Sunday never displaces it. Unlike the reference engine's own
"no commemoratio" for this exact collision, Advent 4 is deliberately
still commemorated — the Sundays of Advent have real standing of their
own. Matins' three-nocturn Sunday psalmody is untouched either way,
since it's driven by weekday, not by which id wins.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ME8QNPdEmHSbSx1r6VmDRG
2026-08-30 08:55:00 -04:00