Stop pooling the governing Sunday's own Matins content on a weekday

nocturnReadingIds pooled the governing Sunday's own nocturn-readings
id (temporalId) and its month-week-N sibling whenever any temporal
commemoration survived on a 3-nocturn day, with no weekday check --
so a Duplex+ saint winning outright on a plain weekday that also
carried a temporal commemoration pulled in a whole second homily's
worth of unrelated Sunday content. Live-verified against the
reference engine (Tridentine 1906, St. Joseph of Cupertino's day):
real Nocturn III there is just the winning saint's own Common homily
plus a single "Commemoratio Feriae" lesson -- no Sunday content at
all. Gates temporalKept to day.weekday === 'sunday'.

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 07:13:07 -04:00
parent 290bbac1b5
commit 3c8ccc3cbb
2 changed files with 52 additions and 13 deletions
+22
View File
@@ -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 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). 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.
+30 -13
View File
@@ -654,20 +654,37 @@ function nocturnReadingIds(day: LiturgicalDay, temporalId: string, date: string,
} }
// The plain temporalId/month-week content is the *governing Sunday's own* // The plain temporalId/month-week content is the *governing Sunday's own*
// Nocturn 2/3 patristic material, real content for that Sunday itself — // 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 // only pooled on a real 3-nocturn day, only on the Sunday itself (see
// day's own occurrence decision (calendar/commemorations.ts's // below), and (as before) only when the day's own occurrence decision
// decideOccurrence) actually retained the temporal identity in some form: // (calendar/commemorations.ts's decideOccurrence) actually retained the
// the temporal cycle won outright (day.winner.kind === 'temporal' -- a // temporal identity in some form: the temporal cycle won outright
// plain Sunday, or a named temporal override like Christ the King), or it // (day.winner.kind === 'temporal' -- a plain Sunday, or a named temporal
// survives as a commemoration alongside a sanctoral winner. Excluded: // override like Christ the King), or it survives as a commemoration
// decideOccurrence's `ordinary-feria` branch, where a real feast -- // alongside a sanctoral winner. Excluded: decideOccurrence's
// however low-ranked -- wins with zero commemorations, correctly // `ordinary-feria` branch, where a real feast -- however low-ranked --
// suppressing the temporal identity entirely (e.g. St. Bartholomew, // wins with zero commemorations, correctly suppressing the temporal
// duplex-2-classis, 2026-08-24 -- his own proper reading has no Nocturn // identity entirely (e.g. St. Bartholomew, duplex-2-classis, 2026-08-24
// 3 content, and without this gate the leftover 13th-Sunday-after- // -- his own proper reading has no Nocturn 3 content, and without this
// Pentecost/month-week content wrongly filled Nocturn 3 instead). // 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 = 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) { if (temporalKept) {
ids.add(temporalId); ids.add(temporalId);
const monthWeek = monthWeekId(date); const monthWeek = monthWeekId(date);