summaryrefslogtreecommitdiff
path: root/test/test_rite_ef.ml
Commit message (Collapse)AuthorAgeFilesLines
* data(ef): fix round 1 (F3) -- eusebius-confessor is white, not lectio's redLukasz Kasprzak2026-08-121-0/+26
| | | | | | | | | | | | | | | | | | | | | | | | data/ef/sanctoral.sexp bootstraps colour=red for this new entry (14 Aug), inherited from lectio's own ini; missalemeum's fixture independently tags it :r too -- two non-primary witnesses agreeing with each other, not with the Missal, the exact "trap" this project's own transcription-audit task already named once. Checked directly against the scan (missale-romanum-1962.pdf), not taken on a reviewer's transcription: the 14 August proper reads "S. Eusebii Conf. / Commemoratio / Missa Iustus, ut in festo S. Pauli primi Eremitae, die 15 ianuarii" -- Conf. (Confessor, not Martyr), borrowing the SAME Mass 15 January's own Paul the First Hermit uses, a Confessor's Common, white in both engines' own data for THAT entry. Every other Confessor/Abbot commemoration in lectio's own data is white (maur-abbot, giles, remigius, didacus, ubaldus, hilarion, sabbas, silvester, alexis); Eusebius Confessor is the one exception, with no textual support found for it. No behavioural impact today (Commemoration_only entries are never the printed observed colour under the current pipeline), fixed via the overlay mechanism since sanctoral.sexp is generated and the source is upstream. New test proves it through the real pipeline, the same discipline already applied to the subject retags.
* data(ef): document why adjustments.sexp's directives survive the re-bootstrapLukasz Kasprzak2026-08-121-8/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Neither of adjustments.sexp's two directives is a no-op after the regeneration, and neither is removed -- reasoned through deliberately rather than deleted on sight, per Overlay.apply's own documented diagnostic behaviour (Edit has no "already correct" case; it unconditionally folds every field_edit over the current value when the slug is present, no diagnostic either way). `Edit most-holy-name-of-mary (Set_subject Bvm)`: the base bootstrap no longer needs this correction (the source dropped `class = lord` for this slug, so the default is already Subject.Saint), but the overlay still forces `Saint -> Bvm`. Kept for two reasons: data precision (the calendarium's "Sanctissimi Nominis Mariae" title still argues for Bvm over the generic Saint default, independent of what lectio's class field says) and as a regression guard (Set_subject is unconditional, so it would also correct a future re-introduction of `class = lord` for this slug, the one subject value RG16(a) behaviourally reads). `Suppress vigil-of-christmas`: re-verified, not assumed -- the slug is still present, unchanged, in both the regenerated source and the regenerated sanctoral.sexp, so the directive still fires its ordinary slug-present path. test_rite_ef.ml's own comment on the overlay-in-effect test previously claimed the base file carries `subject Lord` for most-holy-name-of-mary, which the regeneration made false; corrected in place rather than left stale, per this project's own discipline around wrong claims.
* docs: three comments that outlived the rules they describedLukasz Kasprzak2026-08-121-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | All three are the project's own "correct code, wrong explanation" shape, found by the final review of the RG 113 work. No behaviour change. test_rite_ef.ml's registered Alcotest label said "Thomas of Villanova observed, Maurice commemorated" while the test asserts the Ember Wednesday is observed, Thomas is the sole commemoration and Maurice is omitted -- the opposite of two of its three assertions. The body's own doc comment was right; only the name a test run prints was wrong. validate.ml's lead-in still said origin is reconstructed as Sanctoral uniformly because the EF admit "reads only rank and slug, never origin". That stopped being true in ea22ad2: admit now orders by band, and band reads origin via is_temporal, so a temporal-origin commemoration relabelled Sanctoral would be scored on the wrong table entry. The code below already recovers the origin exactly; only this comment lagged. precedence_ef.ml's band guard justified itself by citing celebration.mli as saying a demoted feast retains its rank for RG 111's admission-COUNT purposes. celebration.mli says the opposite -- it names the ORDERING use the guard removes. The guard is right for a reason it did not give: rank stays load-bearing through RG 111(b)'s "de festo II classis" floor, which is what excludes these entries from a II-class Sunday's slot. Both the citation and celebration.mli's own now-stale line are corrected, each recording what it previously claimed.
* fix(rite-ef): band has no table entry for a bare commemoration, everLukasz Kasprzak2026-08-121-1/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fix round 1 on the commemoration-identity/tie-break work: the "genuine same-band tie" M17 adjudicated as open was not a tie at all. RG 91's table enumerates only "dies liturgici" (real feasts) -- entry 24's own text is "Festa III classis, in calendario Ecclesiae universae inscripta" -- so a Celebration.t.status = Commemoration_only candidate (a saint reduced to a bare commemoration) has no row in the table to begin with. Precedence_ef.band used to read rank alone, so it silently lent such a candidate the same table entry as a genuine Feast of its own rank; the calendarium's own 22 September row confirms the distinction in its own notation ("S. Thomae de Villanova ... III classis. / Commemoratio Ss. Mauritii et Soc. Mm." -- Thomas carries a class number, Maurice carries none). Fixed at the source, not by adding a status tier to compare_precedence: band now checks status first, ahead of every rank-keyed branch, and returns unclassified for any Commemoration_only candidate. M17 deleted (not re-adjudicated) -- 22 September now resolves identically on both sides, with no divergence left to name. Blast radius measured independently (a temporary git worktree at the pre-fix commit): 4451 days change across the whole 1583-9999 domain, exactly 4 verified shapes -- 3576 x maurice-and-companions-martyrs -> thomas-of-villanova and 282 x eleutherius -> philip-neri (admitted set changes), 502 x appollonia/cyril-of-alexandria and 91 x dorothy/titus (order only, independently confirmed against the calendarium's own listing convention). Zero days change who is observed. Further swept the whole domain for a genuine "two different candidates on the identical real table entry" residual -- the shape RG 113 truly gives no instruction for -- and found it empty: of 109201 same-rank ties domain-wide, 83950 now resolve by band alone and the remaining 25251 are exclusively two Commemoration_only candidates tied at unclassified, never two real feasts. The residual admit still breaks alphabetically is real, but narrower than previously documented. The "66 days" figure is reconciled, not merely disputed: 599 is the tie population, 65 (whole-comparator: 67) is the real admitted-set decision count within it (independently reproduced against the pre-Task-B binary), 149 is order-only. Every one of the 65 real decisions traces to the same Commemoration_only/Feast root cause as Maurice/Thomas. Also: validate.ml's admission fixed-point check recovers a commemoration's real origin (by matching its slug against the day's own temporal office) instead of reconstructing every candidate as Sanctoral, since band -- unlike EF's own admit -- does read origin; precedence_ef.ml/.mli's motivating example and blast-radius claims corrected to no longer rest on the fixed Maurice/Thomas case; test_identity_rank_corroboration's own population count corrected now that 22 September (and 21 other Feast-status matches) became reachable; its rank-agreement pin documents exactly what it does and does not prove. Register (§4, §6.1, §6 checklist) and CLAUDE.md corrected in place, including the RG 113 first-sentence gap this exercise surfaced but did not close, recorded as a new open item. 275 -> 276 tests (with the exhaustive sweep), all green.
* fix(rite-ef,kernel): follow the oracle on the Purification; admit reads the ↵Lukasz Kasprzak2026-08-121-18/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | day's own Sunday-ness, not observed Fix round 1 review, two findings landed together because each golden pin's correctness depends on both. CRITICAL (item 1): reverts this branch's own first-pass retag of the Purification (2 February) from Lord back to Bvm -> Lord. The calendarium titles it 'B. Mariae Virg.', but missalemeum -- this project's designated EF oracle -- treats it as taking an occurring II-class Sunday's place outright, commemorations empty, exactly RG16(a)'s own festum Domini treatment (2020-02-02, 2014-02-02, independently fetched). Control, 2019-09-08 (the Nativity of the BVM, an ordinary Marian feast, on a Sunday): the Sunday observed, the feast merely commemorated -- the opposite pattern, proving the Purification's own oracle treatment is deliberate, not a gap. RG16(a) alone, on the untouched data, would have matched the oracle character for character; retagging Bvm is what moved colitur away from it on 1200 domain-wide days. The user has ruled: follow the oracle. Genuine primary-text counter-evidence (RG120(b), the colour rule grouping 2 February under 'B. Mariae Virg.', a category separate from 'Domini') is recorded in the register, not discarded -- a different project could reasonably rule the other way on the same evidence. most-holy-name-of-mary stays retagged Bvm; that one was never disputed. Removes the now-unneeded C12 lectio allow-list entry (data/ef/ expected-divergences.sexp, test_differential.ml): with the Purification Lord again, colitur matches lectio's own class = lord on every affected date, no divergence to allow-list. IMPORTANT (item 2): Precedence.rules.admit gains a ~temporal parameter -- a genuine kernel signature change, unlike RG16(a) itself. RG111(b)'s own Sunday rank floor ('one commemoration, namely of a II-class feast') used to be detected by reading observed's own slug for a Sunday marker, which silently assumed observed IS the day's temporal-cycle office. RG16(a) breaks that assumption on purpose: a Feast of the Lord standing in for an impeded Sunday 'cum omnibus iuribus et privilegiis' keeps the day a dominica II classis for RG111(b) too, even though the FEAST, not the Sunday, is observed. Before this fix an unrelated saint (Pope Sixtus II et al., 6 August, Class3) was wrongly admitted into the freed slot on every one of 1178 domain-wide days. Oracle-confirmed directly: 2023-08-06 (a Sunday) shows him displaced, commemorations empty; 2026-08-06 (an ordinary Thursday) shows him admitted -- being a Sunday is exactly what excludes him. admit now reads Sunday-ness off ~temporal (the day's own temporal-cycle candidate, passed through from Precedence.resolve unchanged) instead of observed. Validate's own admission fixed-point invariant updated to pass the same real temporal candidate through. Both golden pins in test_golden.ml were promoted from actual colitur day output without independently consulting the rubric or the oracle first -- a real defect the review caught. Re-derived from both before re-pinning: 2028-08-06 and 2025-02-02 now pin comms=[], no commemoration at all, matching missalemeum exactly in both cases.
* data(ef): retag the Purification and Most Holy Name of Mary as BVM, not LordLukasz Kasprzak2026-08-121-0/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Both entries carried (subject Lord) in data/ef/sanctoral.sexp, inherited unchecked from lectio's own class = lord field. The calendarium says otherwise: 2 February reads "IN PURIFICATIONE B. MARIAE VIRG." and 12 September reads "Sanctissimi Nominis Mariae" -- both name Mary, not the Lord, unlike the four genuine Lord entries' own "D. N. I. C." formula (Precious Blood, Transfiguration, Exaltation of the Holy Cross, Dedication of the Archbasilica of the Most Holy Saviour), all of which were checked against the same calendarium and left untouched. This matters together with RG16(a): applying the rule while the Purification was still mistagged Lord would have made it outrank an occurring II-class Sunday and then wrongly suppress that Sunday's own commemoration under RG16(a) too, the opposite of the intended fix. Retagged, the Purification no longer bands at RG91 entry 14, so the Sunday is observed and the Purification survives as its own ordinary commemoration. Corrected via a new data/ef/adjustments.sexp overlay (Set_subject Bvm), the same mechanism that file already uses to suppress vigil-of-christmas as a bootstrap duplicate, not a hand-edit of sanctoral.sexp itself: that file's own header asks for edits to go through the generator, and its SHA-256 provenance covers a byte-faithful mirror of lectio's INI. The Purification retag changes which day the lectio differential observes on 2 February whenever it falls on a Sunday (six years, 2005-2050); allow- listed as C12 in data/ef/expected-divergences.sexp, expected_rows derived independently (date -d <year>-02-02 for each year in range), not transcribed from a comparator run.
* test(rite_ef): pin no transfer ever lands inside the Easter octaveLukasz Kasprzak2026-08-121-1/+139
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Task 11's re-review found that Precedence_ef.transfer_target's Annunciation/Easter condition -- and RG 96's general walk more broadly -- is correct only because Temporal_ef happens to make every day from Easter Sunday through Low Sunday (Easter+0..+7) blocking (Class1/2): Easter and Low Sunday via named, every day between via privileged_feria. Nothing enforces that; a future edit narrowing the octave's blocking range could let a translated feast land inside it, silently. Add a test for the consequence, not the mechanism: over 2005-2050 (real data, the project's own differential window), no day in [Easter, Easter+7] is ever a transfer's target, checked against both transferred_in and transferred_out's own recorded target dates. Plus a direct, deliberately-constructed case that starts the RG 96 search inside Holy Week itself (Holy Thursday 2026, real occupant), pinning that the search lands on Easter+8 -- and a companion test that reads the real occupant's own rank across the whole [origin+1, Easter+7] span to confirm the search genuinely walked through the window rather than stopping early for an unrelated reason. Mutation-verified: narrowing privileged_feria's post-Easter range (6 to 4 days) makes all three new tests fail, including a real natural occurrence the fixture did not anticipate (St Joseph, 19 March, transferring into Easter+5 in 2008/2035/2046) -- not just the deliberately constructed Holy Week case.
* test(ef): pin the overlay suppression's own observable effectLukasz Kasprzak2026-08-121-2/+48
| | | | | | | | | | | | | | | | | With data/ef/adjustments.sexp's one Suppress directive replaced by an empty directive list, colitur day 2026's stdout was byte-identical for all 365 days and the whole suite still passed: ef-nativity-vigil already outranks vigil-of-christmas in the RG91 contest regardless of whether the overlay ever ran, so the suppression's only observable effect is keeping vigil-of-christmas out of 24 December's Liturgical_day.omitted -- a field no cram assertion reads. test/dune's own dep on adjustments.sexp pinned the file's existence, never its content. Confirmed the gap two ways: reverting the overlay to (directives ()) makes this new test fail (24 December's omitted gains vigil-of-christmas), and confirmed test/cli.t's whole cram suite still passes under that same mutation -- cram is structurally blind to this, not merely undertested.
* rite(ef): clamp the RG96 search at the domain ceilingLukasz Kasprzak2026-08-121-0/+81
search_from could walk up to 400 days past origin before Calendar's own ~start ~stop clamp is ever consulted, and nothing stopped it probing occupant on a date past 31 December 9999 -- occupant chains through the real EF rite's temporal, which calls Computus.gregorian_easter, not total outside 1583..9999 (it Date.makes and failwiths on Error). Not reachable with the shipped sanctoral data alone, but reachable through the project's own primary extension path: an overlay adding an I-class feast on 25 December leaves nothing but Class2 Nativity-octave days for the rest of civil year 9999, so the unguarded search reached 1 January of year 10000 and crashed there with 'computus: year 10000 out of range 1583..9999'. 9999 is an in-range year and the kernel's contract is 'never raises on in-range input'. search_from now also stops, without probing occupant again, once it passes Date's own domain ceiling -- the same 'return a finite date, let Calendar's own out-of-range handling record it, never pretend to have found something admissible' contract the existing step-count guard already follows. Two new tests, both mutation-verified to actually reproduce the crash when the guard is removed (see the task report): a precedence_ef.ml unit test using the real Temporal_ef.temporal as occupant (a synthetic occupant can never discriminate this, since it never calls Computus itself), and a Calendar-level integration test reproducing the exact overlay-based scenario the review found.