summaryrefslogtreecommitdiff
path: root/tools/bootstrap_lectionary.ml
Commit message (Collapse)AuthorAgeFilesLines
* fix(lectionary): the week after Trinity says its own assigned MassLukasz Kasprzak2026-08-171-1/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | RG 299 located (scan1:1096-1098), which does two things at once. First it closes a standing gap: the ferial-Mass selection rule was recorded in the register as unconfirmed against the primary source, and step 3 said so in its own comment -- "lectio's own observed behaviour, not a confirmed Missal citation". It is confirmed now. "In reliquis feriis dicitur Missa dominicae praecedentis, nisi a rubricis aliter provisum sit", restated in the propers as "...nisi propria Missa assignetur". Second, that escape clause splits M26 shape 2 in half, which is why the shape was never resolvable as one thing. Shape 2(a), the week after Trinity, is fixed. Trinity is the temporal identity of its own Sunday, so a plain walkback lands on Trinity's Mass -- but the Missal prints a named formula for the following week, "Missa dominicae I post Pentecosten" (scan1:21758), precisely because the feast has taken that Sunday's own. Those ferias now resolve at step 2 from it and never reach the walkback. Shape 2(b), Christ the King's week, turns out not to be a bug at all. No proper Mass is assigned there -- checked directly, no rubric precedes that Mass heading (scan1:39163ff) -- so RG 299's default governs and "the Mass of the preceding Sunday" genuinely is Christ the King's own, which is what colitur emits and missalemeum does not. Kept open only because no rubric specific to that week was located either way; the verdict is now argued from the primary text rather than resting on oracle disagreement. No Thursday in the slug list: Corpus Christi is Easter+60, which IS that week's Thursday every year, so the ferial slug never exists. Found by the bootstrap's own reachability guard refusing to emit a key no Temporal_ef slug can match, not reasoned out in advance. Allow-lists: C35 opened (69 rows, verdict colitur -- lectio still walks back); C17 narrowed 406 to 397, nine Saturdays moving to C35 because they carry both a citation and a colour difference, with C35 gated to require the citation so a colour-only Saturday still falls to C17; M26 narrowed 30 to 27; M18 widened 352 to 355, the same three days keeping only their observed-identity difference. Register: section 6.11.
* test(oracle): fix round 1 -- C30 disclosure, RG 17(a) misattribution, M26 shapesLukasz Kasprzak2026-08-171-38/+67
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Three Important findings from coordinator review of 8d1eb25, all fixed. 1. C30's own note claimed its 91-row population "is C25's OWN former population, before this task narrowed it" -- false. Independently re-derived against the real resolver (pre-fix vs post-fix binary) and the lectio fixture: only 44 of the 91 rows were ever in C25 (Wed 6/ Thu 19/Fri 19, matching C25's own fix-round-3 breakdown exactly); the other 47 (all of Monday/Tuesday, plus part of Wednesday/Friday) previously matched lectio outright -- both engines independently landing on the same wrong value -- and are newly allow-listed only because colitur is now right. Rewritten to the same "both engines silently agreed on the wrong answer" pattern C33/C34 already used. 2. "Diebus ferialibus" is not RG 17(a) -- RG 17(a) states only the day-identity privilege; the ferial-Mass rubrics are Mass-propers rubrics, a distinction the register's own §6.3 already drew before this task's first pass blurred it in code/allow-list comments. A further slip: C31/C32 called their own rubric "RG 17(a)'s own next/ third sentence" when it is a different rubric block ~230 lines away, in Holy Family's (not Holy Name's) own feast propers. Fixed the attribution chain throughout tools/bootstrap_lectionary.ml, data/ef/expected-divergences.sexp's C29-C34, and (gitignored, outside this commit) docs/research/rules-register.md -- closed the §6.3 park, added §6.5 recording all four citations with corrected attribution. Quotes and line numbers were already right; only the chain of custody to RG 17(a) was wrong. 3. M26's own 30 rows classify into two nameable shapes, not "three confirmed shapes" with an unexplained 23-row residue that was in fact empty: 21 rows are RG 78's own already-documented BVM votive-Mass gap; 9 rows are a second, distinct gap -- a week whose own Sunday was displaced by a movable named feast (Trinity->Corpus Christi, "Missa Dominicae I post Pentecosten"; Christ the King), where the Missal requires the displaced Sunday's own Mass to keep informing that week's ferias but step 3 walks back to the displacing feast's citation instead -- proven directly by colitur's own citation on the Christ- the-King rows being literally that feast's own Gospel. verdict open unchanged (not fixed here); the shape is now named instead of buried. Minors: section count corrected 1458->1456 (four places); "exactly one candidate, zero ambiguous" corrected to "correctness rests on ordering, not uniqueness" (2 of 1456 sections genuinely yield two candidates, Holy Saturday's own Lectio, both years); the stale "nothing in layers 3-5 compares citations" claim corrected (only layer 5 still doesn't); M18's note corrected (five new entries not six; ~18 of its remaining 352 rows only agree now because of this task's own fixes, not "already" before it); "five" corrected to "six" otherwise-unoccupied Saturdays in bootstrap_lectionary.ml; scan2 quotes softened where OCR-garbled. Also done outside the git-tracked files: the step-4 (Commons) coverage gap is now recorded in data/ef/expected-divergences-missalemeum.sexp's own header, not only the commit body and the (gitignored) report. dune test: 358 tests green. COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force: 359 tests green, 95.7s.
* test(oracle): compare reading citations against missalemeumLukasz Kasprzak2026-08-171-50/+198
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Layer 4 (test_oracle.ml) now extracts and compares the Epistle/Gospel citation for every one of the 730 days in the 2026-2027 fixture, the same axis Task 8 already added to layer 3. tools/ extract_missalemeum_oracle.py gained a structural citation-span detector (the first "*...*"-wrapped span under 40 chars containing a chapter:verse-shaped digit pair), verified exhaustively over all 1 458 Lectio/Evangelium sections. 728 of 730 days are comparable; the 2 that are not (Good Friday, both years) have no such section in missalemeum's own JSON at all -- a structural limit on the oracle's own side (M23), not a colitur gap. 451 of 730 days differ and are all explained across 19 cited entries; 0 unexplained. Chain step 4 (the Commons) has no layer-4 witness: confirmed empirically (a scratch sweep, not merely re-asserted from Task 6's own report) that none of the 15 Commons/proper saints is ever the observed office in this window. The comparison surfaced three genuine colitur bugs in data/ef/lectionary.sexp, all fixed at the source in tools/bootstrap_lectionary.ml: 1. Holy Name of Jesus (ef-holy-name-sunday/ef-holy-name) carried a mis-derived citation, borrowed by analogy from an unrelated ini section ("ef-christmas-sunday-0", the Sunday-within-the-Octave's own Mass) on the wrong assumption the two share a Mass. Disproved by missalemeum's own extraction for both real Holy Name Sundays in its window, confirmed against the Missal itself, twice, both scans (Acts 4:8-12/Luke 2:21, not Gal 4:1-7/Luke 2:33-40). 2. RG 17(a)'s own "diebus ferialibus" rubric (immediately following the Holy Name heading, both scans) was never implemented: 2-5 January ferias repeat 1 January's Mass, 7-12 January ferias before Holy Family Sunday repeat Epiphany's, and Holy Family's own week has a named formula ("Missa Dominicae Primae post Epiphaniam"). All three fell to step 3's undifferentiated Sunday walkback instead. Fixed for three 5-weekday families, deliberately excluding Saturday from all three -- RG 78's BVM Saturday Office wins there unconditionally, confirmed against missalemeum's own title on this window's own such Saturdays. 3. Corpus Christi and Sacred Heart (both real, never-impeded I-class movable feasts) had no lectionary entry at all. Both engines independently fell back to Trinity Sunday's own citation and silently agreed on the wrong answer -- the "Holy Thursday violet in both" shape CLAUDE.md names for exactly this reason. Because lectionary.sexp is shared with layer 3 (the lectio differential, 2005-2050), these fixes changed colitur's output for the whole domain, not only 2026-2027. data/ef/expected-divergences.sexp and test_differential.ml needed matching updates: C1 narrowed 361->173 and C25 narrowed 57->13 (rows that now resolve correctly moved to new entries), C16's note corrected (count unchanged), and six new entries added (C29-C34, 397 rows total, all verdict colitur). test_lectionary.ml and test_lectionary_ef.ml's own pins were updated to match (entry count 131->148; one step-3 regression test re-pointed to a date that still genuinely exercises that step). One entry, M26 (30 rows, verdict open), is a genuine unfixed gap: colitur's step-3 "resume the preceding Sunday" fallback is its only ferial-Mass mechanism, and missalemeum's own selection is more granular in three confirmed ways (a rotating votive Mass of the BVM, a named weekly formula for at least one week, and later Time-after-Pentecost weeks this task's own investigation did not narrow to a single rule) -- the same "needs a season-keyed selection mechanism, new behaviour not new data" shape data/ef/expected-divergences.sexp's own C6/C25 and Task 6's own residual concern already name, out of this task's own scope to build. dune test: 358 tests green. COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force: 359 tests green, 89.5s.
* test(differential): fix round 3 -- two more Ember Saturdays, doc fixesLukasz Kasprzak2026-08-151-7/+67
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Two Ember Saturdays shipped an apostle's Mass verbatim from lectio's own ini, the exact shape already found and fixed for Passion Tuesday (C26): ef-advent-ember-sat carried St Thomas the Apostle's Mass (Eph 2:19-22 / John 20:24-29, 21 December) instead of the real "Sabbato Quatuor Temporum Adventus" (2 Thess 2:1-8 / Luke 3:1-6); ef-september- ember-sat carried St Matthew's Mass (Ezek 1:10-14 / Matt 9:9-13, 21 September) instead of the real "Sabbato Quatuor Temporum septembris" (Heb 9:2-12 / Luke 13:6-17). Both verified against both primary-source scans independently. Both readings are explicitly labelled "Lectio Epistolae" in the Missal on both days, so neither needed the "last lesson before the Gospel" convention Holy Wednesday/Good Friday relied on -- a textual fact, not an editorial choice. Fixed at the source in tools/bootstrap_lectionary.ml: colitur_keys excludes both wrong ini sections; a new ember_saturday_corrections list hand-authors the real citations. New allow-list entries C27/C28 (40 rows each, not the naive 46 -- traced to the identical 6 civil years where 21 September and 21 December, always exactly 91 days apart, land on a Saturday and the fixed saint's feast wins outright). Both values pinned in test_lectionary.ml and mutation-tested. Also: C25's per-weekday breakdown was mislabelled (right multiset, rotated weekday labels) in both test_differential.ml and expected- divergences.sexp -- corrected to Wednesday 6/Thursday 19/Friday 19/Saturday 13, and the claim that this split came directly from the comparator's own output is narrowed to what's actually true (only the total, 57, does). C26's scan2 citation range was extended to include the Gospel (previously stopped after the Epistle). lib/kernel/liturgical_day.mli's "citations always empty until Plan 4" comment is now stale on this branch -- left untouched (Task 11's own documentation pass), noted in the task report so it isn't lost. dune test: 358 tests green; COLITUR_EXHAUSTIVE_SWEEP=1: 359 green.
* test(differential): fix round 2 -- Good Friday, Passion Tuesday, stale headerLukasz Kasprzak2026-08-151-57/+150
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Critical, and worse than what it replaced: removing a lectionary key does not mean "no reading" to Lectionary_ef.readings -- it means step 3 silently resumes the preceding Sunday. Good Friday, which has no Mass at all, was emitting Palm Sunday's own Epistle and Passion narrative every year; Holy Wednesday had the same defect. Fixed by authoring both days fully: the Gospel was always unambiguous and is now always authored; the Epistle uses the same "last lesson before the Gospel" convention this file's own Lenten Ember Wednesday entry already established for an identical two-peer-lesson shape, applied for consistency rather than invented to close this gap. C24 is retired, folded into a widened C23 covering all six Holy Week days. Important: Passion Tuesday was shipping Holy Tuesday's Mass, a defect the previous round's own footnote had found and left unrecorded. Fixed at the source -- colitur_keys now excludes lectio's own (wrong) ini section for this one weekday rather than translating it; a new passion_tuesday_entry hand-authors the real Missal citation (Dan 14:27, 28-42 / John 7:1-13, both scans). New entry C26 records the resulting divergence, 43 of 46 years, traced (not merely counted) to three years where a competing I-class feast impedes the day entirely. Important: the allow-list header was stale one level up, still naming and restating the diagnosis of an id (C21) retired in the previous round. Rewritten in full rather than layered with another correction. Minors: all three Lent Ember values now pinned (only Wednesday was before); C22's citation corrected to attribute the date-anchor text and the rank text to their own separate sources; assert_reachable's own comment no longer overclaims what it can catch; C25's falsified reasoning replaced with the directly observed fact (a first replacement derivation was itself found wrong on a second reading and is recorded as rejected, not silently discarded); hand-authored citations standardised to English book names with a colon, matching this file's own dominant convention, with one stated exception where a value must stay byte-identical to lectio's own data rather than be reformatted. dune test: 358/358. COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force: 359/359.
* test(differential): fix round 1 -- Holy Week, Lent Ember, RG 69Lukasz Kasprzak2026-08-151-44/+265
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Two Critical findings, both real: Holy Week (including the entire Sacred Triduum) was reading Passion Week's Masses -- the original colitur_keys widened lectio's single, conflated ini section into both weeks instead of Passion week alone. Narrowed to Passion week only; Holy Week's own four cleanest days (Monday, Tuesday, Thursday, Saturday) are hand-authored directly from the Missal, verified twice against both scans (C23); Holy Wednesday and Good Friday are genuinely multi-lesson liturgies with no single Epistle slot and are deliberately left unanswered, not guessed (C24). The Lenten Ember days were still dead keys: Temporal_ef computes ef-lent-ember-{wed,fri,sat}, lectio's ini names the same data ef-lent-1-{wednesday,friday,saturday}, and colitur_keys never translated it -- both engines independently fell through to the same wrong ferial answer, so even the differential stayed green (C22, a genuine lectio bug recorded for upstream). Fixed the instance and the class: colitur_keys gained the rename, and tools/bootstrap_lectionary.ml gained assert_reachable, sweeping Rite_ef.Temporal_ef.temporal at generation time so a translation table entry naming a slug colitur never computes dies loudly instead of shipping silently, plus an informational log of every real slug with no entry at all. C21 ("colitur's step 3 cannot reach a correct answer for the fixed Christmastide slugs") is retired, superseded rather than merely patched: the Nativity-Octave days now have their own direct Missal formulary (Tit. 3,4-7/Luc. 2,15-20, "Diebus infra octavam Nativitatis Domini"), resolved at step 2, not step 3 at all. That surfaced a real RG 69 gap underneath it: a Sunday landing 26-31 December should keep its own Office, not the fixed weekday placeholder, which Temporal_ef does not currently distinguish. C6's verdict is re-opened (open, not colitur) for the 19 of its 138 rows where this applies directly, and a new entry C25 (57 rows) records the same gap propagating one hop further through step 3 into Holy Name week. Both are out of this task's own scope -- a behaviour change to a shared, multi-round-reviewed kernel-adjacent function -- and recorded, not fixed, per the coordinator's own instruction. C6's own note is rewritten in full rather than layered with another correction; C18's stale trailing count is fixed to match its own pin; the Vigil-misapplication risk flagged as a Minor closed itself once the Nativity-Octave fix landed, confirmed by inspection rather than assumed. dune test: 358/358. COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force: 359/359.
* test(differential): compare reading citations, 16 801 daysLukasz Kasprzak2026-08-151-9/+150
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Layer 3 is NOT blind to the ferial resumption rule, unusually for this project: lectio implements the same rubric independently, so the differential checks colitur's rule against a second implementation rather than against silence. It IS blind to the Commons -- lectio has no such concept -- so chain step 4 rests on layer 4 alone. Divergence triage, 1 532 of 16 801 days differ (15 269 match exactly), 0 unexplained: - A genuine colitur bug found and fixed: data/ef/lectionary.sexp carried lectio's own ini section names verbatim, never translated into the slugs Temporal_ef actually computes for the identical office. Data the bootstrap already held (Passiontide both weeks, the Pentecost Ember days, Holy Name Sunday) was unreachable by chain step 2, silently falling through to a wrong step-3 answer -- invisible until citation content became comparable. tools/bootstrap_lectionary.ml gained colitur_keys (rename/widen), a hand-authored ef-nativity-vigil entry cross-sourced from lectio's own sanctoral calendar and corroborated by colitur's own (overlay-suppressed) sanctoral bootstrap of the same source, and a derived ef-holy-name entry (RG 17(a)'s single Mass heading covers both the Sunday and 2-January shapes). One guess (giving the fixed Nativity-Octave days Holy Name Sunday's own citation uniformly) was tried and reverted once measured against the fixture -- Missal-verified to be right only for the genuine "Sunday within the Octave" case, wrong whenever the true preceding Sunday is Christmas Day or Advent IV instead. - 10 existing/widened Layer C entries (C1/C6/C8/C14/C15/C16/C17/C18 -- C6 and C17 narrowed with the removed population accounted for, not silently re-absorbed) plus two new ones: C19 (the already-adjudicated Time-after-Epiphany week-numbering offset, now visible in citation content), C20 (lectio computes no reading at all for the seven readingless saints Task 6 gave a Common or proper -- colitur is more complete, not wrong). - One entry, C21, is a genuine colitur LOGIC limitation found but not fixed: Lectionary_ef.readings' step 3 is a single hop to the preceding Sunday, insufficient for a run of colitur-only fixed Christmastide slugs whose own preceding Sunday is itself another entry-less fixed slug. Recorded verdict open (data/ef/expected-divergences-missalemeum.sexp's own established precedent for this shape), not left silently failing -- fully diagnosed in task-8-report.md, recommended as a dedicated follow-up task rather than a hasty fix to a shared, multi-round-reviewed kernel-adjacent function.
* data(ef): bootstrap the temporal lectionary from lectioLukasz Kasprzak2026-08-141-0/+105
119 entries, Epistle + Gospel only. The generator refuses a section carrying exactly one of the two: an Epistle without a Gospel is malformed and wants investigating, not shipping. SHA-256 of the source INI is in the provenance header, as with sanctoral.sexp.