feat(office): assemble the office-structure tree into the day office key (Stage 3) #502
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!502
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/stage3-office-assembler"
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?
Stage 3 of the v1.2 Office/text layer: the DO-format resolver + PHP bilingual assembler that resolve the Stage-1 office-structure tree into the day-level
officekey (office-text-layer.md §4/§5; #100/#102/#104/#105/#106).Provable zero-axis-movement. No office is seeded in the base 1962 corpus, so the
officekey stays null on every day andgoldenDigest/corpusContentDigest/corpusVersion/engineVersionare all UNMOVED (the lock file is byte-identical; both freezes zero-diff on the workspace). Stage 4 (LOBVM) is the first digest-mover.What lands — 10 new internal
src/Office/classes:OfficePartPathResolver(#100/#102),OfficeAssembler(#104/#105), theOfficeTextProviderseam +CorpusOfficeTextProvider, and theTextLeaf/Availability/AssembledPart/AssembledOfficevalue objects. Wired intoDayResolver/LiturgicalDay/DayContractmirroring the fasting axis (#106). Per-string provenance is structural (no leaf without source+rights, no part without a Latin leaf, no full leaf without a value → withhold-never-leak). The office block + part-node shapes get their ownContractShapeTestpin (§5.2); the 16a withhold path is exercised end-to-end.Deferred to Stage 4 (data, not machinery): the per-office proper-text store and the date-driven seasonal-form selection.
Validation —
composer checkGREEN (phpcs + phpstan + 1237 phpunit / 145,799 assertions / 1 skip); bothfreeze-*scripts zero-diff; api-surface re-frozen additively forLiturgicalDay::office(). Adversarial 4-lens review (clean-room/provenance, byte-stability, correctness, spec-honesty): 0 confirmed findings; two low docblock-precision claims tightened.Build the office resolver + bilingual text assembler that resolve the Stage-1 office-structure tree into the day-level `office` key (office-text-layer.md §4/§5, #100/#102/#104/#105/#106). No office is seeded in the base 1962 corpus, so the key stays null on every day and the golden digest is UNMOVED — a provable zero-axis change; Stage 4 (LOBVM) is the first digest-mover. New engine classes under src/Office/ (internal, like the Stage-1 office VOs): - OfficePartPathResolver (#100/#102) mints one OfficePartPath per part from the office identity — bare for a singleton (hour, part-type), #n-ordinalled for repeats; DO section keys stay interop aliases only. - OfficeAssembler (#104/#105) walks the structure in order and fills each part bilingually via an OfficeTextProvider, dispatching psalter -> psalm stream, scripture -> canticle stream, else the proper textRef / minted path. - CorpusOfficeTextProvider expands ps:<n>[:v[-v]] / <book>:<ch>[:v[-v]] from the Stage-2 streams, each locale joined from its own edition so the psalter #114 divergence never misaligns them. - TextLeaf / Availability / AssembledPart / AssembledOffice value objects: the frozen §4.1 leaf {value|incipit, availability, source, rights}. Provenance is structural — no leaf without source+rights, no part without a Latin leaf, no full leaf without a value — so a missing/unlicensed source can only WITHHOLD, never leak. Wiring (#106) mirrors the fasting axis: OfficeResolver is built in DayResolver::forEdition, its resolve() result is a new LiturgicalDay ctor arg, and DayContract reads $day->office()?->toArray() in place of the null literal. The office is decided purely by the edition-declares gate (StructureAttributes::has), never by the occurrence arrays (§3.4). The office block + part-node shapes get their own ContractShapeTest pin (§5.2); the withhold path (16a) is exercised end-to-end. Deferred to Stage 4 (data, not machinery): the per-office proper-text store and the date-driven seasonal-form selection. api-surface re-frozen for LiturgicalDay::office().Stage 3: resolve the office-structure tree into the day office key via a bilingual assemblerto feat(office): assemble the office-structure tree into the day office key (Stage 3)