feat: 1954 sanctoral octave subsystem (safer split) (#65) #449

Merged
manlycucumber merged 1 commit from feature/65-octave-subsystem into develop 2026-07-04 14:43:44 +00:00
manlycucumber commented 2026-07-04 14:42:17 +00:00 (Migrated from github.com)

Closes #65. Materialises the pre-1955 (Divino Afflatu) sanctoral octaves for the 1954 edition — the safer-split design (user-approved 2026-07-04): a sanctoral octave is a fixed-date, feast-anchored window that behaves exactly like a vigil, so it is pure DATA, not a runtime engine. Temporal octaves (Christmas/Easter/Pentecost) stay in the temporal fillers, untouched.

What it does

  • facts/octaves.yaml (per edition) → the generator's transformOctaves expands each entry into full identity / attributes / placement records. A common octave yields its six days within (dies secunda..septima, semidouble) + the octave day (dies octava, greater double); a simple octave yields the octave day only (simple), no days within.
  • Everything derived, nothing authored twice: the octave's date (day-offset, with month/year rollover) and colour come from the bearing feast; its numeric rank is derived from the office-grade (semiduplex/duplex-maius→III, simplex→IV), exactly as a feast's rank is (#448). octaves.yaml authors only class + Latin genitive + two cites.
  • octaveOf plumbing threads through the engine mirroring vigilOf (SanctoralEntry/SanctoralObservance incl. equals(), CorpusSanctoralData, SanctoralCalendar, RerankOperation, CorpusOverlayData, DayContract's reserved slot).

Guarantees

  • 1960/1962 edition dir is byte-identical (git-diff empty) and the 1583–2200 golden fixture is unmoved — protected by construction (temporal fillers untouched; octaves have no 1960 placement).
  • Octave identities join the shared identity as the cross-edition union of observances; each edition selects what it observes via its own placement. (CorpusTest invariant updated to per-edition referential integrity.)
  • No new corpus schema — the identity schema already reserved within-octave/octave-day; the only schema change is an additive octaveOf on placement.sanctorale.

Octave facts — research-verified (adversarially)

Feast Octave Authored
John Baptist (Jun 24) · Peter & Paul (Jun 29) Common Full (within-days + octave day)
Lawrence (Aug 10) Simple Octave day (Aug 17 — survives as commemoration)
Assumption (Aug 15) Common Within-days (Aug 16–21) only
St Joseph (Mar 19) None (the octave belonged to the moveable Solemnity, abolished 1955)

Deferred to #64/#67 (office displaced; commemoration-survival unconfirmed — held to the 100%-accuracy bar): the Assumption octave day (Aug 22, occupied by the Immaculate Heart) and the whole Nativity-BVM octave (Sep 15, replaced by the Seven Sorrows). Adding those feasts + the precedence/commemoration rules is #64/#67.

An adversarial 4-dimension review (data accuracy · plumbing · generator · regression) + a verification pass found one must-fix — the John Baptist octave title needed "Nativitatis" (distinguishing it from the Decollation; every other bearer keeps its full descriptor) — now applied, plus its recommended hardening (the CorpusOverlayData octaveOf symmetry and three fail-closed generator guards).

Gates

phpcs · phpstan L6 · phpunit (728) · npm test (18, incl. OctaveEditionTest + generator unit tests) · npm run verify (16 files reproducible) · validate-oracles — all green.

Closes #65. Materialises the pre-1955 (Divino Afflatu) **sanctoral octaves** for the 1954 edition — the **safer-split** design (user-approved 2026-07-04): a sanctoral octave is a fixed-date, feast-anchored window that behaves exactly like a **vigil**, so it is pure **DATA**, not a runtime engine. Temporal octaves (Christmas/Easter/Pentecost) stay in the temporal fillers, untouched. ## What it does - **`facts/octaves.yaml`** (per edition) → the generator's **`transformOctaves`** expands each entry into full identity / attributes / placement records. A **common** octave yields its six days within (*dies secunda..septima*, semidouble) + the octave day (*dies octava*, greater double); a **simple** octave yields the octave day only (simple), no days within. - **Everything derived, nothing authored twice**: the octave's **date** (day-offset, with month/year rollover) and **colour** come from the bearing feast; its numeric **rank** is derived from the office-grade (`semiduplex`/`duplex-maius`→III, `simplex`→IV), exactly as a feast's rank is (#448). `octaves.yaml` authors only *class + Latin genitive + two cites*. - **`octaveOf` plumbing** threads through the engine mirroring `vigilOf` (`SanctoralEntry`/`SanctoralObservance` incl. `equals()`, `CorpusSanctoralData`, `SanctoralCalendar`, `RerankOperation`, `CorpusOverlayData`, `DayContract`'s reserved slot). ## Guarantees - **1960/1962 edition dir is byte-identical** (git-diff empty) and the **1583–2200 golden fixture is unmoved** — protected *by construction* (temporal fillers untouched; octaves have no 1960 placement). - Octave identities join the shared identity as the **cross-edition union** of observances; each edition selects what it observes via its own placement. (`CorpusTest` invariant updated to per-edition referential integrity.) - No new corpus schema — the identity schema already reserved `within-octave`/`octave-day`; the only schema change is an additive `octaveOf` on `placement.sanctorale`. ## Octave facts — research-verified (adversarially) | Feast | Octave | Authored | |---|---|---| | John Baptist (Jun 24) · Peter & Paul (Jun 29) | Common | Full (within-days + octave day) | | Lawrence (Aug 10) | Simple | Octave day (Aug 17 — survives as commemoration) | | Assumption (Aug 15) | Common | Within-days (Aug 16–21) only | | **St Joseph (Mar 19)** | — | **None** (the octave belonged to the *moveable* Solemnity, abolished 1955) | **Deferred to #64/#67** (office displaced; commemoration-survival unconfirmed — held to the 100%-accuracy bar): the **Assumption octave day** (Aug 22, occupied by the Immaculate Heart) and the whole **Nativity-BVM octave** (Sep 15, replaced by the Seven Sorrows). Adding those feasts + the precedence/commemoration rules is #64/#67. An adversarial 4-dimension review (data accuracy · plumbing · generator · regression) + a verification pass found **one** must-fix — the John Baptist octave title needed *"Nativitatis"* (distinguishing it from the Decollation; every other bearer keeps its full descriptor) — now applied, plus its recommended hardening (the `CorpusOverlayData` `octaveOf` symmetry and three fail-closed generator guards). ## Gates phpcs · phpstan L6 · phpunit (728) · `npm test` (18, incl. `OctaveEditionTest` + generator unit tests) · `npm run verify` (16 files reproducible) · validate-oracles — all green.
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!449
No description provided.