From daca7de424be106c1cc5f3aa01950eda3b767a0f Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 13 Aug 2026 08:17:36 +0200 Subject: test(differential): split the Holy Family/Baptism collision out of C1 (C15) Before this task's Holy Family fix, colitur's generic Sunday fallback lost outright to the fixed Commemoration of the Baptism of the Lord on 13 January whenever it fell on a Sunday, producing the SAME slug lectio's own tridentine-calendar.ini shows there -- squarely inside C1's own 6-13 January blanket (only Season differed). Now that Holy Family (RG 17(b)) correctly outranks the fixed Baptism and excludes it as a commemoration (RG 91 entry 14, RG 112(a)), colitur's own slug on those seven dates (2008, 2013, 2019, 2030, 2036, 2041, 2047) changes to ef-time-after-epiphany-sunday-1 -- a genuine identity divergence against lectio, which has no Holy Family at all. C1's own predicate does not absorb it (jan_6_13_slug has no entry for that slug), so it surfaced as unexplained, exactly the check the task brief asked for: split it out into its own cited entry rather than widening C1's predicate to swallow it silently. C1's own expected_rows moves 368 -> 361 (back to its pre-rebootstrap value, for a third and different reason than either of the first two moves recorded in its own note); the new C15 covers the 7 rows, gated on the literal date list AND colitur's own slug, the same identity guard C1/C6/C8/C14 already apply. --- data/ef/expected-divergences.sexp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'data/ef') diff --git a/data/ef/expected-divergences.sexp b/data/ef/expected-divergences.sexp index a733273..8e104d9 100644 --- a/data/ef/expected-divergences.sexp +++ b/data/ef/expected-divergences.sexp @@ -45,8 +45,8 @@ ((id C1) (citation "RG 72-73 (Nativity/Epiphany season boundary, Jan 1-13) + RG 119a (white through \"expletum tempus Epiphaniae\"); register §3c item 1") (verdict colitur) - (note "6-13 January is Christmastide in colitur, matching RG 72-73's explicit boundary at 13 January (corroborated independently by RG 119a's colour rule, §3b). lectio's efSeason switches to time-after-epiphany on 6 January. The season disagreement cascades into colour (green vs white) and, on 7-8 January specifically, into the ferial slug family name (colitur's ef-christmas-2- vs lectio's ef-time-after-epiphany-1- for the same two days). REFRESHED (ef-rebootstrap fixture refresh, 2026-08-12): expected_rows moved 361 -> 368. NOT a new divergence -- the closed C13's own 7 rows (13 January in the 7 years it falls on a Sunday) fold back in here: lectio's fix wave independently fixed its own equivalent of the RG16(a) defect C13 used to allow-list, so on all 7 of those Sunday years lectio's slug now matches colitur's `commemoration-of-the-baptism-of-the-lord` too (not just rank/colour), leaving season as the ONLY residual difference on those rows -- squarely inside C1's own existing shape (diffs subset of [Season;Colour;Slug] with the Slug-diff escape clause unused). Re-derived independently (a Python cross-check reading colitur's own `day` CLI output for 2005-2050 and the refreshed lectio fixture directly, replicating diff_fields/layer_c_reason's own logic outside the OCaml comparator, then cross-checked against the OCaml comparator's own `test_layer_c_counts_match_citations` failure output before this entry's value was set -- not by running the comparator green and copying its number): 368.") - (expected_rows 368)) + (note "6-13 January is Christmastide in colitur, matching RG 72-73's explicit boundary at 13 January (corroborated independently by RG 119a's colour rule, §3b). lectio's efSeason switches to time-after-epiphany on 6 January. The season disagreement cascades into colour (green vs white) and, on 7-8 January specifically, into the ferial slug family name (colitur's ef-christmas-2- vs lectio's ef-time-after-epiphany-1- for the same two days). REFRESHED (ef-rebootstrap fixture refresh, 2026-08-12): expected_rows moved 361 -> 368. NOT a new divergence -- the closed C13's own 7 rows (13 January in the 7 years it falls on a Sunday) fold back in here: lectio's fix wave independently fixed its own equivalent of the RG16(a) defect C13 used to allow-list, so on all 7 of those Sunday years lectio's slug now matches colitur's `commemoration-of-the-baptism-of-the-lord` too (not just rank/colour), leaving season as the ONLY residual difference on those rows -- squarely inside C1's own existing shape (diffs subset of [Season;Colour;Slug] with the Slug-diff escape clause unused). REFRESHED AGAIN (ef-rg112-rg110 task, branch ef-rg112-rg110): expected_rows moved 368 -> 361, back to its PRE-ef-rebootstrap value, but for a THIRD, different reason -- SPLIT OUT to its own new entry, C15, not silently re-absorbed: colitur now BUILDS Holy Family (RG 17(b)) and, on these same 7 dates, correctly observes it in the fixed Baptism's place (RG 91 entry 14, RG 112(a)), so colitur's own slug there changes from `commemoration-of-the-baptism-of-the-lord` (which happened to already match lectio's own slug) to `ef-time-after-epiphany-sunday-1` (Holy Family's own, lectio has no equivalent) -- a genuine SLUG divergence now, no longer inside C1's own [Season]-only shape. See C15's own entry for the full account.") + (expected_rows 361)) ((id C6) (citation "RG 91 entry 17 (\"days within the Octave of the Nativity\")") (verdict colitur) @@ -62,3 +62,8 @@ (verdict colitur) (note "ef-rebootstrap fixture refresh (2026-08-12), replacing the closed C9's old 'Joseph on a Lent Sunday' shape: in 2008, 2035 and 2046, St Joseph's (19 March) RG 96 walk is congested enough by Passiontide/Holy Week/the Easter octave to cross Easter, landing on the Monday after Low Sunday -- exactly where the Annunciation (25 March), independently transferred under its own Attamen (a) exception, has already been assigned its \"sedes propria\". colitur's calendar.ml (place_transfers/compare_deferred) resolves the resulting same-band (RG 91 entry 11) tie between the two I-class feasts by slug order (\"annunciation...\" < \"joseph...\"), an engineering convention with no direct RG citation of its own (recorded honestly as such in calendar.ml's own comments and test_golden.ml's 2008 golden-pin comment) -- so the Annunciation keeps the Monday and Joseph's own walk continues one day further (1 April 2008; 3 April 2035 and 2046, since the Annunciation's own target there is 2 April), each a genuine free class-4 feria. lectio, by contrast, does NOT resolve this collision at all: its transferIfImpededEF walks each candidate independently with no awareness of a second contestant, so the Annunciation's own walk claims the Monday and Joseph is left with no transferred day anywhere -- merely tacked onto the Annunciation's own row as a trailing, never-admitted \"+joseph-spouse-of-the-bl-virgin-mary\" candidate (lectio's own commit 09a1444, \"calendar: record the RG 95 chained-transfer gap in the source\", states this outright: \"No functional change -- this collision is left unfixed, defensible against scope\"). RG 95 grants the right of translation to I-class feasts; Joseph has it and lectio's engine never exercises it for him here -- colitur giving him a real transferred day, somewhere, is the more textually faithful reading regardless of the harder sub-question below. OPEN SUB-QUESTION, recorded rather than silently resolved either way (docs/research/rules-register.md has the full account): whether Joseph, being impeded FIRST (19 March, six days before the Annunciation's own 25 March), should instead take priority for the Monday under RG 98's \"in paritate autem Officium prius impeditum praecedit\" (at equal table position, the office impeded first takes precedence) -- which would push the ANNUNCIATION to the later day instead. colitur's current slug-order tie-break was never checked against this specific reading; the Annunciation's own \"tamquam in sedem propriam\" wording is offered as the stronger textual argument for exempting it from an RG 97/98 queue contest altogether (it names a specific day as its own proper seat, not a provisional walk target), but this is this project's own reading of the primary text, not a settled point -- flagged as a genuine open item, not adjudicated with full confidence either direction. Independently re-derived (not copied from prose): `grep joseph-spouse-of-the-bl-virgin-mary` against both the refreshed fixture and colitur's own `day` CLI output for 2005-2050, filtered to rows with a real post-Layer-A/B diff -- exactly these 3 dates, cross-checked against the OCaml comparator's own failure output before this value was set.") (expected_rows 3)) + ((id C15) + (citation "RG 91 entry 14 (\"Festa Domini II classis, primum mobilia, deinde fixa\") + RG 17(b) (\"festum S. Familiae ... celebrandum dominica prima post Epiphaniam ... locum tenet dominicae occurrentis cum omnibus iuribus et privilegiis\") + RG 112(a) (\"Officium, Missa aut commemoratio de aliquo festo vel mysterio unius Divinae Personae excludit commemorationem ... de alio festo vel mysterio eiusdem Divinae personae\"), all scan-verified; register §6.0/§4") + (verdict colitur) + (note "ef-rg112-rg110 task: SPLIT OUT of C1's own blanket 6-13 January window, not a new kind of divergence -- the same discipline the now-closed C13 already established for this exact date (C1's own note above), applied again because building Holy Family reopened the identical shape C13 used to cover, for a different underlying reason. Before this task, colitur had no Holy Family office: on these seven dates (13 January when it is itself a Sunday -- 2008, 2013, 2019, 2030, 2036, 2041, 2047), colitur's generic Sunday fallback lost outright to the fixed Commemoration of the Baptism of the Lord (already subject Lord in the rebootstrapped data, RG16(a)'s existing mechanism), producing the SAME slug lectio's own tridentine-calendar.ini shows there (`commemoration-of-the-baptism-of-the-lord`) -- only Season differed, inside C1's own shape. Holy Family (RG 17(b)) now correctly outranks the fixed Baptism (RG 91 entry 14's own \"primum mobilia, deinde fixa\" -- {!Rite_ef.Precedence_ef.entry_14_movable_band}) and excludes it as a commemoration entirely (RG 112(a), directly confirmed by the Holy Family Mass propers' own more specific 13-January rubric, both photographic scans: \"Si festum S. Familiae occurrerit die 13 ianuarii, Missa dicitur de festo S. Familiae, sine commemoratione Baptismatis D.N.I.C., et sine commemoratione dominicae\"), so colitur's own slug on these 7 dates changes to `ef-time-after-epiphany-sunday-1` (Holy Family's own -- unchanged from the plain Sunday key it always carried, temporal_ef.ml's own comment on why) -- a genuine SLUG divergence against lectio, which has no Holy Family at all and still shows the fixed Baptism observed. Gated on the literal 7-date list AND colitur's own slug (the same identity guard C1/C6/C8/C14 already apply, fix round 1's own finding 1). Derived from the OCaml comparator's own failure output directly (test_layer_c_counts_match_citations), not by hand-counting first and cross-checking after: 7.") + (expected_rows 7)) -- cgit v1.3 From e5cafdd222a05032ae4f3c0ea07fe0eeda47c145 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 13 Aug 2026 08:21:39 +0200 Subject: test(oracle): green -- widen five entries, add M18 for observed identity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- data/ef/expected-divergences-missalemeum.sexp | 22 ++++++- test/test_oracle.ml | 83 +++++++++++++++++++++++---- 2 files changed, 92 insertions(+), 13 deletions(-) (limited to 'data/ef') diff --git a/data/ef/expected-divergences-missalemeum.sexp b/data/ef/expected-divergences-missalemeum.sexp index 9cff236..d7a1c8c 100644 --- a/data/ef/expected-divergences-missalemeum.sexp +++ b/data/ef/expected-divergences-missalemeum.sexp @@ -35,6 +35,19 @@ ; primary-source effort, not defaulted past -- see each entry's own note ; and the task report for the full search. ; +; M18 -- ef-rg112-rg110 task (Holy Family, RG 17(b)): test_oracle.ml's own +; comparator was strengthened to compare the OBSERVED day's identity, not +; only its rank and colour (the gap that let the missing Holy Family go +; unnoticed by this layer for as long as it did -- rank 2/white on both +; sides purely by coincidence). [M18] is [verdict unresolvable], the SAME +; fourth verdict as M15, for the SAME reason: colitur's own resolved name is +; [None] for any TEMPORAL-origin observed day, the large majority of this +; window. M1, M2, M3, M13 and M16's own subsets were each widened to absorb +; this axis where it fires alongside their pre-existing citation (see each +; entry's own note) rather than being folded into M18's own count, which +; covers only rows where [Observed_identity_unresolved] is the SOLE +; disagreement. +; ; FIVE MORE REMOVED, ef-rebootstrap (2026-08-12), same shape as M17's own ; removal above -- not re-adjudicated to a different verdict, just gone, ; because the underlying divergence stopped occurring: M4 (second @@ -102,8 +115,8 @@ ((id M2) (citation "RG 91 entry 27 (\"Officium sanctae Mariae in sabbato\") -- register §4") (verdict missalemeum) - (note "Every otherwise-unoccupied IV-class Saturday should carry the votive Office of the BVM (white; missalemeum's own titles cycle \"I\"..\"V Mass of the B. V. M. -- Salve, Sancta Parens\"). precedence_ef.ml's [band] already has an entry-27 comment acknowledging this row exists (corrected attribution, final fix wave: this note previously said temporal_ef.ml, but [band] is precedence_ef.ml's own function), but [Temporal_ef.temporal] never actually CONSTRUCTS this office -- an unimpeded Time-after-Epiphany/-Pentecost Saturday gets a bare ferial slug and season green instead. A genuine feature gap, not a citation dispute; tracked in register §6, not built in this task.") - (expected_rows 17)) + (note "Every otherwise-unoccupied IV-class Saturday should carry the votive Office of the BVM (white; missalemeum's own titles cycle \"I\"..\"V Mass of the B. V. M. -- Salve, Sancta Parens\"). precedence_ef.ml's [band] already has an entry-27 comment acknowledging this row exists (corrected attribution, final fix wave: this note previously said temporal_ef.ml, but [band] is precedence_ef.ml's own function), but [Temporal_ef.temporal] never actually CONSTRUCTS this office -- an unimpeded Time-after-Epiphany/-Pentecost Saturday gets a bare ferial slug and season green instead. A genuine feature gap, not a citation dispute; tracked in register §6, not built in this task. REFRESHED (ef-rg112-rg110 task): expected_rows moved 17 -> 22, for the SAME reason M1/M3/M16 below move too -- the new observed-identity axis (test_oracle.ml's own header) now ALSO fires on 5 Paschaltide BVM-Saturday dates that used to match CLEANLY (colour already white there, RG 119, so the pre-existing [Colour_f]-only check never even reached these 5 rows; M2's own comment already noted \"every Paschaltide occurrence... never reaches this predicate at all\" -- no longer true once [Observed_identity_unresolved] alone is enough to reach it). Not a new divergence, the identical feature gap surfacing on a second axis -- derived from the comparator's own failure output (test_layer_m_counts_match_citations), not hand-counted.") + (expected_rows 22)) ((id M3) (citation "RG 87 (Minor Litanies/Rogations, Mon/Tue before Ascension) -- the SAME citation as the lectio allow-list's own C8 (data/ef/expected-divergences.sexp)") (verdict colitur) @@ -149,3 +162,8 @@ (verdict missalemeum) (note "27 March 2026 (Friday of Passion Week): colitur admits \"St. John Damascene\" (a real Class3 universal feast that genuinely falls that day, data/ef/sanctoral.sexp's own john-damascene entry, 27 March); missalemeum shows \"For Our Lady of the Seven Sorrows\" instead. The SAME standing gap M13 already names: the Seven-Sorrows-of-Passion-Friday commemoration is confirmed real in the primary text but not implemented anywhere in temporal_ef.ml, so colitur has no candidate for it and falls back to whichever ordinary Class3 saint actually wins that Friday. Verdict missalemeum: colitur is missing a real, primary-cited office, not differently opinioned. Register §6 open item (the same one M13's own note already tracks). Only 2026 shows here as an IDENTITY mismatch -- 2027's Friday of Passion Week IS 19 March, M13's own date, where identity comparison cannot even be reached (M13's own rank/colour mismatch already excludes that day from count-matched identity comparison, folded into M13's own widened subset above). NOTE for whoever builds the office (fix round 1, coordinator finding 7): 27 March 2026 is a III-class day, where RG 111(d) admits TWO commemorations -- yet missalemeum admits only the Seven Sorrows and DISPLACES John Damascene entirely, not merely drops him to second place. A naive implementation (one more ordinary III-class commemoration competing for the day's two slots) would give colitur two commemorations where missalemeum shows one; whatever privilege the Seven Sorrows carries must itself explain the exclusion, not just win admission.") (expected_rows 1)) + ((id M18) + (citation "test_oracle.ml's own header, \"COMMEMORATION IDENTITY\" section, restated for the OBSERVED axis (ef-rg112-rg110 task) -- not an RG citation, a comparator LIMIT: Rite_ef.Temporal_ef never sets an English [names] field on any candidate it builds, the SAME limit M15 already names for a commemoration, now visible for the OBSERVED day itself now that the observed-identity axis exists") + (verdict unresolvable) + (note "373 of the 730 days in this window -- the overwhelming majority of days whose observed celebration is TEMPORAL-origin (an ordinary Sunday, a feria, a movable named feast including Holy Family itself), which never carries an English name on colitur's side. Not a rubric dispute and not a data gap either engine is wrong about -- a LIMIT of this comparator, honestly counted rather than silently passed, per the brief's own explicit instruction (\"a day whose observed identity cannot be resolved must be a counted, allow-listed outcome, never a silent skip\"). Gated on the diff SHAPE alone (exactly, and only, observed-identity-unresolved), not a literal date list the way every other entry in this file is -- at this population size a date list would itself be the \"pattern that could silently widen\" this file's own header warns against, for the opposite reason a date RANGE is normally risky: the predicate (colitur's own resolved name is [None]) is the precise, falsifiable evidence, the same shape M2's own title-substring predicate already uses instead of enumerating dates, just keyed on presence-of-a-name rather than a title string. Building an English name onto every temporal-cycle candidate (a data/lectionary-bootstrap task, Plan 4, out of this task's scope -- register §6, the same open item M15's own note already tracks) would resolve this entry to Matched for every one of these days it does not instead expose as a REAL divergence (Holy Family's own two dates in this window, 2026-01-11 and 2027-01-10, are counted here, not separately -- the name comparison genuinely cannot distinguish \"Holy Family\" from any other unnamed Sunday, so proving Holy Family's own correctness rests on the golden pins and the differential's own C15, not this axis). Derived directly from the comparator's own failure output (test_layer_m_counts_match_citations), not hand-counted first and cross-checked after: 373.") + (expected_rows 373)) diff --git a/test/test_oracle.ml b/test/test_oracle.ml index ae5c396..7068af9 100644 --- a/test/test_oracle.ml +++ b/test/test_oracle.ml @@ -726,25 +726,86 @@ let m16_dates = [ "2026-03-27" ] entry needed at all -- removed, not re-adjudicated to a different verdict, since there is no longer a divergence to name. *) +(* M18 -- ef-rg112-rg110 task: the gap this file's own header now names under + "COMMEMORATION IDENTITY", restated for the OBSERVED axis. colitur's own + observed celebration carries an English name ({!Celebration.t}.names) + ONLY for a SANCTORAL-origin day (a saint's feast winning outright); a + TEMPORAL-origin one -- an ordinary Sunday, a feria, a movable named feast + including Holy Family itself -- never does ({!Rite_ef.Temporal_ef}'s own + [build] has no [en "..."] string anywhere in it, this file's own header + again). That is the OVERWHELMING majority of days in any calendar (saints' + feasts are common, but far from every day), so this is a single + STRUCTURAL predicate -- [Observed_identity_unresolved] alone, nothing + else disagreeing -- not a literal date list the way every other entry in + this file is: at 374 of the 730 days in this window, a list would be + exactly the "range/pattern that could silently widen" this file's own + header explicitly avoids elsewhere, for the OPPOSITE reason a range is + normally risky here -- the predicate itself (colitur's own name is + [None]) is the precise, falsifiable evidence, the same shape [M2]'s own + title-substring predicate already uses instead of a date list, just keyed + on presence-of-a-name rather than a title string. NOT a rubric dispute + and NOT a data gap either engine is wrong about -- a LIMIT of this + comparator itself, honestly counted rather than silently passed, per the + brief's own explicit instruction ("a day whose observed identity cannot + be resolved must be a counted, allow-listed outcome, never a silent + skip"), the SAME discipline [M15] already established for an unresolvable + COMMEMORATION, applied here for the first time to the OBSERVED day. Fixing + this at the root (giving every temporal-cycle candidate an English name) + is a data/lectionary-bootstrap task (Plan 4), not something this + comparator can do for itself -- register §6 tracks it, the same open item + [M15]'s own note already points to. *) let layer_m_reason (c : colitur_row) (o : oracle_row) diffs = if diffs = [] then None - else if List.mem c.c_date m1_dates && subset diffs [ Rank; Colour_f; Comm_presence ] then Some "M1" - else if contains_substring o.o_title ~needle:bvm_saturday_title && diffs = [ Colour_f ] then Some "M2" - else if List.mem c.c_date m3_dates && diffs = [ Colour_f ] then Some "M3" + (* M1's own subset widened (this task): colitur's observed day on both + dates is TEMPORAL-origin (the Sunday itself, RG33's own point -- the + vigil should never have displaced it), so it now ALSO carries + [Observed_identity_unresolved] -- the same root cause the file's other + widened entries below share, restated for this one's own shape. *) + else if List.mem c.c_date m1_dates + && subset diffs [ Rank; Colour_f; Comm_presence; Observed_identity_unresolved ] + then Some "M1" + (* M2's own subset widened (this task): every BVM-Saturday date's observed + celebration is temporal-origin (the ordinary Saturday feria colitur + computes, not the distinct Office of the BVM missalemeum's title + names -- M2's own gap), so [Observed_identity_unresolved] now fires + alongside [Colour_f] where it used to fire alone, AND alone on its own + on every Paschaltide occurrence M2's own comment already says never + reached this predicate before (colour already agrees there; only the + new axis has anything left to say). *) + else if contains_substring o.o_title ~needle:bvm_saturday_title + && subset diffs [ Colour_f; Observed_identity_unresolved ] + then Some "M2" + (* M3's own subset widened (this task): the Rogation Monday feria colitur + observes is temporal-origin, same root cause as M1/M2 above. *) + else if List.mem c.c_date m3_dates && subset diffs [ Colour_f; Observed_identity_unresolved ] then + Some "M3" else if List.mem c.c_date m5_dates && diffs = [ Comm_presence ] then Some "M5" else if List.mem c.c_date m8_dates && diffs = [ Comm_presence ] then Some "M8" else if List.mem c.c_date m10_dates && diffs = [ Comm_presence ] then Some "M10" else if List.mem c.c_date m11_dates && diffs = [ Comm_presence ] then Some "M11" else if List.mem c.c_date m12_dates && diffs = [ Comm_count ] then Some "M12" - (* M13's own subset widened (Task B): the same underlying gap (the Seven - Sorrows commemoration is never constructed at all) now ALSO surfaces - as [Comm_identity_unresolved] on this date, since colitur's own - admitted commemoration there is temporal-origin (no English name) -- - one root cause, one id, both axes it touches. *) - else if List.mem c.c_date m13_dates && subset diffs [ Rank; Colour_f; Comm_identity_unresolved ] then - Some "M13" + (* M13's own subset widened AGAIN (this task, following the SAME pattern + Task B's own widening comment below records): colitur's observed + celebration here is Joseph, SANCTORAL-origin, so its name IS + resolvable -- and disagrees with missalemeum's own title outright + ([Observed_identity_mismatch], not [_unresolved]), the SAME underlying + gap (the Seven Sorrows commemoration is never constructed, so colitur + has no candidate to observe OR commemorate in its place) now visible + on a THIRD axis. *) + else if List.mem c.c_date m13_dates + && subset diffs [ Rank; Colour_f; Comm_identity_unresolved; Observed_identity_mismatch ] + then Some "M13" else if List.mem c.c_date m15_dates && diffs = [ Comm_identity_unresolved ] then Some "M15" - else if List.mem c.c_date m16_dates && diffs = [ Comm_identity_mismatch ] then Some "M16" + (* M16's own subset widened (this task): colitur's observed celebration + here is the temporal Passiontide feria (John Damascene is only a + COMMEMORATION on this Feast-status-losing day -- band picks the + temporal candidate outright at Class3 rank, register's own account of + this date), so [Observed_identity_unresolved] now fires alongside the + pre-existing [Comm_identity_mismatch]. *) + else if List.mem c.c_date m16_dates + && subset diffs [ Comm_identity_mismatch; Observed_identity_unresolved ] + then Some "M16" + else if diffs = [ Observed_identity_unresolved ] then Some "M18" else None (* ---------------------------------------------------------------------- *) -- cgit v1.3 From 7005578fa4a3031b8174ba0d27b64b29fdfd4799 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 13 Aug 2026 09:21:05 +0200 Subject: data(ef): fix round 1 (F6) -- restore C1's provenance record for 361 The previous refresh's own note recorded HOW 368 was derived (a Python cross-check against the comparator's own failure output, not hand-counted and not copied from a green run); this task's rewrite explained WHY 361 replaces it (C15's own split) but dropped the provenance sentence, stating 368 -> 361 with no record of how the new number was checked. Restored: 361 read directly from the OCaml comparator's own failure output, with the 368-minus-7 arithmetic noted as corroboration, not the derivation. --- data/ef/expected-divergences.sexp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'data/ef') diff --git a/data/ef/expected-divergences.sexp b/data/ef/expected-divergences.sexp index 8e104d9..283c3bc 100644 --- a/data/ef/expected-divergences.sexp +++ b/data/ef/expected-divergences.sexp @@ -45,7 +45,7 @@ ((id C1) (citation "RG 72-73 (Nativity/Epiphany season boundary, Jan 1-13) + RG 119a (white through \"expletum tempus Epiphaniae\"); register §3c item 1") (verdict colitur) - (note "6-13 January is Christmastide in colitur, matching RG 72-73's explicit boundary at 13 January (corroborated independently by RG 119a's colour rule, §3b). lectio's efSeason switches to time-after-epiphany on 6 January. The season disagreement cascades into colour (green vs white) and, on 7-8 January specifically, into the ferial slug family name (colitur's ef-christmas-2- vs lectio's ef-time-after-epiphany-1- for the same two days). REFRESHED (ef-rebootstrap fixture refresh, 2026-08-12): expected_rows moved 361 -> 368. NOT a new divergence -- the closed C13's own 7 rows (13 January in the 7 years it falls on a Sunday) fold back in here: lectio's fix wave independently fixed its own equivalent of the RG16(a) defect C13 used to allow-list, so on all 7 of those Sunday years lectio's slug now matches colitur's `commemoration-of-the-baptism-of-the-lord` too (not just rank/colour), leaving season as the ONLY residual difference on those rows -- squarely inside C1's own existing shape (diffs subset of [Season;Colour;Slug] with the Slug-diff escape clause unused). REFRESHED AGAIN (ef-rg112-rg110 task, branch ef-rg112-rg110): expected_rows moved 368 -> 361, back to its PRE-ef-rebootstrap value, but for a THIRD, different reason -- SPLIT OUT to its own new entry, C15, not silently re-absorbed: colitur now BUILDS Holy Family (RG 17(b)) and, on these same 7 dates, correctly observes it in the fixed Baptism's place (RG 91 entry 14, RG 112(a)), so colitur's own slug there changes from `commemoration-of-the-baptism-of-the-lord` (which happened to already match lectio's own slug) to `ef-time-after-epiphany-sunday-1` (Holy Family's own, lectio has no equivalent) -- a genuine SLUG divergence now, no longer inside C1's own [Season]-only shape. See C15's own entry for the full account.") + (note "6-13 January is Christmastide in colitur, matching RG 72-73's explicit boundary at 13 January (corroborated independently by RG 119a's colour rule, §3b). lectio's efSeason switches to time-after-epiphany on 6 January. The season disagreement cascades into colour (green vs white) and, on 7-8 January specifically, into the ferial slug family name (colitur's ef-christmas-2- vs lectio's ef-time-after-epiphany-1- for the same two days). REFRESHED (ef-rebootstrap fixture refresh, 2026-08-12): expected_rows moved 361 -> 368. NOT a new divergence -- the closed C13's own 7 rows (13 January in the 7 years it falls on a Sunday) fold back in here: lectio's fix wave independently fixed its own equivalent of the RG16(a) defect C13 used to allow-list, so on all 7 of those Sunday years lectio's slug now matches colitur's `commemoration-of-the-baptism-of-the-lord` too (not just rank/colour), leaving season as the ONLY residual difference on those rows -- squarely inside C1's own existing shape (diffs subset of [Season;Colour;Slug] with the Slug-diff escape clause unused). REFRESHED AGAIN (ef-rg112-rg110 task, branch ef-rg112-rg110): expected_rows moved 368 -> 361, back to its PRE-ef-rebootstrap value, but for a THIRD, different reason -- SPLIT OUT to its own new entry, C15, not silently re-absorbed: colitur now BUILDS Holy Family (RG 17(b)) and, on these same 7 dates, correctly observes it in the fixed Baptism's place (RG 91 entry 14, RG 112(a)), so colitur's own slug there changes from `commemoration-of-the-baptism-of-the-lord` (which happened to already match lectio's own slug) to `ef-time-after-epiphany-sunday-1` (Holy Family's own, lectio has no equivalent) -- a genuine SLUG divergence now, no longer inside C1's own [Season]-only shape. See C15's own entry for the full account. PROVENANCE, fix round 1 (coordinator finding 6, restoring the discipline this entry's own prior refresh recorded and this round's rewrite had dropped): 361 read directly from the OCaml comparator's own failure output (test_layer_c_counts_match_citations's `Received` array, run against the widened C15 predicate/allow-list together, not before it existed) -- not hand-counted first and cross-checked after, and not 368 minus 7 taken on faith: the arithmetic matches C15's own independently-derived 7, which is corroboration, not the derivation itself.") (expected_rows 361)) ((id C6) (citation "RG 91 entry 17 (\"days within the Octave of the Nativity\")") -- cgit v1.3 From 9df26e2e91646925c5977d4bab22c0d510d3b3c1 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 13 Aug 2026 09:22:36 +0200 Subject: test(oracle): fix round 1 (F8) -- correct the M18 headline, name the blind 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. --- CLAUDE.md | 8 ++++- data/ef/expected-divergences-missalemeum.sexp | 2 +- test/test_oracle.ml | 52 ++++++++++++++++----------- 3 files changed, 40 insertions(+), 22 deletions(-) (limited to 'data/ef') diff --git a/CLAUDE.md b/CLAUDE.md index 20f3ebf..8915bc6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -124,7 +124,13 @@ against missalemeum; layer 5 pins ~30 dates. fix below: resolvable only for a SANCTORAL-origin observed day; a TEMPORAL-origin one (an ordinary Sunday, a feria, a movable named feast — 373 of 730 days in the 2026–2027 window) is `Observed_identity_unresolved`, - counted and allow-listed (`M18`), never silently skipped. Teeth proved and + counted and allow-listed (`M18`), never silently skipped. Full breakdown: + 331 of 730 days resolved (330 matching, 1 mismatched — Joseph vs the Seven + Sorrows, `M13`), 399 unresolved (373 in `M18`, 26 absorbed inside four + other entries' own widened subsets). The blind spot, precisely: 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. Teeth proved and reverted: corrupting one sanctoral saint's own English name on an OBSERVED day (rank/colour untouched) reddened the suite immediately with an `observed-identity-mismatch` and nothing else — the exact shape the diff --git a/data/ef/expected-divergences-missalemeum.sexp b/data/ef/expected-divergences-missalemeum.sexp index d7a1c8c..15f9cf2 100644 --- a/data/ef/expected-divergences-missalemeum.sexp +++ b/data/ef/expected-divergences-missalemeum.sexp @@ -165,5 +165,5 @@ ((id M18) (citation "test_oracle.ml's own header, \"COMMEMORATION IDENTITY\" section, restated for the OBSERVED axis (ef-rg112-rg110 task) -- not an RG citation, a comparator LIMIT: Rite_ef.Temporal_ef never sets an English [names] field on any candidate it builds, the SAME limit M15 already names for a commemoration, now visible for the OBSERVED day itself now that the observed-identity axis exists") (verdict unresolvable) - (note "373 of the 730 days in this window -- the overwhelming majority of days whose observed celebration is TEMPORAL-origin (an ordinary Sunday, a feria, a movable named feast including Holy Family itself), which never carries an English name on colitur's side. Not a rubric dispute and not a data gap either engine is wrong about -- a LIMIT of this comparator, honestly counted rather than silently passed, per the brief's own explicit instruction (\"a day whose observed identity cannot be resolved must be a counted, allow-listed outcome, never a silent skip\"). Gated on the diff SHAPE alone (exactly, and only, observed-identity-unresolved), not a literal date list the way every other entry in this file is -- at this population size a date list would itself be the \"pattern that could silently widen\" this file's own header warns against, for the opposite reason a date RANGE is normally risky: the predicate (colitur's own resolved name is [None]) is the precise, falsifiable evidence, the same shape M2's own title-substring predicate already uses instead of enumerating dates, just keyed on presence-of-a-name rather than a title string. Building an English name onto every temporal-cycle candidate (a data/lectionary-bootstrap task, Plan 4, out of this task's scope -- register §6, the same open item M15's own note already tracks) would resolve this entry to Matched for every one of these days it does not instead expose as a REAL divergence (Holy Family's own two dates in this window, 2026-01-11 and 2027-01-10, are counted here, not separately -- the name comparison genuinely cannot distinguish \"Holy Family\" from any other unnamed Sunday, so proving Holy Family's own correctness rests on the golden pins and the differential's own C15, not this axis). Derived directly from the comparator's own failure output (test_layer_m_counts_match_citations), not hand-counted first and cross-checked after: 373.") + (note "373 of the 730 days in this window carry this shape alone (M1/M2/M3/M16 absorb a further 26 where it fires ALONGSIDE their own pre-existing citation -- see each entry's own widened note; 373+26=399 is the axis's own full unresolved population). CORRECTED, fix round 1 (coordinator finding 8) -- the full breakdown, precisely: of 730 days, 331 are RESOLVED (colitur's own observed celebration carries a name) -- 330 resolved-and-MATCHING, 1 resolved-and-MISMATCHED (M13, Joseph vs the Seven Sorrows, already its own entry above) -- and 399 are UNRESOLVED (colitur's own name is [None]), split between this entry's own 373 and the 26 absorbed elsewhere. The BLIND SPOT this axis exists to close, stated precisely: a TEMPORAL-origin observed day silently replaced by a DIFFERENT temporal-origin observed day of the SAME RANK AND COLOUR -- exactly the shape that hid Holy Family from every layer before this task (rank 2/white on both sides, purely coincidental). This count PIN is what stands guard against that population growing silently in either direction: an implementation change that made MORE days temporal-origin-and-unresolvable, or fewer, changes 373 and fails the pin, even though the axis itself cannot say WHICH specific day moved or why. The overwhelming majority of days whose observed celebration is TEMPORAL-origin (an ordinary Sunday, a feria, a movable named feast including Holy Family itself) never carry an English name on colitur's side -- not a rubric dispute and not a data gap either engine is wrong about, a LIMIT of this comparator, honestly counted rather than silently passed, per the brief's own explicit instruction (\"a day whose observed identity cannot be resolved must be a counted, allow-listed outcome, never a silent skip\"). Gated on the diff SHAPE alone (exactly, and only, observed-identity-unresolved), not a literal date list the way every other entry in this file is -- at this population size a date list would itself be the \"pattern that could silently widen\" this file's own header warns against, for the opposite reason a date RANGE is normally risky: the predicate (colitur's own resolved name is [None]) is the precise, falsifiable evidence, the same shape M2's own title-substring predicate already uses instead of enumerating dates, just keyed on presence-of-a-name rather than a title string. Building an English name onto every temporal-cycle candidate (a data/lectionary-bootstrap task, Plan 4, out of this task's scope -- register §6, the same open item M15's own note already tracks) would resolve this entry to Matched for every one of these days it does not instead expose as a REAL divergence (Holy Family's own two dates in this window, 2026-01-11 and 2027-01-10, are counted here, not separately -- the name comparison genuinely cannot distinguish \"Holy Family\" from any other unnamed Sunday, so proving Holy Family's own correctness rests on the golden pins and the differential's own C15, not this axis). Derived directly from the comparator's own failure output (test_layer_m_counts_match_citations), not hand-counted first and cross-checked after: 373.") (expected_rows 373)) diff --git a/test/test_oracle.ml b/test/test_oracle.ml index 7068af9..35d4501 100644 --- a/test/test_oracle.ml +++ b/test/test_oracle.ml @@ -733,26 +733,38 @@ let m16_dates = [ "2026-03-27" ] TEMPORAL-origin one -- an ordinary Sunday, a feria, a movable named feast including Holy Family itself -- never does ({!Rite_ef.Temporal_ef}'s own [build] has no [en "..."] string anywhere in it, this file's own header - again). That is the OVERWHELMING majority of days in any calendar (saints' - feasts are common, but far from every day), so this is a single - STRUCTURAL predicate -- [Observed_identity_unresolved] alone, nothing - else disagreeing -- not a literal date list the way every other entry in - this file is: at 374 of the 730 days in this window, a list would be - exactly the "range/pattern that could silently widen" this file's own - header explicitly avoids elsewhere, for the OPPOSITE reason a range is - normally risky here -- the predicate itself (colitur's own name is - [None]) is the precise, falsifiable evidence, the same shape [M2]'s own - title-substring predicate already uses instead of a date list, just keyed - on presence-of-a-name rather than a title string. NOT a rubric dispute - and NOT a data gap either engine is wrong about -- a LIMIT of this - comparator itself, honestly counted rather than silently passed, per the - brief's own explicit instruction ("a day whose observed identity cannot - be resolved must be a counted, allow-listed outcome, never a silent - skip"), the SAME discipline [M15] already established for an unresolvable - COMMEMORATION, applied here for the first time to the OBSERVED day. Fixing - this at the root (giving every temporal-cycle candidate an English name) - is a data/lectionary-bootstrap task (Plan 4), not something this - comparator can do for itself -- register §6 tracks it, the same open item + again). CORRECTED, fix round 1 (coordinator finding 8) -- the precise + breakdown: of this window's 730 days, 331 are RESOLVED (330 matching, 1 + mismatched, [M13]); 399 are UNRESOLVED, split between this entry's own + 373 (the axis's sole disagreement) and 26 absorbed inside [M1]/[M2]/[M3]/ + [M16]'s own widened subsets, where it fires ALONGSIDE their pre-existing + citation. The BLIND SPOT this axis exists to close, stated precisely: a + TEMPORAL-origin observed day silently replaced by a DIFFERENT + temporal-origin observed day of the SAME RANK AND COLOUR -- exactly the + shape that hid Holy Family from every layer before this task. This is + the OVERWHELMING majority of days in any calendar (saints' feasts are + common, but far from every day), so this is a single STRUCTURAL + predicate -- [Observed_identity_unresolved] alone, nothing else + disagreeing -- not a literal date list the way every other entry in this + file is: at this population size, a list would be exactly the + "range/pattern that could silently widen" this file's own header + explicitly avoids elsewhere, for the OPPOSITE reason a range is normally + risky here -- the predicate itself (colitur's own name is [None]) is the + precise, falsifiable evidence, the same shape [M2]'s own title-substring + predicate already uses instead of a date list, just keyed on + presence-of-a-name rather than a title string. NOT a rubric dispute and + NOT a data gap either engine is wrong about -- a LIMIT of this comparator + itself, honestly counted rather than silently passed, per the brief's own + explicit instruction ("a day whose observed identity cannot be resolved + must be a counted, allow-listed outcome, never a silent skip"), the SAME + discipline [M15] already established for an unresolvable COMMEMORATION, + applied here for the first time to the OBSERVED day. The count pin below + ([test_layer_m_counts_match_citations]) is what stands guard against this + population growing (or shrinking) silently -- it cannot say WHICH day + moved or why, only that the total did. Fixing this at the root (giving + every temporal-cycle candidate an English name) is a data/lectionary- + bootstrap task (Plan 4), not something this comparator can do for itself + -- register §6 tracks it, the same open item [M15]'s own note already points to. *) let layer_m_reason (c : colitur_row) (o : oracle_row) diffs = if diffs = [] then None -- cgit v1.3