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
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
Keeps Simplex commemorating in place, but a Semiduplex feast on an
ordinary Sunday goes back to transferring off to the next open day —
this app's own design choice, not a correction against a reference
engine. The transfer mechanism is already generic: this file's `decideOccurrence`
only signals "couldn't hold onto this candidate" for the day itself;
calendar/index.ts's resolveDay is what independently checks each
neighboring day's own native occurrence for an incoming transfer and
claims it — no separate lookback logic needed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two related fixes surfaced while chasing why St. Gregory Thaumaturgus
appeared to be misdated on Nov 18:
- calendar/commemorations.ts's `ordinary-sunday` case was transferring a
Semiduplex (or lower) saint off the Sunday instead of commemorating it
in place — an earlier, unverified guess. Live-verified against both
Tridentine 1906 and Divino Afflatu 1954 (St. Gregory Thaumaturgus, St.
Clement, St. Apollinaris, St. Thomas Becket, all real cases): the saint
stays and is commemorated on the Sunday itself, same as Simplex, never
pushed to the next open day. This is what was actually moving Gregory
onto Nov 18 — not a data error. `applyChristmasOctaveSunday`'s own
Dec 26-29 special case needed a matching adjustment (per its own
documented intent, the displaced saint there is deliberately *not*
commemorated in place, since he reappears in full on Dec 30 instead).
- getDayLabel had five branches, each hand-assembling its own
filter/format logic for which commemorations to show — which is why
the octave phrasing, the closing-day title, and a missing Sunday
commemoration turned into three separate bugs earlier instead of one.
Replaced with a single shared `collectCommemorations` used by every
branch. This also exposed that the sanctoral-winner branch never
showed any commemorated saint at all, and every other branch only
showed the *first* one (`.find()`), silently dropping real collisions
— both now show every commemorated saint, matching this app's own
generous-commemoration design.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
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>
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.
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.