Commit Graph

33 Commits

Author SHA1 Message Date
will 130b0f983d Extend the source-file fallback to Frances of Rome/Bibiana, fix a real Agatha/Lucy gap
Deploy / deploy (push) Successful in 56s
Follow-up to the previous commit: applies the same "read the fileref
directly, no live query required" fix to St. Frances of Rome and St.
Bibiana, whose own filerefs simply hadn't been derived yet (they predate
the Kalendaria-table work this session built). Both resolve to
common-of-a-virgin, same as several of the 15 fixed previously.

Also swept every saint on the calendar (not just this batch's own
lineage) for any other still-missing collect or Benedictus antiphon,
which turned up a real, older gap: St. Agatha and St. Lucy's own file
comments already documented "resolves honestly missing... despite
propers being set" -- written before collectCommon existed as a
mechanism at all. Agatha's own [Oratio] is a name-substituted reference
confirmed identical to the already-existing collect-c6.yml template, so
collectCommon was simply wired in. Lucy's own [Oratio] references a
different Common formula unedited, with her own [Name] section supplying
the whole descriptive phrase a plain name field would otherwise need the
template for -- written as her own st-lucy-collect.yml rather than a new
single-use template, since she's the only current user of that unedited
form.

St. Clare showed up in the same sweep but is a false positive: her real
content lives in a separate commemoration-bundle file, used via a
different code path the sweep's synthetic-winner methodology doesn't
exercise -- already fully authored, no gap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 10:56:10 -04:00
will 6bb4c6a80f Author day collects for all 94 propers:null saints via Kalendaria tables
Deploy / deploy (push) Successful in 59s
Blind per-date source-file reading (Sancti/SanctiM MM-DD.txt) turned out
unreliable for collect authorship: those files are era-merged, carrying
centuries of accumulated saints behind rubric-conditional gating, so a
naive read often returned a saint canonized long after 1617 instead of
the Monastic-Tridentine-era one actually on this calendar (St. Didacus
instead of All Saints of the Benedictine Order, St. Rose of Lima instead
of Ss. Felix and Adauctus, etc).

Fixed by pulling from web/www/Tabulae/Kalendaria/'s own era-specific
calendar tables (1570.txt Tridentine base + M1617.txt's Monastic diffs)
instead, cross-validated against the pre-1955/Divino Afflatu chain
(1888->1906->1939->1954) as a corroborating signal. Cross-referencing all
205 existing saint records against this table confirmed 204/205 were
already correctly placed -- the earlier live-query verification work was
sound, only blind file-reading was flawed -- so no sanctoral-calendar.yml
corrections were needed, just the collect content itself.

Two collect shapes came out of the 94: 34 proper collects (own YAML file,
Latin verified against source, English translated+draft where the source
lacked it) and 60 resolved via a new Common-collect templating mechanism
-- SaintRecord.collectCommon/collectName plus substituteName() in
resolve-common.ts, filling a template's {N} placeholders positionally
from the saint's own declined name, across 21 new common/collect-c*.yml
templates named after the source's own C-numbering.

St. Michael's Sep 29 propers resolved via its whole-file @Sancti/05-08
inheritance (Apparition of St. Michael, May 8). St. Martha's plural-
template default was overridden to the singular collect-c6a since she's
one person, not a pair.

Also fixes a latent bug this surfaced: getDayCollect looked up
`${collectCommon}-collect`, but collect-c*.yml files are id'd as
`collect-c2` etc with no such suffix -- caught by a smoke test where
every one of the 93 non-Michael saints resolved as missing.

4 pre-existing tests updated: they asserted specific saints (St.
Benedict, St. Romanus Abbot, St. Anthony Abbot) had no authored collect,
which is no longer true; resolve-common.test.ts's generic "missing" case
now uses a synthetic day/winner since no real unauthored saint remains
as an example.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 08:19:28 -04:00
will ea29e5ee45 Add Dec 26-30's own Sunday rule -- a deliberate remix, not a live-verified fix
Deploy / deploy (push) Successful in 54s
Per direct instruction, and explicitly framed as this project's own
departure from Monastic 1617 itself: within Dec 26-30 inclusive (exactly
one real Sunday falls somewhere in that window every year), whichever
date is the actual Sunday always wins as Nat1-0 outright, with no rank
check at all -- even Stephen/John/Holy Innocents (Duplex II. classis)
get fully displaced, not just commemorated. The displaced saint isn't
commemorated in place either; he reappears in full as Dec 30's own
winner instead (the block's one date with no fixed saint of its own).
Rank never matters for this rule -- confirmed with Becket (Semiduplex)
transferring the same way as the Duplex-II-classis saints.

This deliberately diverges both from what Monastic 1617 itself does on
Dec 26-29 (live-verified two commits ago: the saint wins there, Sunday
merely commemorated) and from the general privileged-sunday transfer
rule elsewhere (which only transfers ranks below duplex-majus and
commemorates everything else in place) -- this window transfers every
rank and commemorates nothing in place, a genuinely new, third
behavior specific to this 5-day block.

Implemented as calendar/index.ts's applyChristmasOctaveSunday, a
narrowly-scoped layer in the same spirit as applyMarianSaturday/
applyChristTheKing, rather than by changing the shared
decideOccurrence/transfer machinery every other Sunday relies on. Dec 31
and everything outside Dec 26-30 is untouched -- St. Silvester still
beats the Sunday there via the plain, unchanged ordinary-sunday rule.

Verified against all five possible Sunday positions within the window
(Dec 26/27/28/29/30) plus the "nothing displaces anything" control case,
each with its own dedicated test in the new
tests/calendar/christmas-octave-sunday.test.ts. Updates two existing
tests whose assertions were correct under the old rule and are now
superseded specifically within this window (Stephen/Innocents no longer
win their own Sunday-collision dates there) while confirming the
underlying ordinary-sunday rule is still live and real outside it (Dec
31/St. Silvester).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 10:59:34 -04:00
will 397f31f4fc Implement octave-vs-octave precedence, and fix a real day-label bug it surfaced
Deploy / deploy (push) Successful in 52s
When more than one octave is active on a day with no temporal standing of
its own (St. Lawrence's and the Assumption's genuinely overlap every Aug
16-17), which one governs the day's content/label is now decided by rank
comparison instead of "whichever started first" (an accident of
insertion order). Per direct instruction:

- Highest effective rank wins outright; every other active octave still
  gets commemorated, same as a single octave already outranking a weak
  rival saint.
- A rank tie goes to whichever octave started more recently -- day 1 of
  a new octave needs to be fully present, the whole point of it
  starting. No real tied-rank case exists yet to verify this
  empirically, unlike everything else here -- documented in TODO.md as
  a stated decision, not a live finding.

New OctaveConfig.closingDayRank (default duplex): an octave's own final
day ("in Octava") is elevated above its ordinary in-between rank --
live-verified as a real, general pattern (both St. Lawrence's Aug 17 and
the Assumption's Aug 22 show as Duplex, above their otherwise-Semiduplex
ordinary days), not a one-off. This elevation is *why* Lawrence's octave
beats the Assumption's on their one real overlap day despite the
Assumption being the far higher-ranked feast overall. Feeds both the
existing rival-saint threshold and the new octave-vs-octave comparison.

calendar/octaves.ts gains resolveActiveOctave (+ pickWinningOctave, the
comparison itself factored out for direct unit testing against synthetic
data, since no real tied-rank overlap exists to test against yet).
hours/resolve-common.ts's resolveOfficeWinner and calendar/day-label.ts
both now call it instead of each keeping their own "activeOctavesFor(...)
[0]" logic.

That consolidation surfaced a real, independent bug: getDayLabel never
checked temporalCategory at all before choosing an octave name, unlike
resolveOfficeWinner -- found while testing the real Aug 16 overlap (a
Sunday that year, where the temporal Sunday has standing and should win
outright). Live-verified counterexample: the Christmas Octave's own
stack (Dec 30) was wrongly labeled "3rd Day within the Octave of The Holy
Innocents" instead of the correct plain temporal label -- the real title
never names any of the four stacked octaves there. Fixed by sharing the
exact same ordinary-feria gate resolveOfficeWinner already had, so the
two can no longer disagree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 09:38:06 -04:00
will 5f32a3751c Model St. Clare and surface active octaves in the day label
Deploy / deploy (push) Successful in 52s
Today (Aug 12, within St. Lawrence's octave) was resolving as a plain
ferial day: St. Clare wasn't modeled in the calendar at all, and even
once an octave commemoration exists, getDayLabel only ever looked for a
sanctoral commemoration, never an octave one, so the label fell all the
way through to the generic ordinal week label.

Adds St. Clare (Simplex under Monastic 1617, correctly losing to
Lawrence's octave and only commemorated -- live-verified against three
clean years). Extends getDayLabel to show the active octave itself as
the day's primary identity when nothing else has won outright (e.g.
"3rd Day within the Octave of St. Lawrence, Martyr -- St. Clare,
Virgin"), matching what the live reference engine actually titles these
days, rather than falling back to an anonymous ordinal week label.

Also fixes a regression this surfaced: Trinity Sunday is technically
also day 8 of Pentecost's own octave, and the naive octave-first check
was shadowing its own anchor-day name ("8th Day within the Octave of
Pentecost" instead of "Trinity Sunday"). A season's own named anchor day
now always outranks an active octave label.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 06:39:48 -04:00
will ff81a6fe52 Fix Christmas Octave Sunday's occurrence precedence (was backwards)
Deploy / deploy (push) Successful in 51s
christmastide's Sunday was coded privileged-sunday (Advent's own tier),
which live-checking against the reference engine shows is wrong: on
every one of the three real collision dates (St. Stephen/John/Holy
Innocents, all Duplex-II-classis, falling on the Sunday within the
Octave) the saint wins outright and the Sunday is merely commemorated --
the reverse of what privileged-sunday would produce (Sunday stays
primary, saint just gets a nod). St. Silvester (plain Duplex, Dec 31)
confirms the same live. Reclassified to ordinary-sunday, which matches
all four checked cases: Duplex+ wins outright (Stephen/John/Innocents/
Silvester), Semiduplex still transfers off the Sunday rather than
winning (St. Thomas Becket, unaffected by the fix either way), and a day
with no saint at all resolves to the Sunday cleanly.

Found while pulling christmas-octave-sunday's own Benedictus antiphon
from the reference engine's dedicated Tempora/Nat1-0 proper and noticing
this app's own occurrence resolution didn't match what the live engine
showed for the Sunday's real collision dates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 06:30:46 -04:00
will 2247e8c27f calendar: exempt Vigils from Our Lady's Saturday's demotion
Deploy / deploy (push) Successful in 49s
Refined per direct correction: Our Lady's Saturday is really only a
Simplex-strength standing, not a privileged-feria-minor-shaped one --
a Vigil keeps forcing its own primacy on a Saturday the same way it
already does any other day (see calendar/commemorations.ts's own
transferDirectionOf special-casing for Vigils elsewhere). Only a
Simplex saint alone now loses to it; a Vigil, along with anything
Semiduplex-or-higher, wins outright and Marian Saturday doesn't apply.

Un-does the two test-date moves this same regression prompted last
time (Vigil of St. Lawrence, Vigil of St. John Baptist) -- both dates'
original years work again now that the fix is right.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 14:20:13 -04:00
will 0404642614 calendar: add Christ the King, last Sunday of October
Deploy / deploy (push) Successful in 51s
A 1925 addition, so nowhere in the Monastic Tridentinum 1617 base this
project otherwise targets -- content sourced from "Monastic Divino
1930" instead, the Monastic-lineage version of the era that actually
carries it. Always wins outright (Duplex I. classis, confirmed live),
commemorating whichever Sunday after Pentecost it displaces -- same
additive-layering shape as applyOctaves/applyMarianSaturday, run last
so nested commemorations (e.g. a Simplex saint already commemorated
under that Sunday) survive underneath it.

Extended the Lauds psalmody-override mechanism (both the psalm groups
and, newly, the chapter/responsory/hymn/versicle bundle) to recognize
named temporal winners as unconditionally override-eligible, not just
duplex-majus+ sanctoral ones -- generalizing what had been a Marian-
Saturday-only special case. Suffrages needed their own explicit check
too: isDoubleOrHigher only ever looks at a sanctoral rank, and a named
temporal winner has no FeastClass to check at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 14:13:22 -04:00
will 747a078580 calendar: model Our Lady's Saturday as a real occurrence outcome
Deploy / deploy (push) Successful in 49s
On a free Saturday (nothing privileged already claims it, no active
octave), the day's own identity is now "Our Lady's Saturday" rather
than an anonymous ordinary-feria -- mirrors privileged-feria-minor
exactly, per direct instruction: Semiduplex-or-higher still wins
outright (Marian Saturday doesn't apply at all); below that (Simplex,
and Vigil, both under semiduplex on the FeastClass scale) loses and is
commemorated instead. Layered additively after decideOccurrence, same
shape as applyOctaves -- never touches decideOccurrence's own rules.

Needed a real winner identity (not just the plain temporal feria id)
so day-label/antiphon/collect sourcing can recognize it -- added a
temporal-feasts record purely for that, and taught getDayLabel to
check it for any named temporal winner (a small, free improvement for
Christmas/Pentecost's own labels too, previously unhandled).

hours: build the duplex-majus+ Lauds psalmody override (per-feast)

lauds-psalmody no longer unconditionally uses the plain weekday
default: a duplex-majus-or-higher sanctoral winner, or Our Lady's
Saturday (unconditional, no rank threshold -- it isn't competing with
the weekday default the way a saint is), now substitutes its own
proper psalm groups/antiphons/canticle. Per-feast, not per-Common, per
direct instruction, even though most duplex-majus+ saints across the
year don't have one authored yet and fall back to the plain weekday
default until they do.

Content for the worked example (St. Lawrence's own day) surfaced a
real bug while sourcing it: st-lawrence-antiphon.yml had been read
from the Roman/secular rite's own [Ant 1], not Monastic 1617's actual
Benedictus antiphon for that day -- corrected from a fresh live query.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 14:02:55 -04:00
will eec76a1e4e calendar: enable the four remaining real octaves
Deploy / deploy (push) Successful in 44s
Assumption (Aug 15-22), Nativity of the BVM (Sep 8-15), Immaculate
Conception (Dec 8-15), and All Saints (Nov 1-8) now declare octave:
{ enabled: true }, same generic mechanism as St. Lawrence and the
Christmas trio. Every octave this pull has identified is now modeled;
Matins reading content is a separate, larger follow-up (see conversation)
-- these still just commemorate at L/V-equivalent level for now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 08:20:47 -04:00
will da3b6e893e calendar: model octaves as a generic, data-driven mechanism
Deploy / deploy (push) Successful in 46s
Adds calendar/octaves.ts: a lookback over the past week collecting every
octave (sanctoral or temporal) still active on a date, stacking multiple
at once (Christmas + St. Stephen + St. John + Holy Innocents all
commemorated together within the Christmas Octave). Declared via an
optional `octave` field on a saint's own record or a new small
TemporalFeastRecord (calendar/temporal-feasts.ts) for temporal ids like
Christmas/Pentecost that didn't have a metadata record before -- data-
driven per user design discussion, with `{ enabled: true }` alone using
sensible defaults (8 days, semiduplex threshold) so a minimal declaration
works without authored content.

Wired into resolveDay as a post-processing layer: doesn't change how a
single day's own precedence contest is decided, just adds commemorations
for active octaves and occasionally overrides the winner when the
occurring saint doesn't clear the strictest active octave's threshold.

Populated so far: St. Lawrence's own octave (the one that repeatedly cost
real saints their spot in August), the three Comites Christi octaves
(Stephen/John/Innocents -- Thomas of Canterbury deliberately excluded,
per discussion), and Pentecost's (duplex threshold, user-specified).
Pentecost's octave offsets are also removed from temporal-categories.yml's
privileged-feria-major classification, letting a real candidate reach the
new octave layer instead of being transferred away first -- with the
side effect that Pentecost's own Ember Saturday no longer forces a
transfer (a sub-threshold saint is now commemorated in place instead, see
tests/calendar/transfer.test.ts's updated case). Assumption, Nativity
BVM, Immaculate Conception, and All Saints' own octaves are not yet
populated with octave data -- deliberately deferred to a follow-up pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 07:23:43 -04:00
will c0413a44dc propers: add December's collect and antiphon text
Deploy / deploy (push) Successful in 45s
10 collects, 5 antiphons -- including backfilling the pre-existing
Immaculate Conception entry. St. Damasus's collect is Latin-only (no
English translation exists in the reference source at all); a few
others (All Saints, Bibiana, Immaculate Conception) needed their English
read directly from the raw source file after the live query's English
side either omitted the Oratio translation or rendered the wrong Marian
feast's text -- caught by cross-checking, not assumed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 06:34:45 -04:00
will 08f94823f7 calendar: give Advent's ordinary ferias their own precedence tier
Deploy / deploy (push) Successful in 44s
Found while starting the December sanctoral pull: Advent's plain
(non-Ember) weekday ferias have real standing in the live Monastic 1617
engine that the existing ordinary-feria category couldn't represent --
a Simplex saint (St. Bibiana, Dec 2) is merely commemorated there rather
than winning outright, while a Semiduplex+ saint (St. Nicholas, Dec 6)
wins with the feria itself commemorated back. Adds a third, weaker
privileged-feria-minor tier (Semiduplex+ threshold, vs. privileged-
feria's Duplex+) rather than reusing either existing tier, mirroring how
privileged-feria/privileged-feria-major were split in March. Lent's own
ordinary ferias likely share this property but are left as-is, unverified
this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 06:23:35 -04:00
will 7cc6adfb55 propers: add November's collect and antiphon text
Deploy / deploy (push) Successful in 44s
9 collects, 3 antiphons -- including backfilling the pre-existing All
Saints entry. Also updates two pre-existing tests whose shared date
(2025-11-30, Advent I Sunday) now correctly shows St. Andrew commemorated
alongside it, confirmed against the live reference engine.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 06:18:12 -04:00
will 14227c7afe propers: add October's collect text
Deploy / deploy (push) Successful in 46s
7 collects. Also moves two pre-existing tests' dates off Oct 4-5, which
now carry real sanctoral content (St. Francis, Ss. Placid and
Companions) that changes their governing behavior -- same class of
collision as previous months.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 06:07:51 -04:00
will 3376036779 propers: add September's collect and antiphon text
Deploy / deploy (push) Successful in 43s
6 collects, 1 antiphon -- including backfilling the pre-existing Nativity
of the BVM entry now that the pulling methodology exists.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 21:20:44 -04:00
will a492be961b propers: add August's collect and antiphon text
Deploy / deploy (push) Successful in 44s
11 collects, 4 antiphons -- including backfilling the three pre-existing
August entries (Lawrence, Assumption, Augustine) now that the pulling
methodology exists. Also updates three pre-existing tests whose dates
collided with this month's new real content: the vigil-of-St.-Lawrence
backward-transfer case now runs into a real feast at its landing day
instead of an empty one (confirmed correct against the live reference
engine, including the surviving commemoration on the impeded Sunday
itself), and two other tests moved off Aug 9/10 to dates unaffected by
the new data.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 21:11:56 -04:00
will c03d6a227d propers: add July's collect and antiphon text
Deploy / deploy (push) Successful in 42s
Real collect text for all 9 July saints that have one, plus St. Mary
Magdalene's own antiphon — same extraction method as prior months.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 18:38:50 -04:00
will 9b8dc200a1 propers: add June's collect and antiphon text
Deploy / deploy (push) Successful in 42s
Real collect text for all 16 June saints that have one, plus a real
antiphon for 4 of them and a fifth (Ss. Peter and Paul) that deliberately
reuses the Chair-of-Peter-at-Antioch antiphon text, matching the source's
own cross-reference — same extraction method as prior months.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 17:37:27 -04:00
will a6a72f277d propers: add May's collect and antiphon text
Deploy / deploy (push) Successful in 42s
Real collect text for all 13 May saints that have one, plus a real
antiphon for the 3 that have one of their own (Ss. Philip and James, St.
John Before the Latin Gate, the Apparition of St. Michael) — same
extraction method as prior months. Two saints (St. Peter Celestine, St.
Urban I) have an [Ant 1] in the source that turned out to just be a
cross-reference to the generic Common template, not real unique text, so
no antiphon file was authored for them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 17:25:56 -04:00
will f0e32ae0c1 calendar: fix transferred candidates blindly winning outright
Found via real data (the May sanctoral pull): a transfer landing on a day
whose own native winner was temporal blindly took over as winner,
regardless of that day's own precedence category — so a transferred-in
Simplex saint (St. Felix I, impeded by Pentecost's Ember Saturday) was
overwriting Trinity Sunday itself instead of being merely commemorated,
the way a native Simplex candidate on an ordinary Sunday already
correctly is.

Fixes applyIncomingTransfer to run the arriving candidate through
decideOccurrence using the receiving day's own temporalCategory, the same
rules a native occurrence there would use, instead of assuming an empty
temporal slot means automatic victory.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 17:25:27 -04:00
will 88074cdfe6 propers: add April's collect text
Deploy / deploy (push) Successful in 41s
Real collect text for all 8 April saints that have one — same extraction
method as prior months. One correction to St. Robert's own English
translation in the source, which left his name in Latin genitive form
("blessed Robérti") rather than translating it — fixed, flagged in the
file as a transcription artifact, not a deliberate style choice.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 17:14:12 -04:00
will effe2b1333 calendar: split privileged-feria into two real precedence tiers
Deploy / deploy (push) Successful in 41s
A plain Duplex saint was losing to any privileged feria (Ember days
included) since the occurrence engine only let duplex-1-classis+ get
even a commemoration there. Verified this was wrong: St. Gregory the
Great, plain Duplex, outright wins against a Lenten Ember Saturday in
the real Monastic 1617 engine.

Splits TemporalCategory's single privileged-feria into privileged-feria
(the lesser tier — Lent's Ember days, verified — now behaves like an
ordinary Sunday: Duplex+ wins outright) and privileged-feria-major (Ash
Wednesday, Holy Week, the Easter Octave, verified via St. Mark only ever
being commemorated there, never winning — behaves like privileged-
Sunday). Everywhere else the old single category was ambiguous
(Pentecost's own Ember days/Vigil/Octave, the Vigil of Christmas)
defaults to the stricter major tier pending verification.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:51:09 -04:00
will a2d86a4879 propers: add March's collect and antiphon text
Deploy / deploy (push) Successful in 40s
Real collect text for all 6 March saints that have one, plus St. Joseph's
own antiphon — same extraction method as January/February.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:38:11 -04:00
will 8cb10e57de propers: add February's collect and antiphon text
Deploy / deploy (push) Successful in 38s
Real collect text for the 6 February saints that have one, plus a real
antiphon for the 2 that have one of their own — same extraction method
as January (fully-rendered live-engine output, not the raw source files'
own shorthand endings).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:33:29 -04:00
will c1d99ea70b propers: add January's collect and antiphon text
Deploy / deploy (push) Successful in 41s
Real collect text for the 9 January saints that have one, plus a real
antiphon for the 3 that have one of their own (as opposed to falling back
to a generic Common-of-Saints text) — read directly from the reference
engine's fully-rendered output, not reconstructed from the raw source
files' own shorthand endings ($Per Dominum, $Qui vivis, etc.).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:26:16 -04:00
will 37ac31c3f2 calendar: occurrence engine v2 — real rank thresholds, transfers, collisions
Deploy / deploy (push) Successful in 39s
Corrects and completes the occurrence rules, based on a design discussion
plus one concrete data point: St. Anthony Abbot (plain Duplex) was found
outright winning against an ordinary Sunday in the real Monastic 1617
engine, which the old duplex-1-classis-only threshold got wrong.

- FeastClass gains `vigil`, inserted between `simplex` and `semiduplex` —
  one ordering that correctly serves both "does this win against a Sunday"
  (vigil behaves like simplex there) and "which of two saints wins a
  landing-day collision" (vigil beats simplex, loses to semiduplex).
- LiturgicalDay.occurring (a flat OccurringFeast[] that could only ever
  express a losing *sanctoral* candidate) is replaced by `winner:
  DayWinner` + `commemorations: Commemoration[]` — a discriminated list
  that can hold the temporal day itself, one or more sanctoral entries, or
  (not built yet, but the shape already accommodates it) a future octave
  kind.
- commemorations.ts: ordinary Sundays let Duplex+ win outright (Sunday
  commemorated in return), Semiduplex/Vigil transfer elsewhere (too
  substantial a feast to cheapen with a bare commemoration), Simplex stays
  and is commemorated. Privileged Sundays never displace; Duplex-majus+
  commemorated, everything else transfers.
- collision.ts (new): resolves two sanctoral candidates wanting the same
  day (a transfer landing on an already-occupied day, or two native
  saints sharing a date) — duplex > semiduplex > vigil > simplex, loser
  always commemorated, ties favor the native occupant.
- temporal-id.ts (new): maps any date to one of the 52 real Sunday-collect
  ids from the previous commit, so a temporal winner/commemoration can
  actually be looked up, not just labeled "temporal" in the abstract.
- index.ts's resolveDay orchestrates all of it, including the actual
  Monday/Saturday transfer mechanism. Landing on a privileged feria (the
  concrete case: Holy Week, right after Palm Sunday) is explicitly
  deferred rather than guessed at — it needs its own Easter-keyed lookup
  table, the same way the reference engine handles it.

Added the Vigil of St. Lawrence (Aug 9) as real content specifically to
exercise the backward-transfer rule end-to-end: Aug 9, 2026 is a Sunday,
so the vigil transfers cleanly back to Saturday, verified by a new
integration test alongside the unit-level rule and collision tests.
2026-08-10 12:00:01 -04:00
will 226fff2ce6 ui: show the "day being celebrated" label
Deploy / deploy (push) Successful in 38s
Adds a real label under each hour's heading — "Monday in the 10th week
after Trinity", "The 1st Sunday of Advent" — computed from whichever
LiturgicalDay the hour actually resolved against, which can differ from
the nav date for Compline's evening anticipation.

calendar/day-label.ts combines two things: an ordinal week-within-season
label (pure date arithmetic on the season anchors from calendar/temporal.ts
and calendar/easter.ts — Trinity-counted, not Divinum Officium's own
Pentecost-counted convention; meant to become configurable later via the
same day->id indirection already used for the sanctoral calendar, not
hardcoded forever), and a feast name from calendar/commemorations.ts's
occurrence decision — shown alone if the feast displaces the day outright,
prefixed onto the temporal label if merely commemorated, or omitted
entirely if nothing's occurring.
2026-08-10 07:07:10 -04:00
will eaaca05ad8 calendar: First/Second Vespers anticipation for Compline
Compline (and eventually Vespers) now resolves off whichever day's
identity actually governs tonight's office, not always today's — real
practice anticipates a higher-ranking tomorrow (Alma Redemptoris Mater
starting the Saturday evening before Advent I, Ave Regina Caelorum
starting the eve of Candlemas, Regina Caeli starting at the Easter
Vigil), which the previous date-only resolution missed entirely.

calendar/vespers.ts's resolveEveningDay compares today's and tomorrow's
precedence (reusing commemorations.ts's FeastClass machinery) to decide.
One deliberate absolute exception, caught by a failing test: a short,
explicit list of supreme fixed/movable feasts (Easter, Christmas,
Epiphany, Candlemas, Ascension, Corpus Christi, Sacred Heart) always wins
tomorrow's Vespers before checking whether today would otherwise keep its
own — without it, Holy Saturday's privileged-feria status incorrectly
blocked Easter's anticipation, the textbook case this whole thing exists
to get right.

hours/compline.ts now resolves its whole ordo through resolveEveningDay
instead of resolveDay.
2026-08-10 07:05:41 -04:00
will 2ea21f2c89 calendar: real occurrence/precedence resolution (feast ranks, sanctoral content)
Replaces the FeastRank placeholder with a real ordered FeastClass (the old
pre-1955 six-level scale) and a new TemporalCategory (privileged/ordinary
Sunday/feria). calendar/commemorations.ts's decideOccurrence encodes the
actual precedence rules as explicit, commented branches per category
rather than the reference engine's own opaque numeric weights — this app
targets one ruleset, so the readability trade-off is worth it. Category
membership (data/calendar/temporal-categories.yml) is a best-effort
reconstruction of the pre-1955 tradition, not sourced from a primary text;
expect corrections.

calendar/feasts.ts resolves real sanctoral candidates, and resolveDay()
wires it all together — occurring/temporalCategory are no longer stubs.
isDoubleOrHigher (hours/antiphon.ts) is now a real comparison instead of
a hardcoded false.

Seeded 7 real saints/feasts, each verified directly against Divinum
Officium's own rank data (not reconstructed from memory) as a small,
growable start: St. Lawrence, the Assumption, St. Augustine, the Nativity
of the BVM, St. Michael, All Saints, the Immaculate Conception.
2026-08-10 07:03:28 -04:00
will 67037469fc calendar: compute real Easter dates and temporal-cycle seasons
resolveDay() no longer hardcodes season: 'trinitytide'. Easter is
computed via the Anonymous Gregorian algorithm (verified against 16
known reference dates spanning 1583-2100); Advent/Christmastide/
Epiphanytide follow the Christmas-anchored rules (including Advent's
"Sunday nearest Nov 30"); Septuagesima through Trinitytide come from
easter-offsets.yml, reshaped from single named anchor points into real
ranges plus single-day overrides for Corpus Christi and Sacred Heart.

occurring feasts (calendar/feasts.ts) are still a stub — the sanctoral
calendar and Double-vs-not ranking are a separate, larger project.
2026-08-10 05:27:12 -04:00
will 58958aa847 Prime: real content (psalms, Martyrology, Regula) and ordo corrections
Deploy / deploy (push) Failing after 21s
Pulls in verified content from Divinum Officium rather than placeholders:
17 psalms (2, 6, 7-19, 118, 129), 365 days of the Martyrology, and the full
121-reading Regula cycle, plus the Athanasian Creed.

Ordo corrections driven by review against the real engine output:
- Capitulum and Preces now pick a Sunday/feast vs. ferial form
  (calendar/isSundayOrFeast); ferial Preces said every ferial day by choice.
- Chapter responsory, hymn doxology, and the opening versicle's
  Alleluia/Laus tibi all vary by season via a shared resolver
  (hours/seasonal-propers.ts).
- Real Roman Kalends/Nones/Ides Latin dating (calendar/roman-date.ts,
  verified against 363/365 real Martyrology headings) plus the historical
  "bis sextus" Feb 29 handling, and the Martyrology's Luna (moon-day)
  heading (a ported Golden-Number calculation).
- Fixed responsory structure (was missing its initial full repeat),
  weekday psalm antiphons (opening as incipit-or-full by rank, full
  repeat after the psalms/Creed as its own part, "*" chant mark kept),
  scripture citations on the capitulum/lectio brevis, and V./R. markers
  switched from Unicode symbols to plain text for reliable font rendering.
- Dropped Pretiosa and the dead-commemoration psalm (129) for time;
  trimmed section headings down to the ones that are actually named
  things (Preces, Chapter Office, etc. no longer relabel connective text).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 20:03:53 -04:00
will a5dc6502d7 Milestone 0/1: shell, calendar/psalter/hours scaffold, Prime
Deploy / deploy (push) Failing after 1m8s
Client-side-first PWA (Vite/TS, no backend) per the approved plan: day-
navigable shell listing all 8 hours, Prime fully resolves via the
calendar -> psalter -> ordo pipeline, the other 7 hours are registered
but flagged not-implemented. Sanctoral/temporal calendar data uses a
day -> id indirection layer (saints, easter-offsets, fixed-date-calendar)
so reassigning a feast to a different day is a data edit, not a code
change. Docker (Caddy-serving-static) + Gitea CI workflow scaffolded to
match the eec/drip/bookshop operational pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 15:20:06 -04:00