feat: serialise the resolved day to the versioned output contract (#53) #354
No reviewers
Labels
No labels
area: build
area: ci
area: compare
area: data
area: engine
area: model
area: provenance
area: rite
area: validation
backport
blocked
breaking
confirmed
dependencies
duplicate
epic
github_actions
invalid
needs-info
needs-triage
php
priority: high
priority: low
priority: medium
regression
type: bug
type: chore
type: correction
type: docs
type: enhancement
type: feature
type: fix
type: perf
type: refactor
type: security
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Directorium/Core!354
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/53-output-contract-serialiser"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #53.
Adds the public output contract the Api/Site/Ordo repos build on: a new
Introibo\Core\Contractnamespace that serialises a resolvedLiturgicalDayto a versioned, deterministic, JSON-ready structure.LiturgicalDaystays a pure aggregate; the serialiser is the seam.What's here
Contract\DayContract— frozenSHAPE_VERSION = 1.0.0;from(LiturgicalDay, Provenance)→toArray()/toJson()(flagsJSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR). Offices are serialised via aninstanceofbranch (temporal vs sanctoral) so the shape is uniform.Contract\Provenance— the three independent version axes:edition(roman:rubricae-1960),corpusVersion(1962-seed),engineVersion(Introibo::VERSION).Introibo\Core\contract(DateTimeImmutable): array— the public entry point besideday(), sharing one memoised year resolver.Introibo::VERSIONandResolvedYear::provenance()added.Resolver ripple (offices become self-describing)
RoledObservancenow also carries theOccurrenceOutcomeand thetransferredTo/transferredFromdates.LiturgicalDayholds roled offices; the bare-observance accessors (celebration()etc.) are retained, so every existing reader is unaffected.DayResolverstamps outcomes inassemble()and links every transfer end-to-end in a reconciliation pass. The links follow each feast's hop chain across the year rather than a single impeded/landing pair, so a re-transfer cascade or a feast celebrated on its own date link correctly (hardened after an adversarial review of the reconciliation).Shape (per the frozen contract spec)
Day:
contractVersion·corpusVersion·engineVersion·rite·edition·date·season·commemorationLimit·celebration/commemoration/displaced/tempora(office lists) ·secondVespers(object) · reservedfirstVespers/resolution/fasting/calendar.Office:
id·urn·role·kind·rank/rankOrdinal·season·colour{base,roseAllowed}·names{la}·titulars·outcome·transferredTo/transferredFrom·vigilOf· reservedoctaveOf/aliases/citations/text/chant/audio.Tests & docs
docs/design/output-contract.mddocuments the shape, the three-version scheme, id-vs-urn, transfer links, and reserved slots (bump-rules and worked examples expand in #58).Local gate:
composer lint(0),composer analyse([OK]),composer test(479 tests / 30,360 assertions).