diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-22 16:40:07 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-22 16:40:24 +0200 |
| commit | 60e87914718dd2c8e69bb89d8cc48d6bef9bfc74 (patch) | |
| tree | 814f451ac97e61d8ab83a2e24877b1b5223734db /data/ef/expected-divergences.sexp | |
| parent | 219c0ca6884a634e83293c62b27cca990fa25854 (diff) | |
| download | colitur-60e87914718dd2c8e69bb89d8cc48d6bef9bfc74.tar.gz colitur-60e87914718dd2c8e69bb89d8cc48d6bef9bfc74.zip | |
feat(ef): implement the calendarium's bissextile February shift
The Missale Romanum's calendarium footnote for February (LT.txt:5011-5014,
scan-corroborated scan2.txt:3050-3058): in a leap year the sixth kalends of
March (24 February) is doubled rather than a 29th day appended, so St
Matthias moves 24->25 February and St Gabriel of Our Lady of Sorrows
27->28, with 24 February itself carrying no fixed office that year.
data/ef/expected-divergences-lms.sexp entry L3 tracked this as an open gap.
Implemented as the rubric's own general mechanism (every fixed entry from
24 through 28 February shifts one civil day later in a leap year), not as
"move these two named saints": the two readings are indistinguishable on
shipped data (nothing else is fixed in that window) and diverge only for a
future --overlay entry in the same range, which the mechanism reading
covers correctly and a two-saints special case would not. This project has
already been bitten once (RG 16(a)) by a rule implemented against shipped
data's coincidental shape rather than the rubric itself.
Kernel stays rite-agnostic: Rite.t gains a fixed_key field (Date.t -> (int
* int) option), the same seam easter already establishes, read only by
Layer.on_date's FIXED half -- the movable half (Easter_offset/Nth_weekday)
is untouched. Default is the identity mapping, an optional argument on
on_date, so every existing caller and every rite that supplies nothing is
byte-identical to before this field existed. Date.is_leap is exposed in
date.mli (already existed in date.ml) so the rite reads the kernel's own
single-sourced leap-year definition. The EF implementation lives in
Rite_ef.Temporal_ef.bissextile_fixed_key, fully cited, wired into
Rite_ef.context.
Blast radius, measured over the full 1583-9999 domain (Calendar.year run
twice per civil year, real fixed_key vs identity, every day diffed): all
2,041 leap years in the domain show a visible change for each saint;
6,983 individual liturgical days change total, zero unclassified, across
four shapes (Matthias vacates 24 Feb in 1,803 years / occupies 25 Feb in
1,811; Gabriel vacates 27 Feb in 1,699 / occupies 28 Feb in 1,670).
L3's own prior estimate (1,650 years, observed-outright only) is confirmed
close on the same definition (1,677 measured); the broader observed-or-
commemorated count is higher, not lower, showing the narrow estimate
undercounted visible impact rather than overcounting it.
The lectio differential (2005-2050 fixture) gains a new cited entry, C40
in data/ef/expected-divergences.sexp: lectio implements no such shift, so
every leap year in its window now diverges on the two shifted days (21
rows, not the naive 44 -- the comparator never compares commemorations, so
a side where the shifted saint has zero comparator-visible footprint on
both engines produces no row). The LMS Ordo's 2023-2024 fixture -- the
window L3 was originally found in -- now matches on the Creed comparison;
its formulary-override bucket count is corrected 182->181 (24 February
leaves the counted Proper population, becoming Own_slug-sourced). The
missalemeum oracle fixtures (2026-2027, 2038, 2035) cover no leap year and
are unaffected.
L3 is closed: converted from an active allow-list record to a prose
closure paragraph (L1's own precedent), citation preserved verbatim, fix
and measured blast radius recorded. The id-list assertion narrows to [L4]
alone, and the now-dead "2024-02-24" -> "L3" date mapping is removed.
Six golden values pinned across four new test cases: Matthias in a leap
year (both the vacated and occupied sides) and a common-year control;
Gabriel likewise, deliberately choosing a leap year where he is admitted
only as an ordinary commemoration rather than winning outright, a
different shape from Matthias's.
Mutation-tested: forcing fixed_key back to identity reddens exactly five
test cases -- the differential's Layer C count-pin (C40 drops to 0 actual
vs 21 expected), the LMS Ordo's Creed and formulary-bucket checks, and
both new golden pins -- confirming the tests actually exercise the fix.
Reverted; dune test, the exhaustive sweep, and make check are all green.
Diffstat (limited to 'data/ef/expected-divergences.sexp')
| -rw-r--r-- | data/ef/expected-divergences.sexp | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/data/ef/expected-divergences.sexp b/data/ef/expected-divergences.sexp index 19ff2ef..632854c 100644 --- a/data/ef/expected-divergences.sexp +++ b/data/ef/expected-divergences.sexp @@ -116,6 +116,21 @@ WHAT THIS ENTRY ALSO RESTS ON. Two things, neither of them a day-level witness. Gated on lectio's own slug being one of the three vigils this clause can reach and colitur's not being a vigil -- identity on both sides, not a diff-set shape. The Assumption's and the Ascension's vigils are absent from that list because their I-class feasts always keep their own day: 0 occurrences across the whole domain, measured rather than assumed.") (expected_rows 10)) + ((id C40) + (citation "The Missale Romanum's own CALENDARIUM table, February, footnote (docs/research/LT.txt:5011-5014, scan-corroborated docs/research/scan2.txt:3050-3058): \"In anno bissextili mensis februarius est dierum 29, et festum S. Matthiae celebratur die 25 februarii, ac festum S. Gabrielis a Virgine perdolente 28 februarii, et bis dicitur sexto calendas, id est die 24 et die 25\" -- in a leap year February has 29 days, St Matthias is kept on 25 February (not 24), St Gabriel of Our Lady of Sorrows on 28 February (not 27), and the sixth kalends of March is said twice. Implemented in Rite_ef.Temporal_ef.bissextile_fixed_key, threaded through Colitur_kernel.Rite.t's new [fixed_key] field (bissextile-shift task, 2026-08-22). Not RG-numbered -- a calendarium footnote, not a Rubricae Generales paragraph.") + (verdict colitur) + (note "lectio builds no such shift at all: checked directly against the fixture, Matthias sits at 24 February and Gabriel of Our Lady of Sorrows at 27 February in EVERY ONE of the 11 leap years the 2005-2050 window covers (2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2044, 2048), never moved. colitur now moves both, per the calendarium's own footnote, so every leap year in this window diverges on the two shifted civil days: colitur vacates 24/27 February (the saint moves away) and occupies 25/28 February instead (the saint newly appears there), while lectio keeps the pre-shift assignment throughout. + +19 Matthias rows + 2 Gabriel rows = 21, not the naive 11-years x 2-sides x 2-feasts = 44 ceiling: this comparator, BY DESIGN (see this file's own header), never compares commemorations -- only observed slug/rank/colour/citations -- so a side where the shifted saint has ZERO comparator-visible footprint, on both engines, whether pre- or post-shift, produces no row even though a real change happened underneath (the full-domain probe below, which DOES track commemorations, still counts it). + +MATTHIAS fires on both sides (24 vacated AND 25 occupied) in 8 of the 11 years; in the remaining 3 (2008, 2024, 2036) exactly one side is missing, and in every one of the three the missing side is a SUNDAY -- 2008-02-24 and 2036-02-24 (Matthias already loses outright to that Sunday whichever engine or shift-state is asked, so the vacated side shows no change); 2024-02-25 (the occupied side: colitur's post-shift Matthias loses outright to the 2nd Sunday of Lent, I class, with no commemoration surviving RG111's own tight cap -- Matthias's footprint there is genuinely zero, not merely uncompared). A Sunday's own observed slug is unaffected by this shift either way, so whichever side coincides with one contributes nothing comparator-visible; only the other, non-Sunday side shows the real new divergence. 2024-02-24 is L3's own original date (data/ef/expected-divergences-lms.sexp), now confirmed independently by a second, larger fixture. + +GABRIEL (Class3, weaker than Matthias's Class2/Apostle rank) fires in only 2 of the 11 years (2028 occupied, 2044 vacated) because in the other 9 his position is already dominated by a Class3-or-stronger competing office both before and after the shift, so his own presence is commemoration-only throughout -- invisible to this comparator on either side. He surfaces only where the position happens to be a plain, unprivileged Class4 feria weak enough for his own Class3 to win outright: 2028-02-28 (colitur: gabriel-of-our-lady-of-sorrows, Class3, White, beating ef-septuagesima-3-monday, Class4) and 2044-02-27 (lectio still shows gabriel there unmoved, Class3, White; colitur's post-shift 27th falls to RG78's own votive BVM-Saturday office instead, also White, hence the colour match but slug/rank/citation mismatch in that row). Every one of the 21 rows was read directly off the comparator's own failure output, not apportioned by hand. + +Diff shapes: most rows carry [Slug_f; Rank; Colour_f; First_f; Gospel_f] (the temporal office on one side and the saint's own Class2/3 proper on the other differ in rank too); a handful carry only [Slug_f; Colour_f; First_f; Gospel_f] where the competing temporal office happens to share Matthias's own Class2 (the privileged Lenten Ember Friday/Saturday, 2024 and 2040) or Gabriel's own White (a BVM Saturday, 2044-02-27's own vacated row). Season never differs on any of the 21 -- both sides stay in whichever season that Sunday-relative week already put them in, regardless of which fixed entry, if any, sits on the day. + +BLAST RADIUS, MEASURED, full 1583-9999 domain (not merely this fixture's 2005-2050 window): 6 983 liturgical days change, zero unclassified, across all 2 041 leap years in the domain -- see data/ef/expected-divergences-lms.sexp's own now-closed L3 entry for the full figures (this entry's own 21-row 2005-2050 population is the expected subset of that domain-wide count landing inside the fixture's own window: 11 leap years x up to 2 new rows each, minus the three already-explained overlaps above).") + (expected_rows 21)) ; C8 -- CLOSED, REMOVED (2026-08-18): 0 of 16801 rows, was 26. lectio builds ; Rogation Monday and Tuesday now (RG 87, Easter+36/+37, violet under ; RG 128(d)). The Wednesday is NOT built there and deliberately so: Easter+38 |
