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
+41
View File
@@ -0,0 +1,41 @@
import type { HourId, ResolvedOrdo } from './types';
import { HOUR_IDS } from './types';
import * as prime from './prime';
import * as compline from './compline';
import * as terce from './terce';
import * as sext from './sext';
import * as none from './none';
import * as lauds from './lauds';
import * as vespers from './vespers';
import * as matins from './matins';
type Resolver = (date: string) => ResolvedOrdo;
// Uniform on purpose — even though terce/sext/none are structurally
// identical, callers never branch on which hour they're asking for.
const registry: Record<HourId, Resolver> = {
prime: prime.resolveOrdo,
compline: compline.resolveOrdo,
terce: terce.resolveOrdo,
sext: sext.resolveOrdo,
none: none.resolveOrdo,
lauds: lauds.resolveOrdo,
vespers: vespers.resolveOrdo,
matins: matins.resolveOrdo,
};
export function resolveOrdo(hourId: HourId, date: string): ResolvedOrdo {
return registry[hourId](date);
}
export { HOUR_IDS };
export type {
HourId,
HourDefinition,
HourPart,
ResolvedOrdo,
ResolvedPart,
ResolvedText,
ResolvedVerse,
PropersRef,
} from './types';