Implement octave-vs-octave precedence, and fix a real day-label bug it surfaced
Deploy / deploy (push) Successful in 52s
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>
This commit is contained in:
@@ -137,6 +137,15 @@ export interface OctaveConfig {
|
||||
* data/calendar/temporal-feasts/pentecost-sunday.yml), which is
|
||||
* stricter (`duplex`). */
|
||||
wins?: FeastClass;
|
||||
/** The octave's own effective rank on its *last* day specifically (the
|
||||
* "in Octava" closing day) instead of `wins` — live-verified as a real,
|
||||
* general pattern rather than a per-saint quirk: both St. Lawrence's
|
||||
* own Aug 17 and the Assumption's own Aug 22 show as Duplex, elevated
|
||||
* above their otherwise-Semiduplex ordinary in-between days. Default
|
||||
* 'duplex'. Feeds both the rival-saint threshold (calendar/octaves.ts's
|
||||
* `strictestThreshold`) and octave-vs-octave precedence
|
||||
* (`resolveActiveOctave`) on that one day. */
|
||||
closingDayRank?: FeastClass;
|
||||
}
|
||||
|
||||
export type DayWinner =
|
||||
|
||||
Reference in New Issue
Block a user