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
This commit is contained in:
2026-09-04 14:50:31 -04:00
parent 2a611cc17b
commit aba89dc250
15 changed files with 387 additions and 32 deletions
+26 -19
View File
@@ -21,18 +21,19 @@ describe('getDayLabel — ordinal temporal label', () => {
it('names the anchor day itself, not "day after itself"', () => {
// Trinity Sunday 2026 (May 31) is now also the Queenship of the
// Blessed Virgin Mary's own fixed day (Duplex II Classis, added per
// the full-year sanctoral import) — since this app models Trinitytide
// Sundays as plain `ordinary-sunday` with no special first-class
// standing of their own, the Duplex+ sanctoral feast wins outright
// here per the normal ordinary-Sunday rule (see
// tests/calendar/transfer.test.ts's own May 31 case for the full
// winner/commemorations breakdown), so the label now reflects her,
// not Trinity Sunday itself — but Trinity Sunday is still
// commemorated in return (`decideOccurrence`'s own `ordinary-sunday`
// branch), by bare name only — a commemoration never carries a rank
// parenthetical, only the day's own winner does.
// the full-year sanctoral import). Trinity Sunday itself used to be
// modeled as plain `ordinary-sunday` with no special first-class
// standing of its own, purely a cosmetic label overlay -- fixed
// 2026-09-04 with a real `trinity-sunday` temporal-feast record
// (calendar/data/calendar/temporal-feasts/trinity-sunday.yml),
// `unconditional: true` per direct instruction (a principal Sunday
// shouldn't lose to a same-rank fixed-date collision, same shape as
// christ-the-king.yml). Trinity Sunday now wins outright and the
// Queenship is commemorated instead, by bare name only — a
// commemoration never carries a rank parenthetical, only the day's
// own winner does.
expect(getDayLabel(resolveDay('2026-05-31')).en).toBe(
'The Queenship of the Blessed Virgin Mary (Duplex II Class) — Trinity Sunday',
'The Most Holy Trinity (Duplex II Class) — The Queenship of the Blessed Virgin Mary',
);
expect(getDayLabel(resolveDay('2026-04-05')).en).toBe(
"Easter (Duplex I Class) — St. Vincent Ferrer, Confessor (transferred away)",
@@ -41,12 +42,12 @@ describe('getDayLabel — ordinal temporal label', () => {
"Ash Wednesday — St. Simeon, Bishop and Martyr (transferred away)",
);
// Latin: the winner now has a real authored nameLa (see
// calendar/data/calendar/saints/queenship-of-the-bvm.yml), so this is
// real Latin throughout — the rank label ("Duplex II. Classis") and
// the commemorated Sunday's own name ("Dominica Sanctissimae
// Trinitatis") were already real Latin before this.
// calendar/data/calendar/saints/queenship-of-the-bvm.yml and
// temporal-feasts/trinity-sunday.yml's own "Sanctissima Trinitas"),
// so this is real Latin throughout — the rank label ("Duplex II.
// Classis") was already real Latin before this.
expect(getDayLabel(resolveDay('2026-05-31')).la).toBe(
'Beata Maria Virgo Regina (Duplex II. Classis) — Dominica Sanctissimae Trinitatis',
'Sanctissima Trinitas (Duplex II. Classis) — Beata Maria Virgo Regina',
);
expect(getDayLabel(resolveDay('2026-04-05')).la).toBe(
'Pascha (Duplex I. Classis) — Sanctus Vincentius Ferrerius, Confessor (translata alio)',
@@ -233,14 +234,20 @@ describe('getDayLabel — active octave', () => {
expect(getDayLabel(resolveDay('2028-11-03')).en).toBe('3rd Day within the Octave of All Saints (Semiduplex)');
});
it("a season's own named anchor day outranks an active octave, even though Trinity Sunday is technically also day 8 of Pentecost's own octave", () => {
it("Trinity Sunday itself outranks Pentecost's own octave, which is technically still active on the same day (day 8)", () => {
// Not 2026 (May 31, the Queenship of the Blessed Virgin Mary's own
// fixed day, see tests/calendar/transfer.test.ts) and not 2023
// (June 4, now St. Francis Caracciolo's own fixed day) -- both would
// muddy this specifically octave-vs-anchor-day check with a sanctoral
// winner. 2030's Trinity Sunday (June 16) has no sanctoral entry at
// all, isolating the octave interaction cleanly.
expect(getDayLabel(resolveDay('2030-06-16')).en).toBe('Trinity Sunday (Duplex I Class)');
// all, isolating the octave interaction cleanly. Since 2026-09-04,
// Trinity Sunday is a real, unconditional-winning temporal-feast
// (see the test above) rather than a purely cosmetic label overlay,
// so this is now a real occurrence result, not just a label choice --
// Duplex II Class, its own live-verified rank, not the earlier
// (never-verified) "Duplex I Class" placeholder this test used to
// assert.
expect(getDayLabel(resolveDay('2030-06-16')).en).toBe('The Most Holy Trinity (Duplex II Class)');
});
it("a temporal day with real standing of its own (not ordinary-feria) never shows an octave name at all, even with one active -- live-verified counterexample: the Christmas Octave's own stack (Dec 30) titles itself off the Sunday, never any of the four octaves layered on top of it", () => {