feat: Novus Ordo Ordinary Time engine + edition-selected temporal cycle (#258) #480

Merged
manlycucumber merged 1 commit from feature/258-ordinary-time into develop 2026-07-11 04:13:20 +00:00
manlycucumber commented 2026-07-11 04:12:06 +00:00 (Migrated from github.com)

Builds the Ordinary-Form Ordinary Time temporal engine (#258) and makes the resolver's temporal fill edition-selected, without moving the frozen 1962/1954/1955 corpus.

What lands

  • OrdinaryTime filler — the two green blocks under one 1–34 week series. Block I counts forward from the Baptism of the Lord (its own week is 1; the first minted Sunday is the Second, since the Baptism occupies the first-Sunday slot); Block II counts backward from Christ the King (always the 34th Sunday, = the Sunday before Advent I). So the last Sunday before Advent is always the 34th and a 33-week year omits exactly one week (the week after Block I). Minted from the edition's ot-sunday / ot-feria temporal archetypes; reuses the shared PaschalSkeleton unchanged — the Easter arithmetic is edition-invariant, so the NO needs no new anchors and no PaschalSkeleton global is touched.
  • Edition-selected temporal cycleTemporalCycle / YearTemporalCycle strategy. DayResolver::resolveYear now sources its fillers and Triduum window from a cycle keyed off the RubricSystem (next to rulesFor). TraditionalTemporalCycle reproduces the historic filler list exactly (1962/1954/1955 byte-identical); NovusOrdoTemporalCycle carries OrdinaryTime.
  • AnchorFamily::ORDINARY_TIME (additive) so OT slugs parse; TemporalCalendar::addDays made signed (byte-identical for the forward-only traditional callers).

Safety / scope

  • 1962 golden fixture byte-identical (1055 tests, 144k assertions green); corpus verify OK — 32 files (corpus untouched — no generator/facts change).
  • The Novus Ordo edition stays isBuilt=false and is refused at the public boundary; the filler is exercised by its own tests against a minimal temporal fixture corpus.
  • Deferred to the general-calendar corpus slice (#108): the per-edition temporal-skeleton.yaml generator addition (OT expresses its seasons in the filler, needs no new offsets) and the remaining NO season fillers (Advent / Christmas Time / Lent / Holy Week / Easter Time) with their cited archetypes — that slice confronts the born-cited / public-domain naming gate holistically. Full oracle sweep is #260. Recorded in docs/design/novus-ordo-calendar-model.md (Implementation sequencing).

Verification

  • Local gate green: lint (0), PHPStan ([OK]), 1055 PHPUnit tests, Node generator tests, corpus verify.
  • OrdinaryTime week arithmetic adversarially reviewed: independent recomputation across all 618 years (1583–2200) — weeks always ∈ 1..34, Christ the King always 34th, no cross-block double-assignment/overlap, gap always 0 or 1 at exactly maxBlockI+1 — and the resume week cross-checked against USCCB/romcal for 2023–2027 (2024→wk 7 continuous; 2025→wk 10, week 9 omitted). No bugs found.
Builds the Ordinary-Form **Ordinary Time** temporal engine (#258) and makes the resolver's temporal fill **edition-selected**, without moving the frozen 1962/1954/1955 corpus. ## What lands - **`OrdinaryTime` filler** — the two green blocks under one 1–34 week series. Block I counts **forward from the Baptism of the Lord** (its own week is 1; the first minted Sunday is the *Second*, since the Baptism occupies the first-Sunday slot); Block II counts **backward from Christ the King** (always the 34th Sunday, = the Sunday before Advent I). So the last Sunday before Advent is always the 34th and a **33-week year omits exactly one week** (the week after Block I). Minted from the edition's `ot-sunday` / `ot-feria` temporal archetypes; **reuses the shared `PaschalSkeleton` unchanged** — the Easter arithmetic is edition-invariant, so the NO needs no new anchors and no `PaschalSkeleton` global is touched. - **Edition-selected temporal cycle** — `TemporalCycle` / `YearTemporalCycle` strategy. `DayResolver::resolveYear` now sources its fillers and Triduum window from a cycle keyed off the `RubricSystem` (next to `rulesFor`). `TraditionalTemporalCycle` reproduces the historic filler list **exactly** (1962/1954/1955 byte-identical); `NovusOrdoTemporalCycle` carries `OrdinaryTime`. - **`AnchorFamily::ORDINARY_TIME`** (additive) so OT slugs parse; **`TemporalCalendar::addDays` made signed** (byte-identical for the forward-only traditional callers). ## Safety / scope - **1962 golden fixture byte-identical** (1055 tests, 144k assertions green); `corpus verify OK — 32 files` (corpus untouched — no generator/facts change). - The Novus Ordo edition stays **`isBuilt=false`** and is refused at the public boundary; the filler is exercised by its own tests against a **minimal temporal fixture corpus**. - **Deferred to the general-calendar corpus slice (#108):** the per-edition `temporal-skeleton.yaml` generator addition (OT expresses its seasons in the filler, needs no new offsets) and the remaining NO season fillers (Advent / Christmas Time / Lent / Holy Week / Easter Time) with their **cited** archetypes — that slice confronts the born-cited / public-domain naming gate holistically. Full oracle sweep is **#260**. Recorded in `docs/design/novus-ordo-calendar-model.md` (Implementation sequencing). ## Verification - Local gate green: lint (0), PHPStan (`[OK]`), 1055 PHPUnit tests, Node generator tests, corpus verify. - OrdinaryTime week arithmetic **adversarially reviewed**: independent recomputation across all 618 years (1583–2200) — weeks always ∈ 1..34, Christ the King always 34th, no cross-block double-assignment/overlap, gap always 0 or 1 at exactly `maxBlockI+1` — and the resume week cross-checked against USCCB/romcal for 2023–2027 (2024→wk 7 continuous; 2025→wk 10, week 9 omitted). No bugs found.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Directorium/Core!480
No description provided.