From 76298db9b0fb5409bcfd4276b642f69f4da530e9 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 12 Aug 2026 15:37:08 +0200 Subject: feat(test): oracle layer compares commemoration identity, not just count 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. --- CLAUDE.md | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'CLAUDE.md') diff --git a/CLAUDE.md b/CLAUDE.md index 174bf30..0f18537 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,11 +113,39 @@ against missalemeum; layer 5 pins ~30 dates. the week column. It also **shares colitur's own lineage**: colitur's data was bootstrapped from lectio, so an error both inherited is invisible here. Proven: Holy Thursday was violet in both because both were wrong. -- Layer 4 is **two years wide** and compares rank, colour-membership and - commemoration presence/count — **never celebration identity**. -- Together they sleep through **commemoration identity**: reversing `admit`'s - dignity sort, so the engine admits the *worst* commemorations, leaves all eight - differential and oracle assertions green across 17 531 days. +- **Layer 4's commemoration-identity gap is CLOSED** (2026-08-12, Task B, branch + `ef-rg16a`): it used to compare presence/count only, never *which* commemoration + won — reversing `admit`'s dignity sort (the engine admitting the *worst* + commemoration, an outright RG 111 violation) left all eight differential and + oracle assertions green across 17 531 days. Layer 4 now also compares **identity** + — colitur's own resolved English name (`Celebration.t.names`, `en`) against + missalemeum's title text, for every day both streams admit the same count. The + mapping resolves **every SANCTORAL-origin commemoration** (colitur's own name + field, bootstrapped from lectio, verified to match missalemeum's titles + character-for-character); it **cannot resolve a TEMPORAL-origin one** (an + impeded feria/Ember/Rogation day — `Rite_ef.Temporal_ef` never sets a celebration + name) — that case is **never silently skipped**: it is a separate, counted, + allow-listed outcome (`Comm_identity_unresolved`, 19 of 227 non-empty-commemoration + days over 2026–2027), not a silent pass. Two genuine identity mismatches surfaced + and were adjudicated (register §4/§6.1, `data/ef/expected-divergences-missalemeum + .sexp` M16/M17): a known unimplemented office (the Seven Sorrows of Passion + Friday) and the RG 113 same-band tie-break residual (below), the latter left + explicitly OPEN, not defaulted to either side. Proof of teeth: reversing + `admit`'s *dignity*-based sort (the same historical defect shape) now turns + layer 4 red — `test_no_unexplained_differences` reports an unexplained + `commemoration-identity-mismatch` day (colitur admitting "St. Thecla" where both + the rubric and missalemeum require "St. Linus") — reverted after confirming. +- **The `admit` same-rank tie-break is RG 113, not an uncited convention** (same + task): RG 113's own second sentence ("in admittendis et ordinandis aliis + commemorationibus, servetur ordo tabellae praecedentiae"), previously quoted only + in its first half, is the real rule — `admit` now orders/selects by + `Precedence_ef.band` (RG 91's own table), not RG 8's coarse four-class rank. + Measured (not assumed): the fix's blast radius against the pre-change binary is + **zero admitted-commemoration changes across the entire 1583–9999 domain** — a + correctness-of-citation fix, not an answer-changing one, on this codebase's + current data. A narrower residual remains open where two candidates land on the + *identical* RG 91 table entry (RG 113 gives no further instruction there); + `admit` still breaks that alphabetically, still uncited, register §6.1. ## Current state (Plans 1–3 DONE — verify with `git log`) -- cgit v1.3