Milestone 0/1: shell, calendar/psalter/hours scaffold, Prime
Deploy / deploy (push) Failing after 1m8s

Client-side-first PWA (Vite/TS, no backend) per the approved plan: day-
navigable shell listing all 8 hours, Prime fully resolves via the
calendar -> psalter -> ordo pipeline, the other 7 hours are registered
but flagged not-implemented. Sanctoral/temporal calendar data uses a
day -> id indirection layer (saints, easter-offsets, fixed-date-calendar)
so reassigning a feast to a different day is a data edit, not a code
change. Docker (Caddy-serving-static) + Gitea CI workflow scaffolded to
match the eec/drip/bookshop operational pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 15:20:06 -04:00
commit a5dc6502d7
53 changed files with 8634 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
export type Weekday =
| 'sunday'
| 'monday'
| 'tuesday'
| 'wednesday'
| 'thursday'
| 'friday'
| 'saturday';
// Deliberately an open string, not a hardcoded union. Which temporal-id a
// given day resolves to — and what it's *called* ("trinitytide" vs "time
// after pentecost") — is a property of data/calendar/easter-offsets.yml and
// fixed-date-calendar.yml, not a compile-time decision. This is what
// actually resolves the "opinionated but configurable" tension: the opinion
// (trinitytide) lives in editable data, not in a TS enum you'd recompile to
// change.
export type Season = string;
// Open-ended on purpose — the actual ranking scheme (double/semidouble/simple,
// or whatever the finalized rank system turns out to be) is a rule decision for
// milestone 4, not a type decision for milestone 0.
export type FeastRank = string;
export interface OccurringFeast {
id: string;
name: string;
rank: FeastRank;
commemorated: boolean;
// Placeholder for the first/second-Vespers overlap wrinkle — unresolved until
// milestone 4 actually needs it.
vespersFrom?: 'today' | 'firstVespersOfTomorrow';
}
export interface LiturgicalDay {
/** ISO date, e.g. "2026-08-09" */
date: string;
weekday: Weekday;
/**
* Real season resolution depends on Easter's date (see calendar/easter.ts,
* not implemented until milestone 4). Until then this is a placeholder and
* must not be trusted by any hour's logic.
*/
season: Season;
/** Always [] until milestone 4 wires up calendar/feasts.ts. */
occurring: OccurringFeast[];
}