diff --git a/TODO.md b/TODO.md index b5c5ed6..2702dab 100644 --- a/TODO.md +++ b/TODO.md @@ -5282,3 +5282,25 @@ on every split lesson, and does so consistently across the *entire* nocturn-read just Ember days — flagged for the user as a real presentational rough edge, not fixed yet pending their call on scope (a corpus-wide UI/authoring change, not a narrow one-file fix). +**Third follow-on, same session**: user then asked why a Sunday's own patristic homily was +showing up on a Friday at all. Pulled the live reference engine's own Matins page for St. Joseph +of Cupertino's day (Tridentine 1906) to check, rather than reasoning from vu's data alone: real +Nocturn III there is exactly 3 lessons — 2 from the winning Duplex saint's own Common homily, plus +a single "**Commemoratio Feriæ**" lesson for the displaced Ember day. No Sunday content +whatsoever. `hours/matins.ts`'s `nocturnReadingIds` had a `temporalKept` block that pooled the +governing Sunday's own id (`temporalId`) *and* its `month-week-N` sibling whenever any temporal +commemoration survived on a 3-nocturn day, with no weekday check at all — so a Duplex+ saint +winning outright on a plain weekday (not a Sunday) that also happened to carry a temporal +commemoration pulled in a whole second homily's worth of unrelated content (here: St. Ambrose's +homily + its own Gospel from `post-pentecost-16`, and St. Leo's September-fast sermon from +`month-week-093` — two different reference-engine representations of the *same* underlying +Sunday, both wrongly pooled at once). Fixed by gating `temporalKept` to `day.weekday === 'sunday'` +— the governing Sunday's own content only belongs in the pool when that Sunday is the day actually +being celebrated. Live-verified by reloading `/vu/2026-09-18/matins`: both spurious readings are +gone. `npm test` (2025 passed) and `tsc --noEmit` both pass. + +Still open, by the user's own explicit request to land this first: Ember Friday's own homily +still surfaces as all 3 of its lessons even when merely commemorated, where the live engine caps +a commemorated feria at exactly one lesson (its own Lectio 1 only) — same shape of fix as this +one, not yet done. + diff --git a/src/hours/matins.ts b/src/hours/matins.ts index 2b21e4b..2641eb4 100644 --- a/src/hours/matins.ts +++ b/src/hours/matins.ts @@ -654,20 +654,37 @@ function nocturnReadingIds(day: LiturgicalDay, temporalId: string, date: string, } // The plain temporalId/month-week content is the *governing Sunday's own* // Nocturn 2/3 patristic material, real content for that Sunday itself — - // only pooled on a real 3-nocturn day, and (as before) only when the - // day's own occurrence decision (calendar/commemorations.ts's - // decideOccurrence) actually retained the temporal identity in some form: - // the temporal cycle won outright (day.winner.kind === 'temporal' -- a - // plain Sunday, or a named temporal override like Christ the King), or it - // survives as a commemoration alongside a sanctoral winner. Excluded: - // decideOccurrence's `ordinary-feria` branch, where a real feast -- - // however low-ranked -- wins with zero commemorations, correctly - // suppressing the temporal identity entirely (e.g. St. Bartholomew, - // duplex-2-classis, 2026-08-24 -- his own proper reading has no Nocturn - // 3 content, and without this gate the leftover 13th-Sunday-after- - // Pentecost/month-week content wrongly filled Nocturn 3 instead). + // only pooled on a real 3-nocturn day, only on the Sunday itself (see + // below), and (as before) only when the day's own occurrence decision + // (calendar/commemorations.ts's decideOccurrence) actually retained the + // temporal identity in some form: the temporal cycle won outright + // (day.winner.kind === 'temporal' -- a plain Sunday, or a named temporal + // override like Christ the King), or it survives as a commemoration + // alongside a sanctoral winner. Excluded: decideOccurrence's + // `ordinary-feria` branch, where a real feast -- however low-ranked -- + // wins with zero commemorations, correctly suppressing the temporal + // identity entirely (e.g. St. Bartholomew, duplex-2-classis, 2026-08-24 + // -- his own proper reading has no Nocturn 3 content, and without this + // gate the leftover 13th-Sunday-after-Pentecost/month-week content + // wrongly filled Nocturn 3 instead). + // + // `day.weekday === 'sunday'` gate added 2026-09-03: live-verified + // (Tridentine 1906) that a Duplex+ saint winning outright on a *weekday* + // that also happens to carry a temporal commemoration (e.g. St. Joseph + // of Cupertino, Duplex, Friday Sept 18) gets no Sunday content at all -- + // the reference engine's own Nocturn III there is just the saint's own + // Common homily (2 lessons) plus a single "Commemoratio Feriæ" lesson + // for the displaced feria, never the week's separate governing-Sunday + // homily (Ambrose's/Leo's, in that live case). This mechanism previously + // fired on *any* 3-nocturn day with a surviving temporal commemoration, + // regardless of weekday, wrongly pooling in a whole extra Sunday's worth + // of unrelated patristic content on top of the day's own two real + // sources. The governing Sunday's own content only belongs in the pool + // when that Sunday *is* the day being celebrated. const temporalKept = - threeNocturns && (day.winner.kind === 'temporal' || day.commemorations.some((c) => c.kind === 'temporal')); + threeNocturns && + day.weekday === 'sunday' && + (day.winner.kind === 'temporal' || day.commemorations.some((c) => c.kind === 'temporal')); if (temporalKept) { ids.add(temporalId); const monthWeek = monthWeekId(date);