aboutsummaryrefslogtreecommitdiff
path: root/test/test_oracle.ml
Commit message (Collapse)AuthorAgeFilesLines
* test(oracle): close M4, M6, M7, M9 and M14 -- the five now-fixed data gapsLukasz Kasprzak2026-08-121-68/+21
| | | | | | | | | | | | | | | | | | Each was recorded as a genuine data gap "traced upstream into lectio, unfixable without touching lectio". That constraint is gone: all five commemorations (St Agnes secundo 28 Jan, St Eusebius Confessor 14 Aug, St Evaristus 26 Oct, St Theodore 9 Nov, St Boniface Martyr 14 May) are now present in the re-bootstrapped sanctoral.sexp, and each divergence stops occurring in the 2026-2027 oracle fixture -- verified by re-running the comparator and confirming zero rows for all five ids, not assumed from the data change alone. Removed rather than kept as dead 0-row citations, matching the M17 precedent already in this file: the count pin (test_layer_m_counts_match_citations) now enforces that none of these five divergences can silently reappear. Corresponding dead code (m4_dates .. m14_dates and their layer_m_reason branches) removed from test_oracle.ml; a short pointer comment left at each id's old location.
* fix(rite-ef): band has no table entry for a bare commemoration, everLukasz Kasprzak2026-08-121-53/+93
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* feat(test): oracle layer compares commemoration identity, not just countLukasz Kasprzak2026-08-121-32/+351
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | test_oracle.ml (validation layer 4) used to compare commemoration presence and List.length only -- cardinality, never which candidate is admitted. A reviewer proved this vacuous by reversing admit's dignity sort (the engine admitting the worst commemoration, an outright RG 111 violation) and finding every assertion in this file green across all 730 days. tools/extract_missalemeum_oracle.py now also emits each commemoration's own missalemeum id (field 9, commemoration_ids), parallel to the existing title field; fixture regenerated from the same underlying lectio snapshot (commit d7da4b0, re-verified, first 8 fields byte-identical), read from a scratch copy so ~/git/projects/lectio was never touched. SHA-256 pin and provenance updated. The mapping: colitur identifies a commemoration by slug, missalemeum by an English title string. No hand-built slug<->title table -- colitur's own Celebration.t.names already carries the same English text for every SANCTORAL-origin commemoration (bootstrapped from lectio, verified to match missalemeum's titles character-for-character). This resolves identity for every sanctoral-origin commemoration but cannot resolve a TEMPORAL-origin one (Rite_ef.Temporal_ef never sets a celebration name) -- that case is a new, distinct outcome (Comm_identity_unresolved), counted and allow-listed, never silently skipped: 19 of 227 non-empty-commemoration days over 2026-2027. Two genuine identity mismatches found and adjudicated (new allow-list entries M15-M17, one is the unresolved bucket): M16, 27 March 2026, the already-known unimplemented Seven Sorrows of Passion Friday office (verdict missalemeum); M17, 22 September 2027, the RG 113 same-band tie-break residual (verdict open, per the sibling admit fix). A new corroborating check cross-references missalemeum's own id-embedded rank against colitur's, split by status: Feast-status matches must agree exactly (none reachable in this 2-year window, checked regardless); Commemoration_only-status matches either genuinely agree or fit a known, pre-existing, already-registered convention gap (colitur's bootstrap rank vs missalemeum's own sentinel) -- not a title-matching defect. Perturbation test performed and reverted: reversing admit's dignity- based ordering (compare_precedence's real committed form uses band, not dignity -- this reproduces the historical defect shape directly) turns the oracle layer red: "no differences outside the cited allow-list" fails with an unexplained commemoration-identity-mismatch on 2026-09-23 (colitur admits "St. Thecla" where the rubric and missalemeum both require "St. Linus"). Reverted; diff against the prior commit confirms no residue. CLAUDE.md's "know what each layer cannot see" section updated: the commemoration-identity gap it documented as open is now closed, with the mapping's limits and the RG 113 tie-break finding summarised. 271 -> 273 tests (274 with the exhaustive sweep), all green.
* fix(ef): M6 was convicted on the transcription's silence, not a scanLukasz Kasprzak2026-08-121-13/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | data/ef/expected-divergences-missalemeum.sexp's M6 entry and its matching comment in test/test_oracle.ml both cited 1962-06-23,_SS_Ioannes_XXIII, _Missale_Romanum,_LT.pdf's 14 August row ("Vigilia, II classis." -- nothing else) as if it were the calendarium itself. It is an electronic transcription that silently drops commemoration lines the photographic scans carry. missale-romanum-1962.pdf's 14 August row reads "Vigilia, II classis, Commemoratio S. Eusebii Conf.", with its own proper following -- independently confirmed in the second scan, Missale Romanum 1962_text.pdf. M6's verdict flips colitur -> missalemeum: this is a genuine colitur data gap, the same shape as M4/M7/M9/M14 (absent from data/ef/sanctoral.sexp and from lectio's own tridentine-calendar.ini), not a spurious oracle entry. Not fixed here for the same reason those four are not: it requires touching lectio's own bootstrap source, out of reach for this task. expected_rows is unchanged (2) -- the diff shape the allow-list predicate matches does not depend on which side is judged correct, confirmed by the suite passing unchanged. A companion register ruling that convicted romanus (9 August) on the identical reasoning -- and the register's own sanctoral-audit bucket counts that followed from it -- are corrected in docs/research/ rules-register.md (gitignored, not part of this commit). Full audit method, the complete list of dropped commemorations found across the whole calendarium, and every other ruling checked for the same defect are in .superpowers/sdd/2026-08-12-colitur-rg16a/transcription-audit- report.md (also gitignored).
* docs+test: small factual corrections (item 7, part 1)Lukasz Kasprzak2026-08-121-3/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Six independent, small corrections found during the final review: - dune (workspace root): the comment said the stanza used "(:standard)" to preserve dune's default `default` alias target; the stanza actually spells that out explicitly via (alias_rec install). Comment now matches the code. - test_validate.ml's test_easter_extremes asserted `List.length ys = 2` where an identity check was called for -- the comment already named 1598 and 1666, but nothing confirmed extreme_years() found THOSE two rather than some other pair with the right cardinality. Now asserts the identities directly (the project's "cardinality where identity was required" vacuity flavour, per the review). - test_oracle.ml and expected-divergences-missalemeum.sexp both claimed "one entry (M13) is [verdict open]" -- M11 is open too (its own verdict changed from colitur to open in fix round 1); both now say "two entries (M11 and M13)". - expected-divergences-missalemeum.sexp's M2 note attributed `band` to temporal_ef.ml; `band` is precedence_ef.ml's own function. - lib/kernel/precedence.mli documented `dropped`/`admit`'s physical- equality obligation nowhere -- it lived only in one rite's own module (Rite_ef.Precedence_ef.admit's doc comment), but this signature is what an author of the next rite actually reads. Added the obligation here, cross-referencing the EF instance as precedent, not the only source. - README's opam install line omitted sexplib and ppx_sexp_conv (both in dune-project's own depends; `dune build` fails without them for a contributor following the README verbatim) and documented only `colitur easter`, though `temporal` and `day` both exist and are the more useful entry points. Fixed both. No behaviour change: comment/doc/test-assertion corrections only (the easter-extremes fix strengthens an assertion, it does not change what passes). Verified byte-identical `colitur day` output across 1583, 1900, 1902, 2008, 2011, 2026, 2038, 9999. 259/259 tests green.
* test(oracle): correct M11's citation and verdict (fix round 1, F3)Lukasz Kasprzak2026-08-121-15/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | M11 (the Nativity Octave's 26/27/28 December commemoration) previously read "No RG paragraph found to support this" with verdict colitur. Wrong on both counts, found by fix-round-1 review. RG 67 ("dies infra octavam sunt II classis") and RG 109(c) ("de diebus infra octavam Nativitatis Domini") both name this commemoration; the 1962 calendarium's own text confirms it directly, verbatim, under all three dates: "S. STEPHANI PROTOMARTYRIS, II classis. / Com. octavae Nativitatis." (same pattern for John the Evangelist and the Holy Innocents). It is also a genuine regression the previous commit's own commemoration-eligibility fix introduced: before that fix, colitur happened to commemorate the day's generic Christmastide loser unconditionally, which coincidentally kept presence agreeing with the oracle even though the reasoning was wrong; the fix correctly stopped that, but 26-28 December's own temporal candidate falls through to [ferial_rank]'s Christmastide catch-all, which gives it Class4 -- the wrong ferial rank for a day RG 67 says is II class. A naive fix would also get RG 69 backwards: when this window falls on a Sunday, RG 69 names the SUNDAY as observed with a commemoration of THE FEAST ITSELF (Stephen/John/the Innocents), never the generic octave placeholder -- so this needs a commemoration that attaches to whichever named feast is observed, not one more competing RG 92-95 candidate the way everything else in this engine is modelled. Out of this fix round's own scope. Verdict changed from colitur to open: neither side is confidently right without that fix, and the previous "colitur is correct, nothing to implement" framing was itself the risk under review.
* test: oracle vs missalemeum 2026-2027; audit the sanctoralLukasz Kasprzak2026-08-121-0/+607
Validation layer 4: an oracle harness against missalemeum (Divinum Officium data), independent of the lectio bootstrap chain colitur's own sanctoral data comes from -- the only layer that can catch an error inherited from that bootstrap, and the only one that can validate commemorations at all (the lectio differential explicitly excludes them, per its own header comment). tools/extract_missalemeum_oracle.py shapes the fixture from lectio's sources/snapshot.tar.gz outside the test (no JSON library in this project's frozen deps, same reasoning test_differential.ml's own fixture already documents). test/fixtures/missalemeum-ef-2026-2027 .txt (730 days, SHA-256 pinned and asserted) + its own .provenance note record exactly how to regenerate it. test_oracle.ml compares three axes the oracle actually supports: rank, colour (SET MEMBERSHIP -- 14 of 730 days carry two colours, e.g. rose+violet on Gaudete/Laetare, which independently vindicates this project's own rose reading against lectio's violet-only one, recorded in the register), and commemoration presence/count. Slug identity is deliberately out of scope (needs a title->slug mapping, the data audit's own business, not the automated comparator's). Of 730 days, 688 matched cleanly outright. The remaining 42 are all named in data/ef/expected-divergences-missalemeum.sexp (14 cited entries, M1-M14): most are genuine primary-source-confirmed findings this task adjudicated and fixed in the two preceding commits (RG 33, RG 109/111, Holy Thursday's colour); the rest are real, cited, deferred feature/data gaps (RG 91 entry 27's BVM-Saturday office, RG 110's inseparable Peter/Paul commemoration, four sanctoral entries missing from lectio's own source) or genuine oracle-side artifacts -- honestly verdicted against whichever side this task's own primary-source research actually backs, never defaulted to colitur. One entry (M13, St Joseph vs the Friday of Passion Week 2027) is verdict open: adjudicated as unresolved after real search effort, not guessed past. The data audit: every sanctoral entry the comparison flagged was hand-checked against the 1962 calendarium, plus a 20-entry deterministic random control sample (seed 20260812) drawn independently of the flagged set. The control sample caught two entries (benedict, frances-rome) marked Commemoration_only in the bootstrapped data when the primary calendarium lists them as plain III-class feasts with their own Office -- traced to lectio's own source, not fixable here, and reported as a signal (10% of a random sample) rather than a blanket claim. Coverage recorded honestly in docs/research/rules-register.md's own three buckets: confirmed by oracle (200/322), confirmed by hand (23/322, 2 of them wrong), unverified (115/322) -- the unverified bucket stated explicitly rather than left implicit. Harness teeth demonstrated and reverted (not committed): a fixture rank/colour edit on a previously-clean day fails both the checksum pin and the no-unexplained-differences assertion independently; an expected_rows drift on the allow-list fails the citation-count assertion. Both captured with their exact failure messages, both reverted before this commit.