Living Word — Live-Ops Phase 1A
What shipped
The Phase 1A slice of knowledge/acceptance/living-word-liveops-phase1.md §12:
-
Server-side liturgical calendar engine —
src/lib/living-word/calendar.tscomputeWesternEaster(year)implements the Anonymous Gregorian Algorithm (Computus); deterministic, no external library.resolveActiveEvent(date, traditionLensId?)returns the single active event (with specificity-based overlap resolution) plus the next 3 upcoming events.- Hand-verified for Easter dates 2025-2035 (48 unit tests, all green).
-
Three-feast default ON for every player — Christmas (Dec 25 - Jan 5), Easter Sunday + Eastertide (50 days), Pentecost. All universal scope — visible regardless of tradition lens.
-
Lens-gated full Western calendar — Advent, Lent, Christ the King surface only when the player's lens is Catholic (7), Lutheran (6), Methodist / Wesleyan (5), Anglican (13), or Eastern Orthodox (11). The gated lens set is encoded as
WESTERN_LITURGICAL_LENS_IDSand asserted in the test suite to guard against silent drift. -
HUD chip —
CalendarEventChip.tsxsits beside the existingFiveActsHudChipin the top-left HUD. Hidden when no event is active or the player has opted out. Click opens the modal. -
CalendarEventModal — narrator-voice copy for each of the 8 seasons. Tradition-neutral by default. Shows event name, date range, scripture anchor, contemplative paragraph, next-3 upcoming events, opt-out link.
-
Per-event opt-out — new table
lw_player_calendar_prefs(RLS; player-owned). Supports exact event-id opt-out (christmas-2026) or wildcard family opt-out (christmas-*). API at/api/living-word/calendar-prefs. -
Voice-rule lint —
scripts/living-word/voice-rule-check.mjsgrepssrc/app/living-word/+src/lib/living-word/for the banned root "evolv". Exits non-zero on match. Currently clean across all Living Word surfaces. -
Full Phase 1 schema migration —
2026-05-24-lw-events-and-streaks.sqlcreated all four tables in one shot per spec §12 (avoids a second migration when Phase 1B + 1C land):lw_player_calendar_prefs(used today)lw_player_streaks(Phase 1B will wire)lw_streak_events(Phase 1B will wire)lw_event_completions(Phase 1C will wire)
Deferred (per spec)
- Phase 1B — streak telemetry foundation. The schema is in place; the
StreakDisplayUI extension and/api/living-word/streaks/*endpoints are the next slice. - Phase 1C — Holy Week six-scene event. Blocked on founder content authoring (per the handoff doc, Phase C).
- Eastern Orthodox calendar (Phase 2). Phase 1A's Orthodox lens reads the Western calendar with a flagged TODO; Pascha (Julian) math lands in Phase 2.
- Push notifications of any kind. Phase 3 minimum.
Verification evidence
- Unit tests. 48 tests in
src/lib/living-word/__tests__/calendar.test.ts, all passing. Covers Computus correctness 2025-2035, First Sunday of Advent + Christ the King, three-feast lens-blind surfacing, lens-gating on Ash Wednesday + Advent + Christ the King, overlap resolution (Easter > Eastertide; Pentecost > Eastertide; Lent during ordinary days for Catholic lens), upcoming-list cardinality + ordering, pattern matching. - Playwright spec. 26 tests in
e2e/living-word/liveops-phase1a.spec.ts, all passing on a freshly deployed dev server. Verifies the API contract for every Western-liturgical lens + the chip/modal browser flow + 401 auth boundary on opt-out endpoint. - Voice-rule lint. Clean across all Living Word source surfaces.
- Build.
pnpm buildcompiles successfully.
Founder follow-ups (per spec §15 + handoff §3)
- Apply the migration (already applied via Supabase MCP on 2026-05-24).
- Personally approve all calendar event modal copy (8 seasons of narrator
paragraphs) — see
src/app/living-word/components/CalendarEventModal.tsxEVENT_COPYobject. - Pre-commit to streaks-default rule for Phase 1B (recommendation: ON with prominent opt-out).
- Pre-commit to Phase 1C slip-date decision rule (Triduum fallback vs. hold for 2028) by mid-January 2027.
Operational notes
- The
/api/living-word/events/activeendpoint accepts optional?date=YYYY-MM-DDand?lensId=Nquery params. Anonymous players hit it without auth and see universal feasts only. Authenticated players additionally have theirlw_player_calendar_prefsopt-outs applied. - The chip also supports
?lwTestDate=YYYY-MM-DDand?lwTestLens=NURL parameters on/living-worditself — used by Playwright to mock any liturgical date + lens combination without authenticating or mutating server state. In production these params are harmless. - Per-event opt-out persists across sessions via
lw_player_calendar_prefs(authenticated) only. Phase 2 will add anonymous opt-out via localStorage.