<feed xmlns='http://www.w3.org/2005/Atom'>
<title>colitur.git/test/test_differential.ml, branch v0.10.1</title>
<subtitle>deterministic OCaml engine to compute and validate liturgical calendars for multiple rites, template-driven output to year 9999</subtitle>
<id>https://git.labunix.xyz/colitur.git/atom?h=v0.10.1</id>
<link rel='self' href='https://git.labunix.xyz/colitur.git/atom?h=v0.10.1'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/'/>
<updated>2026-08-21T12:42:30Z</updated>
<entry>
<title>feat(ef): implement RG 33's third omission trigger</title>
<updated>2026-08-21T12:42:30Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-21T12:42:30Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=12b97761019cfa02ca0da8a5fb50ef815d07685c'/>
<id>urn:sha1:12b97761019cfa02ca0da8a5fb50ef815d07685c</id>
<content type='text'>
RG 33 omits a II/III-class vigil in three cases: it falls on a Sunday, it
falls on a I-class feast, "vel si festum cui praemittitur in alium diem
transferri aut ad commemorationem reduci contingat". Only the first two
were built; the third was recorded in precedence_ef.ml as unimplemented on
the grounds that no witness existed in the shipped data. That reasoning was
wrong, and the rule fires on 1 744 days across 1583-9999.

Both halves of the clause reduce to one observable question -- is the feast
the OBSERVED office on the following day (RG 34 puts it there) -- so the
kernel asks it once per candidate, after place_transfers has settled the
year. No fixed point is needed: a vigil is a candidate only on its own day,
never on its feast's, so suppressing it cannot change what the next day
observes. Precedence.rules gains vigil_feast, which returns the slug of the
feast a vigil precedes; the kernel cannot infer that itself, because only
two of the five vigil/feast pairs share a slug stem.

Blast radius, measured pre-change binary vs HEAD over the whole domain and
classified: 1 744 days, three shapes, zero unexplained. 1 199 are the feast
reduced to a commemoration (10 August on a Sunday, St Lawrence); 478 and 67
are the feast transferred under RG 96 after the Sacred Heart or Corpus
Christi takes its day. The Assumption's and the Ascension's vigils never
qualify -- their I-class feasts always keep their own day.

Independently witnessed, which is unusual here. The published Ordo -- the
only witness outside the Divinum Officium -&gt; missalemeum -&gt; lectio lineage
-- omits St Lawrence's vigil on 2025-08-09, agreeing with colitur against
both engines. That date had been read earlier as an Ordo gap; the Ordo was
right, and correcting the misreading is what surfaced this clause. On
2027-08-09 the feast does keep its day and the Ordo omits a vigil colitur
correctly keeps, which is a genuine Ordo gap.

Allow-lists: C39 (lectio, 10 rows) and a 2038 oracle class citing the
register, the 2026-2027 window having no instance. The golden pin asserting
St Lawrence's vigil is violet moved 2025 -&gt; 2027; its own comment had
reasoned about the vigil's weekday and missed that RG 33 also looks at the
feast's. Two new pins cover both shapes of the clause.

The vigil/feast table is built with Slug.of_string_exn: mutation testing
showed that of_string plus Result.to_option turns a typo into None, which
this hook's contract reads as "not a vigil", switching the rule off in
silence. Two tests assert the table against the shipped data in both
directions.
</content>
</entry>
<entry>
<title>test(differential): C14 and C15 closed -- only slug vocabulary remains</title>
<updated>2026-08-18T15:35:53Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T15:35:53Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=897c274fd28402159ca6d45eedc1257b1ce98696'/>
<id>urn:sha1:897c274fd28402159ca6d45eedc1257b1ce98696</id>
<content type='text'>
lectio adopted the last two Missal corrections colitur argued:

  C14  3 -&gt; 0   RG 96(a)/97/98. lectio resolved each impeded I-class feast's
                transfer independently, so in 2008, 2035 and 2046 St Joseph and
                the Annunciation both walked onto the Monday after Low Sunday
                and Joseph, losing there, was observed on no day of those years
                at all. It now resolves the year's transfers as a set: the
                Annunciation takes the Monday as its sedes propria, Joseph the
                Tuesday.
  C15  7 -&gt; 0   The Holy Family propers' own 13-January rubric, "sine
                commemoratione Baptismatis D.N.I.C.". lectio kept the Baptism
                as the observed office on all seven such years in 2005-2050.

Those were the last two BEHAVIOUR classes. What is left is C1 (138) and C6
(119), both pure slug vocabulary.

Measured across the whole fixture, applying only the season normalisation the
test already applies: 579 of 16801 days differ, and every one of them differs
on the SLUG ALONE. Zero days differ on season, rank, colour, Epistle or Gospel.
(The test's own norm_slug table already maps 322 of the 579; the 257 left are
C1 and C6. The field profile is the same either way.)

So the two engines now agree on every liturgically meaningful field on every
day of 2005-2050. The residue is what the two projects call things --
ef-christmas-2-friday against ef-time-after-epiphany-1-friday for the same day,
same Mass. Aligning it means renaming lectio's slugs, and those are keys: its
lectionary, clectio's generated tables and any user overlay are built on them.
Left as vocabulary rather than forced.

Fixture refreshed against lectio e713da2; 13 rows changed, colitur agrees with
all of them. 24 divergence classes at the start of this work, 2 now.
</content>
</entry>
<entry>
<title>test(differential): C31 closed -- 4 classes left, 257 of 267 rows are naming</title>
<updated>2026-08-18T15:18:16Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T15:18:16Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=5773d603a2936638654f8e6bd8e595240de4203a'/>
<id>urn:sha1:5773d603a2936638654f8e6bd8e595240de4203a</id>
<content type='text'>
The ferias between Epiphany and the first Sunday after it repeat Epiphany's
own Mass in lectio now; they had been taking the Mass of the Sunday that
follows them.

  C31  98 -&gt; 0
  C1   40 -&gt; 138   grew, and changed character

C1 is now SLUG VOCABULARY ONLY, and its note says so. Season, rank, colour and
both citations agree with colitur on every day of the January window; what
differs is the identifier -- ef-christmas-2-thursday against
ef-time-after-epiphany-1-thursday for the same day with the same Mass. C6 is
the same shape.

That is 257 of the 267 remaining rows. Aligning the vocabularies would mean
renaming lectio's slugs, and those are keys: its own lectionary, clectio's
generated tables and any user overlay are built on them. Recorded as
vocabulary rather than closed, because the rows do differ -- just not in
anything a reader of either engine's output sees.

Measured for 2026: season, rank and colour agree on all 365 days; 14 days
differ and every one differs on the slug alone.

5 classes -&gt; 4, agreement 98.4%.
</content>
</entry>
<entry>
<title>test(differential): C20 and C38 closed -- agreement 98.4%</title>
<updated>2026-08-18T15:13:03Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T15:13:03Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=60db67eb2246d748d1e8e55047cef7d3d7843c4e'/>
<id>urn:sha1:60db67eb2246d748d1e8e55047cef7d3d7843c4e</id>
<content type='text'>
lectio carries the readings of the nine Common-routed saints and of three more
that had proper Masses but no reading at all. Every day of 2005-2050 now
resolves a reading there; four days used to come back empty.

C38's own note said it could not close without lectio gaining a Commons
concept. The readings arrived instead of the abstraction, which was enough:
each Common resolves to one first/gospel pair for the saint that names it, so
a table plus assignment layer would have bought indirection and nothing else.

  C20  14 -&gt; 0
  C38  70 -&gt; 0

7 classes -&gt; 5, 351 rows -&gt; 267, agreement 97.9% -&gt; 98.4%.
</content>
</entry>
<entry>
<title>test(differential): seven classes closed -- agreement 93.9% to 97.1%</title>
<updated>2026-08-18T14:51:45Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T14:51:45Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=3c770951011d2fd4911cd98793683bef69ac2d27'/>
<id>urn:sha1:3c770951011d2fd4911cd98793683bef69ac2d27</id>
<content type='text'>
lectio gained the Passiontide week split and thirteen lectionary entries.

  C23  230 -&gt; 0   Holy Week's own six Masses
  C32   99 -&gt; 0
  C35   60 -&gt; 0   the first weeks after Epiphany and Pentecost (RG 299)
  C33   46 -&gt; 0   Corpus Christi
  C34   46 -&gt; 0   the Sacred Heart
  C26   43 -&gt; 0   Passion Tuesday
  C19    7 -&gt; 0   the Holy Family week-index residue

  C1    75 -&gt; 40
  C31   63 -&gt; 98  GREW

The Passiontide split is the one that carried most of this. efWeek had no
Passiontide case, so both weeks numbered 0 and every day of Holy Week took the
slug of its Passion-week namesake -- one set of readings for two weeks with
entirely different Masses. Good Friday was reading Passion Friday's.

C31 growing is the same bookkeeping as C1's earlier growth and is recorded in
its own note: C32 and C35 closed, and rows that carried several causes now
carry only this one. Nothing new disagrees.

17 classes -&gt; 10, 1019 rows -&gt; 488, agreement 93.9% -&gt; 97.1%.

What remains is almost entirely NAMING rather than disagreement: C6 (119) is
colitur's ef-nativity-octave-day-N against lectio's ef-christmas-N-weekday on
days where both now read the same Mass, and C1 (40) is the same shape in the
January window.
</content>
</entry>
<entry>
<title>test(differential): C8 closed, C6 narrowed to naming</title>
<updated>2026-08-18T14:38:15Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T14:38:15Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=71054def597178f8143ed121e33460558456cce6'/>
<id>urn:sha1:71054def597178f8143ed121e33460558456cce6</id>
<content type='text'>
lectio gained Rogation Monday and Tuesday (RG 87, violet under RG 128(d)) and
the Missal's own Mass for the weekdays within the Octave of the Nativity
("Diebus infra octavam Nativitatis Domini", Titus 3:4-7 / Luke 2:15-20).

  C8   26 -&gt; 0    CLOSED
  C6  119 -&gt; 119  narrowed: the cause halved, the count did not

C6 is worth reading carefully rather than skimming the number. Its rows no
longer differ on First_f or Gospel_f at all -- the two engines now read the
SAME Mass on 29-31 December, where lectio previously served the Sunday's. What
is left is Slug_f alone, colitur's ef-nativity-octave-day-N against lectio's
ef-christmas-N-weekday. That is vocabulary, not disagreement. The count did not
move because the entry's gate already admitted a Slug_f-only subset, which is
exactly the case where a row count is a misleading summary.

17 classes, 1019 rows, agreement 93.9%.
</content>
</entry>
<entry>
<title>test(differential): C17 closed -- the largest divergence class is gone</title>
<updated>2026-08-18T14:29:22Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T14:29:22Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=1528d6533bbce035f78b92128fd9b2bb13e05db4'/>
<id>urn:sha1:1528d6533bbce035f78b92128fd9b2bb13e05db4</id>
<content type='text'>
lectio built the votive Office of Our Lady on Saturday (RG 78) and then said
RG 309(a)'s own Mass for it. Both halves were needed: RG 78 keeps the office
and gives it white, RG 309(a) picks among the Missal's five seasonal
formularies. Fixing only the first leaves the day announcing Our Lady and
reading the feria's Mass -- the bug colitur itself shipped briefly and fixed
in its v0.3.0.

  C17  439 -&gt; 0     CLOSED -- the largest class between the two engines
  C31  103 -&gt; 63    Saturdays that carried both causes; only this one left
  C35   69 -&gt; 60    same
  C1    35 -&gt; 75    GREW

C1 growing is not a regression and is recorded as such in its own note: the
January Saturdays C17 used to absorb now differ only on the slug vocabulary
C1 already covers, so they land there instead. Rows moved between entries as
the larger cause was removed.

Also in this refresh, from the same session: weeks after Epiphany now count
from the first Sunday after it rather than from 6 January, which took C19
from 35 to 7 -- what remains there is the Holy Family interaction, a different
cause needing RG 17(b) in lectio.

19 classes -&gt; 18, 1493 rows -&gt; 1045, agreement 91.1% -&gt; 93.8%.
</content>
</entry>
<entry>
<title>test(differential): refresh the fixture -- three more corrections adopted</title>
<updated>2026-08-18T14:05:28Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T14:05:28Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=80096d1227ea7406a88a774bf258bc3ac603eb8f'/>
<id>urn:sha1:80096d1227ea7406a88a774bf258bc3ac603eb8f</id>
<content type='text'>
lectio has taken three further corrections colitur argued from the Missal: the
twelve RG 124 colours (red is for Apostles, Evangelists and Martyrs, and
missalemeum had the rule inverted in both directions), Good Friday's black
under RG 128(b) with RG 132, and RG 72's Christmas Time boundary at 13 January
inclusive.

864 rows changed. Two classes closed outright and two moved:

  C18  450 -&gt; 0    the RG 124 colours -- the LARGEST single class in this file
  C36   46 -&gt; 0    Good Friday's colour
  C1   159 -&gt; 35   the season boundary stopped differing
  C23  184 -&gt; 230  Good Friday's rows fold back, the split no longer needed

C36 is closed rather than kept at zero because the split it represented has
dissolved: it existed only to hold Good Friday apart while its diff set had a
third member, and with the colour agreeing the rows are the exact pair C23 has
always gated on. Restoring 230 is not a regression, it is the number returning
to what it was before the split.

Cited classes 24 -&gt; 19, divergent rows 2252 -&gt; 1521, agreement 86.6% -&gt; 90.9%.

The percentage is again the least interesting part. C18 alone was 450 days on
which the two engines agreed about nothing and now agree because both apply
RG 124 the same way round.
</content>
</entry>
<entry>
<title>test(differential): refresh the lectio fixture -- the lineage inverted</title>
<updated>2026-08-18T12:37:34Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T12:37:34Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=906a84e626ed49c6bd995c6fad7d53355baf582a'/>
<id>urn:sha1:906a84e626ed49c6bd995c6fad7d53355baf582a</id>
<content type='text'>
Every previous refresh of this fixture carried lectio's answers TO colitur,
because colitur's data was bootstrapped from lectio. This one carries
colitur's answers BACK. lectio has merged eight field corrections colitur
argued from the 1962 Missal: ubaldus and didacus promoted from commemoration
to III-class feast on the Missal's own calendarium, both August vigils
recoloured violet under RG 128, and both Ember Saturdays' readings, which
lectio had carrying St Thomas's and St Matthew's Masses respectively.

227 of the 16801 rows changed. Three cited classes went to zero and are
CLOSED and REMOVED, citations preserved in the register, the same discipline
C2-C5, C7, C9-C13, C21, C22 and C25 already record:

  C27  40 -&gt; 0   the Advent Ember Saturday's readings
  C28  40 -&gt; 0   the September Ember Saturday's readings
  C37  77 -&gt; 0   the two vigil colours

C37 is worth noting by name: its own note called the shared lineage "the
sharpest demonstration in the project", colitur and lectio and missalemeum all
carrying the same two wrong colours. Two of the three now carry the right one.

C38 NARROWED rather than closed, and the distinction matters. Its identity
half is gone -- lectio ranks both saints class-3 now -- but the same 70 rows
still differ on readings, because both saints take their Mass from a Common
and lectio has no Commons concept to resolve one. It is gated on
diffs = [First_f; Gospel_f] exactly, which is C18's shape. It cannot close
without lectio gaining a capability, which is a feature rather than a fix.

Net: 24 cited classes to 21, 2252 divergent rows to 2095, agreement 86.6% to
87.5%. The number that matters is not the percentage though -- it is that
those 227 days now agree BECAUSE BOTH ENGINES FOLLOW THE MISSAL, where before
they agreed because both inherited the same errors from Divinum Officium.
That is the failure mode CLAUDE.md's lineage note describes, resolved rather
than documented, for the first time in this project.
</content>
</entry>
<entry>
<title>fix(ef): ubaldus and didacus are III-class feasts, not commemorations</title>
<updated>2026-08-18T10:11:05Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T10:11:05Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=a6daed7820a97f4032f21964b5b1bb30fe00b36b'/>
<id>urn:sha1:a6daed7820a97f4032f21964b5b1bb30fe00b36b</id>
<content type='text'>
Both carried rank Class3 with status Commemoration_only, bootstrapped from
lectio, which inherits it from missalemeum, which is generated from Divinum
Officium. The Missal's own universal calendarium ranks both "III classis"
outright, with no commemoration rubric: "S. Ubaldi Ep. et Conf., III classis"
(16 May) and "S. Didaci Conf., III classis" (13 November), corroborated in
the second scan and in a published 1962 Ordo.

Universal by construction, not by assumption: the calendarium carries no "pro
aliquibus locis" marker in its 573 lines while the wider Missal carries 79 of
them elsewhere. Each saint also has his own Mass entry in the Proprium, which
a bare commemoration never has -- a commemoration carries an oration only.

Found by auditing ALL 290 fixed-date entries against that calendarium, day by
day, anchored on the Roman calends column because the arabic day column is
OCR-wrecked and the dominical-letter column vanishes in some months. These
two were the only status defects in the whole file. The 15 days the automated
pass could not cover were read by hand and all agree.

Neither needed a proper authored: each takes its Mass from a Common with only
its own Oratio proper, per its own rubric at its own date. ubaldus shares
patrick's Common exactly. didacus needed one newly transcribed --
common-of-a-confessor-not-a-bishop-2, the "Altera Missa" Iustus, 1 Cor 4:9-14
and Luke 12:32-34, read independently in both scans, which agree, so the
page-image third reading this file's method requires on disagreement was not
triggered.

Blast radius, full 1583-9999 sweep, every day classified: 13 036. That is
5 564 ubaldus observed, 7 196 didacus observed, and 276 where the Ascension
Vigil still wins on 16 May but its single RG 111(c) slot passes from
rogation-wednesday to ubaldus -- correct and already pinned, since the
Rogation days are the MINOR Litanies and so an ordinary commemoration, which
RG 113's table order ranks below a III-class feast. Cited as C38 (70 rows)
and M30 (3); C8, C17 and M18 shrink accordingly, each with the reason
recorded rather than the count silently adjusted.
</content>
</entry>
</feed>
