From f8bd7f3140fdef58ecaa5b8c875797b2f6549f80 Mon Sep 17 00:00:00 2001 From: Will Estes Date: Sat, 5 Sep 2026 07:22:53 -0400 Subject: [PATCH] Dedupe Matins nocturn readings pooled from two ids on the same day post-pentecost-15 and month-week-092 land on the same Sunday (2026-09-06) and independently reuse the identical Gregory the Great Moralia in Job excerpt -- a real duplication in the reference engine's own Tempora files, not a vu authoring error. buildReadingPool pooled both ids and rendered the reading twice; now dedupes by text. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01MKC2QQGLYo2UTiDjDyWEkW --- src/hours/matins.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/hours/matins.ts b/src/hours/matins.ts index a7d8715..97c9b69 100644 --- a/src/hours/matins.ts +++ b/src/hours/matins.ts @@ -839,11 +839,23 @@ function buildReadingPool(day: LiturgicalDay, temporalId: string, date: string, // must be handled, not just the usual Sunday/feast pair. const ids = nocturnReadingIds(day, temporalId, date, threeNocturns); const byNocturn = new Map(); + // The reference engine's own Tempora files sometimes independently reuse + // the exact same excerpt across two different Sunday-numbering schemes + // (e.g. a Pentecost-numbered Sunday and a calendar-month Sunday landing on + // the same date — see month-week-092.yml's own header) — only one of + // those numbering schemes is ever in force on a given real calendar, but + // `nocturnReadingIds` can legitimately pool both ids for the *same* day + // here, which would otherwise surface the identical reading twice in one + // hour. Dedupe by Latin text, keeping the first (earliest-id) occurrence. + const seenReadingText = new Set(); for (const id of ids) { const readings = getNocturnReadings(id); let commonPoolIndex = 0; for (let i = 0; i < readings.length; i++) { const reading = readings[i]!; + const textKey = reading.text.la ?? reading.text.en ?? ''; + if (textKey && seenReadingText.has(textKey)) continue; + if (textKey) seenReadingText.add(textKey); const bucket = byNocturn.get(reading.nocturn) ?? []; if (reading.isGospel) { // A genuine separate homily on this pericope is the very next