Commit Graph

5 Commits

Author SHA1 Message Date
will 4bbd78b1fd Model Ascension, Corpus Christi, and the Sacred Heart as temporal feasts
Deploy / deploy (push) Successful in 1m23s
Adds pre-1955 TemporalFeastRecords (rank duplex-1-classis, real octaves)
for the three "feasts of the Lord" that were previously only referenced
as bare date offsets: Corpus Christi/Sacred Heart's own days already
couldn't lose to a sanctoral candidate, but with no record the day fell
back to the generic Trinity-week feria collect and never displayed its
real name; Ascension had no protection at all against an ordinary saint
winning it outright. Sacred Heart's own record carries the
forbidsSuccessorCommemoration flag added in the prior commit, refusing to
commemorate Most Precious Blood on the rare late-Easter date they fall
adjacent.

octave.wins is set to duplex on all three, matching Pentecost's own
verified threshold, despite a known conflict with a previously
live-verified case (St. Ubald winning First Vespers within Ascension's
own octave) -- kept per direct instruction; the affected tests (Ubald,
St. Margaret of Scotland) were updated to assert the new behavior, and
the tradeoff is documented in ascension.yml and TODO.md. A handful of
unrelated test fixtures that happened to land inside these new octave
windows were moved to nearby clean dates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014axryJBrRswYh2niA7WCUc
2026-08-26 15:21:26 -04:00
will dde539d2e4 Fix Vespers commemoration: a Simplex successor is commemorated too
Deploy / deploy (push) Successful in 1m18s
User-reported: 2026-08-24 Vespers (St. Bartholomew, Duplex II. classis,
keeps his own evening) should have commemorated 2026-08-25's St. Louis
(Simplex), but didn't. This was the exact untested asymmetry the old
commemorationOf's own doc comment flagged as "inferred by symmetry, not
independently live-verified." Live-verifying now shows the two
directions genuinely differ: a Simplex predecessor losing to tomorrow's
First Vespers is correctly excluded (Aug 7 Donatus case, "nihil de
præcedenti"), but a Simplex successor displaced because today keeps its
own Vespers IS still commemorated (Aug 24->25, "commemoratio de
sequenti").

Split the one shared commemorationOf into
commemorationOfDisplacedPredecessor (keeps the Simplex exclusion) and
commemorationOfDisplacedSuccessor (drops it).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014axryJBrRswYh2niA7WCUc
2026-08-26 08:57:03 -04:00
will 979bbe6aa4 Model cross-day Vespers commemorations, fix First Vespers threshold
Deploy / deploy (push) Successful in 1m1s
Whichever of today/tomorrow doesn't govern a given evening's Vespers
can still be commemorated there, unless it's Simplex (or a bare
temporal winner with no standing of its own) — live-verified in both
directions against the real Monastic 1617 engine: Ss. Cyriacus/Largus/
Smaragdus (Semiduplex) commemorated when Sunday claims First Vespers
over them; St. Anne commemorated even though St. James (Duplex II.
classis) keeps his own Second Vespers outright; St. Donatus (Simplex)
gets nothing ("nihil de præcedenti") in the same situation Cyriacus/
etc. did get a commemoration. The isMajorFixedFeastOfTheLord override
(Christmas/Epiphany/Candlemas/Easter/Ascension/Corpus Christi/Sacred
Heart) deliberately doesn't inherit this yet — no live data on whether
those suppress it the way privileged-sunday/privileged-feria-major do
during the day.

Also fixes hasFirstVespers's threshold, found wrong while gathering
the above evidence: it required duplex-majus+, but Ss. Cyriacus/etc.
(plain Semiduplex) actually claims First Vespers over St. Donatus in
the live engine. Lowered to semiduplex, matching the sibling
privileged-feria-minor threshold already used just below it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 18:59: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 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