aboutsummaryrefslogtreecommitdiff
path: root/test/test_oracle.ml
Commit message (Collapse)AuthorAgeFilesLines
* test(oracle): fix round 1 (F8) -- correct the M18 headline, name the blind ↵Lukasz Kasprzak2026-08-131-20/+32
| | | | | | | | | | | | | | | | | | | | spot precisely The full breakdown, precisely: of 730 days, 331 are resolved (330 matching, 1 mismatched -- M13, Joseph vs the Seven Sorrows), 399 unresolved -- 373 in M18's own bucket, 26 absorbed inside M1/M2/M3/ M16's own widened subsets where the axis fires alongside their pre-existing citation. M18's own note previously stated only its own 373 without this fuller context. Also names the blind spot the axis exists to close in exact terms, not just "the observed day's identity": a TEMPORAL-origin observed day silently replaced by a DIFFERENT temporal-origin observed day of the SAME rank and colour -- exactly Holy Family's own shape, and the reason every prior layer stayed green through the whole gap. States explicitly what the count pin does and does not prove: it guards against the 373/399 population moving silently in either direction, but cannot say which specific day moved or why.
* test(oracle): green -- widen five entries, add M18 for observed identityLukasz Kasprzak2026-08-131-11/+72
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | layer_m_reason's own five entries whose diff shape was checked by EXACT list equality (M1, M2, M3, M13, M16) lost their match once the observed-identity axis widened every row's diff set two commits ago. Each is widened the same way commemoration-identity was already widened for M13 once before: the axis now ALSO fires alongside their existing citation, same root cause, same id -- M1/M3 (temporal-origin observed day, no name), M2 (same, plus five Paschaltide dates that used to match cleanly and now surface for the first time), M13 (Joseph, sanctoral, now a genuine title MISMATCH, not merely unresolved), M16 (the temporal Passiontide feria observed there). M18 covers the remainder: 373 of 730 days whose observed celebration is temporal-origin and so carries no English name at all -- the overwhelming majority of the window, including Holy Family's own two dates in it (2026-01-11, 2027-01-10), counted here rather than shown as a false Matched. Gated on the diff SHAPE alone (this file's own convention for a population this size, the same reasoning M2's own title-substring predicate already uses instead of a date list), verdict unresolvable -- the same fourth verdict M15 already established for the identical limit on the commemoration axis. Building an English name onto the temporal cycle is Plan 4's own scope, register §6. Teeth, per the brief: temporarily corrupted hilary's own English name in data/ef/sanctoral.sexp (14 January 2026, an OBSERVED sanctoral day, rank and colour left untouched) and reran. Reddened immediately: 2026-01-14: observed-identity-mismatch differ -- colitur=(rank=3 colour=w ...) oracle=(rank=3 colours=[w] title="St. Hilary" ...) rank and colour agree on both sides -- exactly the shape the pre-strengthening comparator would have slept through completely. Reverted (git diff on the data file is empty) before this commit.
* test(oracle): compare the observed day's identity, not only rank/colourLukasz Kasprzak2026-08-131-2/+70
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Layer 4 (test_oracle.ml, vs missalemeum) compared the observed celebration's rank and colour and stopped there -- it never checked whether the observed day is actually the RIGHT one. Holy Family (11 January 2026: oracle title "The Holy Family: Jesus, Mary & Joseph") is rank 2/white on both sides purely by coincidence -- an ordinary, unnamed Sunday and Holy Family share both -- so this layer has been silently blind to the missing feast since it was built. Adds Observed_identity_mismatch/Observed_identity_unresolved, following the shape and honesty of yesterday's commemoration-identity comparison (Comm_identity_mismatch/Comm_identity_unresolved): colitur identifies its own observed day by slug, missalemeum by an English title, and the bridge is Celebration.t.names, read directly off LD.observed. That name is only ever set for a SANCTORAL-origin celebration -- a TEMPORAL-origin one (an ordinary Sunday, a feria, a movable named feast) carries none, so most of the 730 days in the fixture window land in Observed_identity_unresolved, not a clean match. That is counted and reported, never silently skipped -- the same discipline this file already applies to an unresolvable commemoration. WIP, expected red: 399 days now show observed-identity-unresolved with nothing in the allow-list naming it, and five of the six existing M-series entries whose own diff shape is checked by exact list equality (M1, M2, M3, M13, M16) lose their match now that this axis widens their diff set. Landed on its own, ahead of any production fix, so it is the regression net the following commits are checked against rather than a change bundled in alongside the fix they enable. The next commits widen those five entries' own diff shapes and add the new bucket's own cited allow-list entry, then build Holy Family itself.
* 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.