From e5cbc662227de4f3ab0089fe73f639f4f84601a4 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 26 Aug 2026 14:28:50 +0200 Subject: fix(citation): make the well-formed reading-part set rite-supplied I7 (final-review.md, 2026-08-25-colitur-of-phases-3-5): OF Sundays and solemnities shipped without the Second reading, and the lectionary data header called the First reading an "Epistle" -- EF vocabulary. The sole blocker was Validate's own kernel-hardcoded assertion that a well-formed day's sorted citation parts are exactly [First; Gospel]; Citation.part already carried Second. Rite.t gains citation_shapes : Citation.part list list, the fourth EF-shaped kernel misfit (after Preface.t, Mass_formulary.source, transfer_target's strictly-later contract) and the first fixed rather than only documented. EF supplies its one shape unchanged; OF supplies two, [First; Gospel] on a feria/feast/memorial and [First; Second; Gospel] on a Sunday or solemnity (OLM 1981 Praenotanda n. 66.1 vs n. 69.1, n. 84(b)/(c), page-image verified against olm-1981.pdf). Validate's "citations" check now matches against the rite's own declared shapes rather than a single literal pattern, preserving all three invariants it always enforced: zero or one complete shape, never partial; no part outside what the rite declares; no part repeated. bootstrap_lectionary_of.ml's cite now extracts a Second reading from Sunday-cycle ini sections only, correctly excluding the one stray `second` field lectio's snapshot carries on a weekday-cycle section (a content-verified scraping artifact). The hand-authored Christmas Day entry gains its own Second reading from the same OLM passage already cited for its First/Gospel. Regenerated data/of/lectionary.sexp: 771 entries unchanged, citation fields 1542 -> 1725 (+183, all Second readings), SHA-256 re-pinned, header wording fixed and a new coverage bullet added. Responsorial Psalm is deliberately still not emitted -- OLM 1981 Praenotanda n. 71 itself lists it apart from the readings proper as a chant with its own refrain, and the finding driving this change names only the missing Second reading. EF output verified byte-identical to the branch start (empty lib/rites/rite_ef + data/ef diff since v1.0.0, plus a direct binary comparison of `day`/`readings` for 2026, 1583 and 9999 against a worktree build of the pre-change commit). Tests: three new fixtures in test_validate.ml prove the generalisation holds both directions (a multi-shape rite accepts either of its declared shapes; a rite that never declared a shape still rejects it). test_citation_coverage_of.ml's pinned residual grows 41 -> 49, all new entries the same already-understood chapter-crossing shape. --- test/test_lectionary_of.ml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'test/test_lectionary_of.ml') diff --git a/test/test_lectionary_of.ml b/test/test_lectionary_of.ml index 03aaea5..706ee15 100644 --- a/test/test_lectionary_of.ml +++ b/test/test_lectionary_of.ml @@ -183,9 +183,17 @@ let test_sha256_pinned () = the Christmas Day Mass hand-authored from OLM 1981; see test_coverage_2026's own citation), not header-only as the I2 change just above was. Re-derived with `sha256sum data/of/lectionary.sexp`, - same discipline. *) + same discipline. + + Fix wave I7 (final-review.md, 2026-08-25-colitur-of-phases-3-5, + 2026-08-26): changed again -- {!Colitur_kernel.Rite.t.citation_shapes} + (kernel change) plus tools/bootstrap_lectionary_of.ml's own [cite] now + also extract a Second reading on every Sunday-cycle entry (183 new + citation fields; see data/of/lectionary.sexp's own header COVERAGE (5) + and test_citation_coverage_of.ml), and the header's "Epistle" wording + is fixed to "First". Re-derived the same way, same discipline. *) Alcotest.(check string) "data/of/lectionary.sexp SHA-256" - "e08207614472955974b504bfe6984ff44e882c4d8fadc778c4fa1ddce1adecf8" (sha256_of_file lectionary_path) + "0d82069e879d8312943dee543aabc23208265534fcf7edd85c3d9137c2f4581d" (sha256_of_file lectionary_path) (* lectio's OWN of-lectionary.ini SHA-256, pinned inside data/of/ lectionary.sexp's own provenance header (tools/bootstrap_lectionary_of -- cgit v1.3