Author Benedictus antiphon + P/T/S/N Commons for 66 propers:null saints
Deploy / deploy (push) Successful in 56s
Deploy / deploy (push) Successful in 56s
Continues the 94-saint batch this collects pass unblocked. Raw Commune/*.txt fields don't reliably match what the engine actually renders per hour -- same lesson as the collects pass, confirmed again: no CommuneM/*.txt file defines explicit per-hour antiphon fields for any category this batch needed, and the already-authored common-of-a-confessor-bishop content (from the original 29-saint pass) doesn't match Commune/C4.txt's own raw [Ant 1] either, since it was live-query-sourced rather than read from the file directly. Fixed by querying web/cgi-bin/horas/officium.pl directly (local Perl, not a network fetch) for one representative saint per Common category, with every representative's title verified against an accent-insensitive name-stem match before its content is trusted -- caught a stale-date bug this way: St. Emerentiana's stored clean-year comment actually rendered St. Hilary of Poitiers's office that year. Cross-querying multiple saints per nominal SaintRecord.common category found the real liturgical groupings are coarser (Martyr-Bishop and Martyr; Abbot, Confessor-not-Bishop, and Confessor; Virgin-Martyr, Virgin, and Holy Woman all render identical minor-hour text) but not uniformly so (Pope-Martyrs render distinct allelúja-toned text from plain Several-Martyrs; the Dedication of the Basilicas of Ss. Peter and Paul draws from the Dedication Common, not its nominal common-of-an-apostle at all). Net: 7 new shared Common categories plus the pre-existing common-of-a-confessor-bishop (which also needed a new Benedictus-antiphon file of its own) cover 66 of the 94 saints. New mechanism: SaintRecord.benedictusCommon, with getBenedictusAntiphon falling back to it the same way getDayCollect already falls back to collectCommon -- no name-substitution needed here, since every Common category in current use renders name-free Benedictus-antiphon text. Also fixes a real bug this surfaced: getMinorHourOverrideId gated all Prime/Terce/Sext/None lookup behind the same duplex-majus+ threshold Lauds' own psalmody override uses, on the assumption that only a strong feast carries its own minor-hour content -- live-querying proved that wrong (a winning Semiduplex saint still renders its own antiphons, not the ferial default). Lauds' psalmody override itself stays majus+-gated correctly, since it's a much bigger per-saint commitment this batch doesn't add a Common fallback for. Ss. Ursula and Companions deliberately left without a minor-hour Common: her collect template has no other calendar member to verify a shared text against, and she can never be queried directly (a genuinely unwinnable stub) -- left honestly unauthored rather than guessed. The other 26 of the 94 (own proper collect, from the collects batch) still need their own individually-authored Benedictus antiphon, same shape as the original 109-saint pass -- not done in this pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -272,6 +272,120 @@ all 94 ids via a synthetic sanctoral-winner day, confirming a real
|
||||
(non-`missing`, no leftover `{N}`) collect for every one — not just that
|
||||
the YAML files parse.
|
||||
|
||||
### 94 `propers: null` saints — Benedictus antiphon + P/T/S/N Commons (2026-08)
|
||||
|
||||
The natural next step the collects batch unblocked. Two more real gaps
|
||||
found and fixed along the way, both explained below.
|
||||
|
||||
**Raw `Commune/*.txt` fields don't reliably match what the engine
|
||||
actually renders per hour, same lesson as the collects pass but for
|
||||
antiphons this time.** `Commune/C2.txt`'s (Martyr-Bishop) own `[Ant 1]`/
|
||||
`[Ant 2]`/`[Ant 3]` fields don't correspond 1:1 to Prime/Terce/Sext/None
|
||||
the way a naive reading would suggest, and no `CommuneM/*.txt` file
|
||||
defines explicit `[Ant Prima]`/`[Ant Tertia]`/`[Ant Sexta]`/`[Ant Nona]`
|
||||
fields for any of the categories this batch needed (only `C10`, BVM
|
||||
Saturday, has them). Confirmed independently: the already-authored
|
||||
`common-of-a-confessor-bishop` P/T/S/N content (from the original
|
||||
29-saint pass) doesn't match `Commune/C4.txt`'s own raw `[Ant 1]` either
|
||||
— it was live-query-sourced from Chair of St. Peter/St. Martin's own
|
||||
rendered pages, not read from the Commune file directly, which is
|
||||
exactly why. Fix: queried `web/cgi-bin/horas/officium.pl` directly
|
||||
(local Perl, not a network fetch — `prayPrima`/`prayTertia`/`praySexta`/
|
||||
`prayNona`/`prayLaudes`, `version=Monastic Tridentinum 1617`) for one
|
||||
representative `propers: null` saint per Common category, parsing the
|
||||
antiphon (incipit + full, reconstructing the `*` split point) and
|
||||
chapter (citation, text, closing versicles) out of the rendered HTML —
|
||||
new scratchpad tool `query_hours.py`/`batch_hours.py`, not committed,
|
||||
same one-off-tool convention as the rest of this project's extraction
|
||||
scripts. Caught its own version of the collects batch's "wrong saint"
|
||||
bug this way too: St. Emerentiana's stored clean-year comment
|
||||
(2029-01-23) actually rendered St. Hilary of Poitiers's office by that
|
||||
year (a stale date after his own earlier Jan 23 → Jan 14 correction,
|
||||
see above) — every representative's title is now verified against an
|
||||
accent-insensitive name-stem match before its content is trusted, with a
|
||||
fallback year search when the stored date doesn't check out.
|
||||
|
||||
**The real liturgical categories are coarser than `SaintRecord.common`'s
|
||||
naming suggests — verified by cross-querying multiple saints per
|
||||
category, not assumed.** `common-of-a-martyr-bishop` and
|
||||
`common-of-a-martyr` render byte-identical P/T/S/N and Benedictus
|
||||
antiphon content (confirmed: St. Anacletus, St. Simeon, St. Blaise, St.
|
||||
Pantaleon — four different collect-template variants, one shared minor-
|
||||
hour Common); so do `common-of-an-abbot`, `common-of-a-confessor-not-
|
||||
bishop`, and `common-of-a-confessor` (St. Odo, St. John Gualbert, St.
|
||||
Nicholas of Tolentino, St. Alexius); so do `common-of-a-virgin-martyr`,
|
||||
`common-of-a-virgin`, and `common-of-a-holy-woman` (St. Justina, St.
|
||||
Emerentiana, St. Praxedes, St. Martha). `common-of-several-martyrs`
|
||||
splits further than its own name suggests, though: plain groups of
|
||||
martyrs (Ss. Cornelius and Cyprian, Ss. Faustinus and Jovita, Ss. Placid
|
||||
and Companions — the last a real Duplex II. classis feast, not just a
|
||||
low-rank stub, confirming the fallback isn't only reached by minor
|
||||
saints) share one Common, but groups of *Pope*-martyrs (Ss. Cletus and
|
||||
Marcellinus, Ss. Soter and Caius) render distinct, more triumphal,
|
||||
allelúja-toned text of their own — a real category the collect
|
||||
templates already knew about (`collect-c3b`) that the `common` field
|
||||
alone doesn't surface. One saint, the Dedication of the Basilicas of Ss.
|
||||
Peter and Paul, turned out *not* to share its `common` field's nominal
|
||||
category (`common-of-an-apostle`) at all: live-verified its P/T/S/N and
|
||||
Benedictus antiphon are the Dedication-of-a-Church Common instead (about
|
||||
the building, matching its own `collect-c8`), not shared with any
|
||||
apostle content. Net result: 7 new shared Common categories
|
||||
(`common-of-a-martyr`, `common-of-an-abbot`, `common-of-several-
|
||||
martyrs`, `common-of-pope-martyrs`, `common-of-a-vigil`, `common-of-a-
|
||||
virgin`, `common-of-a-dedication`) plus the pre-existing `common-of-a-
|
||||
confessor-bishop` cover 66 of the 94 saints; the 7th confessor-bishop
|
||||
saint's own Benedictus antiphon Common file was also new (the original
|
||||
29-saint pass never needed it — Chair of St. Peter/St. Martin both have
|
||||
their own proper Lauds antiphon, only their chapters were shared).
|
||||
|
||||
**New mechanism**: `SaintRecord.benedictusCommon` (`calendar/feasts.ts`)
|
||||
— `getBenedictusAntiphon` (`hours/resolve-common.ts`) now falls back to
|
||||
`benedictus-antiphon-${benedictusCommon}.yml` when a saint has neither a
|
||||
proper collect-antiphon pair nor... (see below) — deliberately no name-
|
||||
substitution mechanism built for it (unlike `collectCommon`): every
|
||||
Common category in current use renders name-free Benedictus-antiphon
|
||||
text; only the Doctor Common (`C4a`, not used by any saint here) has a
|
||||
`{N}`-shaped placeholder in the source.
|
||||
|
||||
**Real bug found and fixed while wiring this in**: `getMinorHourOverrideId`
|
||||
gated *all* Prime/Terce/Sext/None lookup — both the per-saint proper file
|
||||
and the shared-Common fallback — behind the same duplex-majus+ threshold
|
||||
Lauds' own *psalmody* override uses, on the assumption that only a
|
||||
strong feast carries its own minor-hour content at all. Live-querying
|
||||
this batch proved that wrong: a winning Semiduplex saint (St. Anacletus)
|
||||
still renders its own proper/Common antiphons at Prime/Terce/Sext/None,
|
||||
not the plain ferial default — the majus+ gate was only ever a proxy for
|
||||
"this app has authored proper content," not a real liturgical rule, and
|
||||
became actively wrong once Common-category content started covering
|
||||
lower ranks too. Fixed by making `getMinorHourOverrideId` eligible for
|
||||
*any* sanctoral winner; Lauds' own psalmody override
|
||||
(`hours/lauds.ts`'s `getPsalmodyOverrideFor`) is unaffected and correctly
|
||||
stays majus+-gated, since that's a real, much bigger per-saint authored
|
||||
commitment (the whole psalm-antiphon block), not something this batch
|
||||
adds a Common fallback for.
|
||||
|
||||
One saint, Ss. Ursula and Companions, deliberately left without
|
||||
`minorHoursCommon`/`benedictusCommon`: her collect template
|
||||
(`collect-c6b`, plural Virgins and Martyrs) has no other member on this
|
||||
app's calendar to verify a shared minor-hour text against, and she can
|
||||
never be queried directly herself (a genuinely unwinnable stub, always
|
||||
commemorated under St. Hilarion) — left honestly unauthored rather than
|
||||
guessed from the singular `common-of-a-virgin` category, moot in
|
||||
practice since a commemoration's own minor hours are never rendered.
|
||||
|
||||
Verified end-to-end: a runtime smoke test (folded into
|
||||
`tests/hours/resolve-common.test.ts`) resolving `getBenedictusAntiphon`/
|
||||
`resolveMinorHourAntiphon`/`resolveMinorHourChapter` for a sample across
|
||||
categories, including the Duplex II. classis case to confirm the
|
||||
majus+-gate fix isn't just a low-rank special case.
|
||||
|
||||
**Not done in this pass**: the other 26 of the 94 (`propers` now set to
|
||||
their own id, from the collects batch's proper-collect saints) still
|
||||
need their own individual Benedictus antiphon authored — same shape as
|
||||
the original 109-saint pass (own `[Ant 1]`/live-rendered text, not a
|
||||
shared Common), since a saint with a genuine proper collect usually has
|
||||
a genuine proper antiphon too. Not yet started.
|
||||
|
||||
### Christmas-Octave Sunday content — done (2026-08)
|
||||
|
||||
Was: only the Benedictus antiphon existed for `christmas-octave-sunday`
|
||||
@@ -608,8 +722,10 @@ correction (confirmed Roman-rite sourced), a handful already matched.
|
||||
(see the section above for method and its own correction).
|
||||
- **94 `propers: null` saints: done (2026-08)** — see the dedicated section
|
||||
below for the collect-authoring pass and the era-specific-calendar
|
||||
discovery it took to do reliably. Antiphons for these 94 (the natural
|
||||
next step this unblocks) not yet started.
|
||||
discovery it took to do reliably. Benedictus antiphon + P/T/S/N: done
|
||||
for the 66 that draw from a shared Common (own dedicated section
|
||||
below); the other 26 (own proper collect, from the same batch) still
|
||||
need their own individually-authored Benedictus antiphon, not started.
|
||||
|
||||
### Bug found and fixed while pulling christmas-octave-sunday's antiphon
|
||||
|
||||
|
||||
Reference in New Issue
Block a user