Fix Matins reading-pool ordering when Nocturn 2/3 come from different sources
buildReadingPool concatenated readings in id-processing order, so a later post-Pentecost Sunday's Nocturn 3 (from its own temporalId file) could land ahead of its Nocturn 2 (from the newly-added month-week id) in the pool, flipping which nocturn slot each landed in. Group by each reading's own nocturn tag instead, ascending, preserving id/file order within each group. Also logs three follow-up items to TODO.md: displaying "Te decet laus", the missing responsory marker convention in nocturn-readings content, and removing Ps 129/50 from the Lauds/Vespers ferial Preces. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EWzE3kaSZCs79fPBrrE1aF
This commit is contained in:
@@ -32,6 +32,38 @@ across every hour and content type in this app.
|
|||||||
needs bilingual voice selection (La/En) worked out, and quality for Latin pronunciation
|
needs bilingual voice selection (La/En) worked out, and quality for Latin pronunciation
|
||||||
is an open question. Open, not started — needs its own design pass before content/UI work
|
is an open question. Open, not started — needs its own design pass before content/UI work
|
||||||
begins.
|
begins.
|
||||||
|
- Matins: "Te decet laus" (the short versicle sung right after the closing Gospel+"Amen",
|
||||||
|
opening Lauds — Rule of Benedict ch. 13, `data/regula/02-13.yml`) isn't modeled or
|
||||||
|
displayed anywhere. `post-pentecost-15.yml`'s own header comment already flagged this as
|
||||||
|
"a known simplification"; the user asked (2026-08-23) for it to actually be shown. Needs a
|
||||||
|
text/part decided (own `ResolvedPart` kind vs. reusing an existing one like `versicle`)
|
||||||
|
and where in the Matins ordo it renders (after the Gospel-reading-again-in-full that
|
||||||
|
currently closes Nocturn 3, before/instead of the existing Benedicamus/Fidelium close —
|
||||||
|
see memory `vu-matins-closing`). Not started.
|
||||||
|
- Matins nocturn-readings responsory formatting is inconsistent with octave-readings':
|
||||||
|
`data/propers/octave-readings/*.yml` responsories are written with explicit `℟.`/`℣.`
|
||||||
|
marks at the start of each line (e.g. `all-saints-octave-day-6.yml`), but every
|
||||||
|
`data/propers/nocturn-readings/*.yml` responsory (both the original two proof dates and
|
||||||
|
everything from the 2026-08-23 temporal-cycle/month-week sweeps) starts straight into the
|
||||||
|
Latin/English text with no leading marker at all — confirmed by grepping every responsory
|
||||||
|
`la:` line in that directory, not an isolated miss on one file. User flagged this
|
||||||
|
(2026-08-23) via "the responsory after the Augustine reading needs to start with the R.;
|
||||||
|
that R. is missing" — real, but the fix is either (a) prepend `℟.`/`R.` (and `℣.`/`V.`)
|
||||||
|
to every existing nocturn-readings responsory's text, matching octave-readings' convention
|
||||||
|
exactly, or (b) inject the marker at render time in `ui/hour-view.ts`'s lesson-responsory
|
||||||
|
rendering instead of in content, which would fix every file (old and new) in one place but
|
||||||
|
needs the responsory text's internal `\nV. ...\nR. ...` structure parsed rather than
|
||||||
|
treated as opaque text. Needs a decision before either bulk-editing ~30+ content files or
|
||||||
|
touching the renderer — not started.
|
||||||
|
- Lauds/Vespers ferial Preces (`data/propers/common/lauds-preces-feriales.yml`,
|
||||||
|
`vespers-preces-feriales.yml`) each embed a full psalm inline within the Preces text
|
||||||
|
itself — Psalm 129 (De profundis) at Lauds, Psalm 50 (Miserere) at Vespers, per the
|
||||||
|
reference engine's own `[Preces feriales Vespera] @:Preces feriales Laudes:s/129/50/`
|
||||||
|
substitution (see each file's own header comment). User asked (2026-08-23) to remove
|
||||||
|
both psalms from the Preces. Not started — needs deciding whether to just delete the
|
||||||
|
psalm block (and its own trailing Gloria Patri line) from each file's `text.la`/`text.en`
|
||||||
|
wholesale, or whether the surrounding V/R litany needs any adjustment once the psalm's
|
||||||
|
gone.
|
||||||
|
|
||||||
2. **Minimal-proof-done, bulk content pending** — mechanism is built and trusted (a proof
|
2. **Minimal-proof-done, bulk content pending** — mechanism is built and trusted (a proof
|
||||||
date/entry already resolves correctly end-to-end); what's left is authoring/importing more
|
date/entry already resolves correctly end-to-end); what's left is authoring/importing more
|
||||||
@@ -1500,6 +1532,25 @@ reach (there are none within Aug-Nov — all 20 files are authored); the rest of
|
|||||||
cycle (Advent through Eastertide, per the post-Pentecost sweep's own "not done" list above)
|
cycle (Advent through Eastertide, per the post-Pentecost sweep's own "not done" list above)
|
||||||
remains open and is unrelated to this particular gap.
|
remains open and is unrelated to this particular gap.
|
||||||
|
|
||||||
|
**Ordering bug found and fixed same day**: pooling a `temporalId`'s own file (Nocturn 3 only,
|
||||||
|
for a late post-Pentecost Sunday) alongside a separately-sourced `month-week-<id>` file
|
||||||
|
(Nocturn 2 only) put the Nocturn 3 reading ahead of the Nocturn 2 reading in the pool — the two
|
||||||
|
sources were being concatenated in `nocturnReadingIds` set order, not grouped by each reading's
|
||||||
|
own `nocturn` tag, so `distributeIntoNocturns`'s front-light positional slotting (1st pool
|
||||||
|
reading -> Nocturn 1, 2nd -> Nocturn 2, rest -> Nocturn 3) put the Nocturn-3-tagged reading into
|
||||||
|
the Nocturn 2 slot and vice versa. Confirmed live on the date that surfaced the whole month-week
|
||||||
|
gap in the first place (2026-08-23, `post-pentecost-13` + `month-week-084`): St. Gregory's
|
||||||
|
Moralia commentary (tagged `nocturn: 2`) was showing up after St. Augustine's homily (tagged
|
||||||
|
`nocturn: 3`) instead of before it. Fixed in `buildReadingPool` (`hours/matins.ts`) by bucketing
|
||||||
|
every contributing id's readings by `reading.nocturn` and emitting the buckets in ascending
|
||||||
|
numeric order — not hardcoded to `[2, 3]`, since Ember days' own nocturn-readings files use
|
||||||
|
`nocturn: 1` for their single-nocturn structure, and an initial `[2, 3]`-only version of this
|
||||||
|
fix silently dropped those (caught by `tests/calendar/ember-days.test.ts` failing). Within each
|
||||||
|
bucket, id order (and each file's own reading order) is preserved, matching this pool's usual
|
||||||
|
priority rule. `npm test` green at 460 tests — no fixture changes needed, since every
|
||||||
|
previously-authored id's own file already had its readings correctly ordered internally; only
|
||||||
|
the cross-source case this pass introduced was actually broken.
|
||||||
|
|
||||||
### Pre-1955-but-post-1617 saints' Matins readings — done (2026-08)
|
### Pre-1955-but-post-1617 saints' Matins readings — done (2026-08)
|
||||||
|
|
||||||
Resolved the former "mechanism gap" above into a concrete, scoped content pass — no new
|
Resolved the former "mechanism gap" above into a concrete, scoped content pass — no new
|
||||||
|
|||||||
+19
-2
@@ -394,11 +394,28 @@ function buildReadingPool(day: LiturgicalDay, temporalId: string, date: string):
|
|||||||
responsory: r.responsory ? { text: r.responsory, status: { la: 'verified', en: 'verified' } } : undefined,
|
responsory: r.responsory ? { text: r.responsory, status: { la: 'verified', en: 'verified' } } : undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (const id of nocturnReadingIds(day, temporalId, date)) {
|
// Grouped by the reading's own `nocturn` tag (ascending), not by which id
|
||||||
|
// contributed it — a later post-Pentecost Sunday's Nocturn 2 now comes
|
||||||
|
// from a different source (the month-week id) than its Nocturn 3 (its own
|
||||||
|
// temporalId file), and pooling in plain id order would put that Nocturn
|
||||||
|
// 3 content ahead of the Nocturn 2 content supplied by a later-processed
|
||||||
|
// id. Within each nocturn-number group, id order (and each file's own
|
||||||
|
// reading order) is preserved, matching this pool's usual priority rule.
|
||||||
|
// Not hardcoded to [2, 3]: Ember days' own nocturn-readings files use
|
||||||
|
// `nocturn: 1` (their single-nocturn structure), so every tag present
|
||||||
|
// must be handled, not just the usual Sunday/feast pair.
|
||||||
|
const ids = nocturnReadingIds(day, temporalId, date);
|
||||||
|
const byNocturn = new Map<number, ResolvedPart[]>();
|
||||||
|
for (const id of ids) {
|
||||||
for (const reading of getNocturnReadings(id)) {
|
for (const reading of getNocturnReadings(id)) {
|
||||||
parts.push(nocturnReadingPart(reading));
|
const bucket = byNocturn.get(reading.nocturn) ?? [];
|
||||||
|
bucket.push(nocturnReadingPart(reading));
|
||||||
|
byNocturn.set(reading.nocturn, bucket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const nocturnNumber of [...byNocturn.keys()].sort((a, b) => a - b)) {
|
||||||
|
parts.push(...byNocturn.get(nocturnNumber)!);
|
||||||
|
}
|
||||||
for (const octave of activeOctavesFor(date)) {
|
for (const octave of activeOctavesFor(date)) {
|
||||||
const reading = getOctaveReading(octave.id, octave.dayNumber);
|
const reading = getOctaveReading(octave.id, octave.dayNumber);
|
||||||
if (reading) {
|
if (reading) {
|
||||||
|
|||||||
Reference in New Issue
Block a user