Prime: real content (psalms, Martyrology, Regula) and ordo corrections
Deploy / deploy (push) Failing after 21s

Pulls in verified content from Divinum Officium rather than placeholders:
17 psalms (2, 6, 7-19, 118, 129), 365 days of the Martyrology, and the full
121-reading Regula cycle, plus the Athanasian Creed.

Ordo corrections driven by review against the real engine output:
- Capitulum and Preces now pick a Sunday/feast vs. ferial form
  (calendar/isSundayOrFeast); ferial Preces said every ferial day by choice.
- Chapter responsory, hymn doxology, and the opening versicle's
  Alleluia/Laus tibi all vary by season via a shared resolver
  (hours/seasonal-propers.ts).
- Real Roman Kalends/Nones/Ides Latin dating (calendar/roman-date.ts,
  verified against 363/365 real Martyrology headings) plus the historical
  "bis sextus" Feb 29 handling, and the Martyrology's Luna (moon-day)
  heading (a ported Golden-Number calculation).
- Fixed responsory structure (was missing its initial full repeat),
  weekday psalm antiphons (opening as incipit-or-full by rank, full
  repeat after the psalms/Creed as its own part, "*" chant mark kept),
  scripture citations on the capitulum/lectio brevis, and V./R. markers
  switched from Unicode symbols to plain text for reliable font rendering.
- Dropped Pretiosa and the dead-commemoration psalm (129) for time;
  trimmed section headings down to the ones that are actually named
  things (Preces, Chapter Office, etc. no longer relabel connective text).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 20:03:53 -04:00
parent a5dc6502d7
commit 58958aa847
571 changed files with 21842 additions and 72 deletions
+42
View File
@@ -0,0 +1,42 @@
import type { OccurringFeast } from '../calendar/types';
export interface SplitAntiphon {
incipit: string;
full: string;
}
/**
* Antiphon text is stored as one string with an embedded "*" marking where
* the incipit (the "half antiphon") ends — the same convention Divinum
* Officium's own data uses, so no separate half/full fields are needed.
*
* The "*" is kept in `full` (by explicit choice — it's a meaningful chant
* mark, not just an incipit-boundary artifact, even though the reference
* engine's own rendering happens to strip it there).
*/
export function splitAntiphon(text: string): SplitAntiphon {
const starIndex = text.indexOf('*');
if (starIndex === -1) {
return { incipit: text, full: text };
}
const before = text.slice(0, starIndex).trim();
const after = text.slice(starIndex + 1).trim();
return { incipit: before.replace(/,$/, '.'), full: `${before} * ${after}` };
}
/**
* Real practice: the antiphon is said in full both before and after the
* psalms on a Double-rank feast or higher; below that, only the incipit is
* said before the psalms (the full text is always said after, regardless
* of rank).
*
* FeastRank is an open string with no defined hierarchy yet (see
* calendar/types.ts), and `occurring` is always [] until milestone 4 wires
* up real feast data — so this can only ever return false today. That's
* the *correct* answer for every day currently reachable (a plain ferial
* day is below Double), not a stub papering over missing logic; it starts
* doing real work the moment FeastRank has an ordering to compare against.
*/
export function isDoubleOrHigher(_occurring: OccurringFeast[]): boolean {
return false;
}