<feed xmlns='http://www.w3.org/2005/Atom'>
<title>colitur.git/test/fixtures, branch v0.7.0</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.7.0</id>
<link rel='self' href='https://git.labunix.xyz/colitur.git/atom?h=v0.7.0'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/'/>
<updated>2026-08-17T20:38:01Z</updated>
<entry>
<title>test(oracle): a third window, 2035, witnessing common-of-doctors</title>
<updated>2026-08-17T20:38:01Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T20:38:01Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=c1776a07bfb41667d897c90914acea17f66f6510'/>
<id>urn:sha1:c1776a07bfb41667d897c90914acea17f66f6510</id>
<content type='text'>
Step 4's blind spot is now closed as far as the method allows. 2038
witnessed two of the five Common-routed saints; isidore-of-seville is the
third and the last that any year in 2005-2050 can reach, being observed
only in 2008, 2035 and 2046. He is also the only saint routing through
common-of-doctors, so that Common had never been compared against any
external source in any window.

Three independent agreements on it: the scan (Commune Doctorum,
scan1:41878ff, 2 Tim. 4, 1-8 / Mt. 5, 13-19), colitur, and missalemeum's
own 2035-04-04 row. Asserted by date in its own test rather than folded
into an aggregate count, so a regression there cannot hide.

The remaining two saints are unreachable by construction, not for want of
a fixture: gregory-the-great and patrick both sit in March and are
impeded by Lent's privileged ferias in every one of the 46 years the
differential covers. The blind spot is closed to its limit, not closed
absolutely, and the register says so.

The comparator is generalised rather than copied -- compare_live takes a
fixture and a year -- so a fourth window would cost a fixture and a count
list.

2035 differs on 3 days, both families pre-existing and already cited.
2035-04-02/03 are the Joseph/Annunciation transfer pair landing in the
opposite order from missalemeum's: neither stream loses a feast, the
sequence differs, which is C14's own RG 96 collision finally getting an
oracle window. 2035-12-30 is the Sunday within the Christmas Octave
against colitur's numbered octave-day slug, C6's family. Both are
recognised by slug rather than by date, so a year exhibiting only half
the shape would surface as unexplained rather than be quietly absorbed.

393 tests green with the exhaustive sweep.

Register: section 6.15.
</content>
</entry>
<entry>
<title>feat(cli): --overlay FILE, so a local calendar can be supplied</title>
<updated>2026-08-17T15:46:31Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T15:46:31Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=0a4bb4e6c3cbcafb302962d9d1e70b5a0bb554b8'/>
<id>urn:sha1:0a4bb4e6c3cbcafb302962d9d1e70b5a0bb554b8</id>
<content type='text'>
The Overlay algebra has been built and tested since Plan 2, and
Date_spec grew movable variants last commit, but there was still no way
to hand colitur a file: bin/main.ml applied exactly one overlay, the
shipped data/ef/adjustments.sexp, with the path hardcoded. This is the
plumbing.

--overlay is repeatable and ordered, and applies ON TOP of the shipped
adjustments rather than instead of them. That ordering is the whole
point: adjustments.sexp carries RG 110's own 30 June companion, the Major
Litanies, St Barbara and Rogation Wednesday, and a user file that
replaced it would silently drop all four while appearing merely to add a
local feast. Overlay.merge is last-writer-wins, so a local calendar can
still override a universal entry deliberately, by naming its slug.

The dispatch needed real argument parsing. It matched Sys.argv as an
exact array, which does not survive a repeatable flag -- two --overlay
arguments are a different array shape from one, and each further flag
would multiply the patterns again. Flags are now stripped first and the
remaining words matched as command plus year. Hand-rolled, because the
dependency list is frozen and this is fifteen lines. One defect found by
the cram suite on the first run: the unknown-option guard rejected
--help and --version, having excluded only their short forms.

Refused, not ignored, on easter and temporal. Neither reads sanctoral
data -- temporal deliberately runs the cycle before any layer exists --
so accepting the flag there and silently doing nothing is the failure
mode this project refuses everywhere else.

A file that fails to load is fatal, exactly as the shipped overlay is; a
directive naming a slug that does not exist warns on stderr and the run
continues. The second matters more for a user file than for ours: a typo
in a diocesan calendar should say so rather than quietly do nothing.

test/fixtures/overlay-example-diocesan.sexp is a worked example and is
labelled as invented, not calendar data. It carries both shapes a real
local calendar needs: a fixed-date patron, and a dedication on "the first
Sunday of October" -- which is the case the Date_spec work existed to
unlock and which lands on 4 October in 2026, 3 October in 2027, 1 October
in 2028. The dedication is I class because a church's own dedication
anniversary is I class in that church; at III class it lost to the
II-class Sunday every year, which a first draft demonstrated correctly
and uselessly.

The man page gains an OVERLAYS section saying plainly that an overlay is
applied, NOT validated: the five test layers assert things about the
shipped calendar and none of them can vouch for a file the user supplies.
This is the first feature that lets someone change what colitur computes,
and that distinction should not have to be inferred.
</content>
</entry>
<entry>
<title>test(oracle): a second oracle year, 2038, closing step 4's blind spot</title>
<updated>2026-08-17T14:00:23Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T14:00:23Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=f03567a04b68ab19b5f16f0b6d56d9c08b14c818'/>
<id>urn:sha1:f03567a04b68ab19b5f16f0b6d56d9c08b14c818</id>
<content type='text'>
Register section 6.7 recorded that step 4 of the reading chain -- the
Common route -- had no external witness of any kind, and proved it by
mutation: corrupting a Common citation left both the 16801-day
differential and the 730-day oracle green. This closes that.

2038 is the only year in 2005-2050 in which two of the five
Common-routed saints are the observed office (Perpetua and Felicitas on
6 March, Frances of Rome on 9 March). 365 days were captured live, one
request per day, zero failures.

A separate fixture, not more rows on the existing one. sources.md
already records that the live endpoint has drifted from lectio's
archived 2026-2027 snapshot; merging two versions of one source behind a
single set of expectations would make any future disagreement
unattributable -- calendar or drift, no way to tell. Nothing in the 2038
comparison is checked against the older fixture, and its provenance file
says so, along with the fact that a live capture is not reproducible
byte-for-byte on demand the way a snapshot-derived one is.

338 of 365 days match. 27 differ, every one of them in a named,
already-adjudicated class, none unexplained: 13 the BVM Saturday votive
Mass (M26 shape 1), 7 colour (M21), 2 Judith (M28), 2 Christ the King's
week (M26 shape 2b), 1 Christmas multi-Mass (M27), 1 Perpetua's Common,
1 new. Each was decided in a different year, so 2038 re-confirms them
independently -- the point of a second window is not new rulings but
evidence the old ones are not artefacts of their own year.

Two findings came out of it. Perpetua and Felicitas: missalemeum serves
the Common of Virgins and calls them "Virgins and Martyrs" in its own
oration, where the Missal directs "Missa Me exspectaverunt, de Communi
non Virginum I loco" (scan1:27634-27635). Both Commons share the Introit
Ps 118:95-96, which is exactly why the calendarium qualifies its
direction, and both women were mothers. Verdict colitur; the mechanism
is located on missalemeum's side, not merely asserted. Passion Tuesday:
the Missal prints "Dan. 14, 27 et 28-42" (scan1:11106) and colitur
reproduces that two-part form where missalemeum collapses it to
27-42. Same verses; the convention is deliberate, appearing also in the
Seven Sorrows and the Common of Non-Virgins. Verdict colitur, cosmetic.

Citations are notation-normalised before comparing, as layer 3 already
does: Ecclus/Sir, Joann/John, Luc/Luke, Matth/Matt. Each pair was added
because a real row needed it, and no target contains its own source as a
substring, so the set is idempotent.

Not compared, stated rather than left to be found: commemorations and
observed-identity. That machinery is built around a date-literal
28-entry allow-list specific to 2026-2027, and re-deriving it for a
second year is its own task. 2038 compares rank, colour, Epistle, Gospel.

The extractor's day count was hardcoded to 730, which silently forbade
any other window. It is now a parameter defaulting to 730, so the
existing documented command keeps its guard and a partial fetch still
fails loudly instead of producing a short fixture that passes a
comparison it never ran.

Teeth, by re-running section 6.7's own experiment: corrupting the Common
of Non-Virgins II now reddens four tests, two of them external-oracle,
where the same mutation previously reddened neither oracle layer.

Residual: isidore-of-seville is still unwitnessed and needs 2035 or
2046; gregory-the-great and patrick are never the observed office in any
year 2005-2050, so no fixture in that range can reach them.

Register section 6.8 and 6.9.
</content>
</entry>
<entry>
<title>fix(lectionary): two Judith citations wrong in both engines</title>
<updated>2026-08-17T12:13:02Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T12:13:02Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=3565ebd1608a7d87e0d890f9953845efcfe743ca'/>
<id>urn:sha1:3565ebd1608a7d87e0d890f9953845efcfe743ca</id>
<content type='text'>
A live-missalemeum sweep over a full liturgical year (2028, 364 days)
returned 333 matching and 31 differing days: 17 already-known or pure
notation, 3 new. All three now adjudicated against the photographic
scans of the 1962 Missal.

The Assumption's Epistle reads "Iudith 13, 22-25; 15, 10" (scan1:35357).
Both engines carried "Judith 13:22-25; 13:15; 13:10" -- a chapter
carry-over defect that re-applied chapter 13 to the second citation and
so invented two verses the Missal never cites. The Seven Sorrows reads
"Iudith 13, 22 et 23-25" (scan1:36938, corroborated at 28468); both
carried "Judith 13:22; 13:25", dropping the range. The third, St Monica,
resolves the other way: the Missal gives 1 Timothy (scan2:32679, heading
and incipit both legible; scan1:29524 agrees) where missalemeum serves
the Common of Holy Women's Proverbs -- colitur is right, no change.

Layer 3 could not have found either citation defect. colitur's data is
bootstrapped from lectio, and lectio is the other side of that
differential, so while both engines produced the identical wrong answer
the comparison held it against itself and reported agreement -- the
shared-lineage blindness CLAUDE.md names, now with a second live witness
beside Holy Thursday's colour. Only an external oracle could see it, and
only outside the committed fixture's own window.

Fixed upstream in lectio, re-bootstrapped here (provenance SHA-256 moved
to 54f6bfc5, verified against the source), fixture regenerated.

The upstream fix inverted layer 3 from blind to load-bearing here:
reverting the Assumption citation now reddens both layers, where before
it would have reddened neither. Verified by mutation, both directions.

Allow-lists:
- C22 closed and removed (128 rows -&gt; 0), not re-adjudicated -- the other
  engine was fixed to agree, the same shape as the C2-C5/C7/C9-C13/C21
  closures. Its own note had already flagged the Lenten Ember dead-key
  bug for upstream; lectio now also fails its build on any unreachable
  lectionary key rather than serving a plausible wrong Mass.
- M28 opened (3 rows, verdict colitur), pinning both sides' citation
  text rather than the date and diff shape alone, so a different
  divergence landing on the same date cannot be swallowed.
- M8's gate widened, expected_rows unchanged at 2: 2027-08-15 carries
  both its cause and M28's, and one entry is admitted per day. It stays
  under M8, which now requires its own commemoration difference to be
  present and admits the citation difference only when it satisfies
  M28's two-sided predicate. Neither cause absorbs the other.

layer_m_reason's oracle-row parameter, kept named since M2 closed for
exactly such a future reader, is live again.

Register: docs/research/rules-register.md section 6.6.
</content>
</entry>
<entry>
<title>test(oracle): fix round 1 -- C30 disclosure, RG 17(a) misattribution, M26 shapes</title>
<updated>2026-08-17T11:02:39Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T11:02:39Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=5d236c75c557a7e9ed4a8a852b8089aca48b594e'/>
<id>urn:sha1:5d236c75c557a7e9ed4a8a852b8089aca48b594e</id>
<content type='text'>
Three Important findings from coordinator review of 8d1eb25, all fixed.

1. C30's own note claimed its 91-row population "is C25's OWN former
   population, before this task narrowed it" -- false. Independently
   re-derived against the real resolver (pre-fix vs post-fix binary) and
   the lectio fixture: only 44 of the 91 rows were ever in C25 (Wed 6/
   Thu 19/Fri 19, matching C25's own fix-round-3 breakdown exactly); the
   other 47 (all of Monday/Tuesday, plus part of Wednesday/Friday)
   previously matched lectio outright -- both engines independently
   landing on the same wrong value -- and are newly allow-listed only
   because colitur is now right. Rewritten to the same "both engines
   silently agreed on the wrong answer" pattern C33/C34 already used.

2. "Diebus ferialibus" is not RG 17(a) -- RG 17(a) states only the
   day-identity privilege; the ferial-Mass rubrics are Mass-propers
   rubrics, a distinction the register's own §6.3 already drew before
   this task's first pass blurred it in code/allow-list comments. A
   further slip: C31/C32 called their own rubric "RG 17(a)'s own next/
   third sentence" when it is a different rubric block ~230 lines away,
   in Holy Family's (not Holy Name's) own feast propers. Fixed the
   attribution chain throughout tools/bootstrap_lectionary.ml,
   data/ef/expected-divergences.sexp's C29-C34, and (gitignored, outside
   this commit) docs/research/rules-register.md -- closed the §6.3 park,
   added §6.5 recording all four citations with corrected attribution.
   Quotes and line numbers were already right; only the chain of custody
   to RG 17(a) was wrong.

3. M26's own 30 rows classify into two nameable shapes, not "three
   confirmed shapes" with an unexplained 23-row residue that was in fact
   empty: 21 rows are RG 78's own already-documented BVM votive-Mass
   gap; 9 rows are a second, distinct gap -- a week whose own Sunday was
   displaced by a movable named feast (Trinity-&gt;Corpus Christi, "Missa
   Dominicae I post Pentecosten"; Christ the King), where the Missal
   requires the displaced Sunday's own Mass to keep informing that
   week's ferias but step 3 walks back to the displacing feast's citation
   instead -- proven directly by colitur's own citation on the Christ-
   the-King rows being literally that feast's own Gospel. verdict open
   unchanged (not fixed here); the shape is now named instead of buried.

Minors: section count corrected 1458-&gt;1456 (four places); "exactly one
candidate, zero ambiguous" corrected to "correctness rests on ordering,
not uniqueness" (2 of 1456 sections genuinely yield two candidates,
Holy Saturday's own Lectio, both years); the stale "nothing in layers
3-5 compares citations" claim corrected (only layer 5 still doesn't);
M18's note corrected (five new entries not six; ~18 of its remaining
352 rows only agree now because of this task's own fixes, not "already"
before it); "five" corrected to "six" otherwise-unoccupied Saturdays in
bootstrap_lectionary.ml; scan2 quotes softened where OCR-garbled.

Also done outside the git-tracked files: the step-4 (Commons) coverage
gap is now recorded in data/ef/expected-divergences-missalemeum.sexp's
own header, not only the commit body and the (gitignored) report.

dune test: 358 tests green. COLITUR_EXHAUSTIVE_SWEEP=1 dune test
--force: 359 tests green, 95.7s.
</content>
</entry>
<entry>
<title>test(oracle): compare reading citations against missalemeum</title>
<updated>2026-08-17T10:28:03Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T10:28:03Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=8d1eb25a311e16ddb7bf89d2b21fb1ca0aa058a7'/>
<id>urn:sha1:8d1eb25a311e16ddb7bf89d2b21fb1ca0aa058a7</id>
<content type='text'>
Layer 4 (test_oracle.ml) now extracts and compares the Epistle/Gospel
citation for every one of the 730 days in the 2026-2027 fixture, the
same axis Task 8 already added to layer 3. tools/
extract_missalemeum_oracle.py gained a structural citation-span
detector (the first "*...*"-wrapped span under 40 chars containing a
chapter:verse-shaped digit pair), verified exhaustively over all 1 458
Lectio/Evangelium sections. 728 of 730 days are comparable; the 2 that
are not (Good Friday, both years) have no such section in missalemeum's
own JSON at all -- a structural limit on the oracle's own side (M23),
not a colitur gap. 451 of 730 days differ and are all explained across
19 cited entries; 0 unexplained. Chain step 4 (the Commons) has no
layer-4 witness: confirmed empirically (a scratch sweep, not merely
re-asserted from Task 6's own report) that none of the 15 Commons/proper
saints is ever the observed office in this window.

The comparison surfaced three genuine colitur bugs in
data/ef/lectionary.sexp, all fixed at the source in
tools/bootstrap_lectionary.ml:

1. Holy Name of Jesus (ef-holy-name-sunday/ef-holy-name) carried a
   mis-derived citation, borrowed by analogy from an unrelated ini
   section ("ef-christmas-sunday-0", the Sunday-within-the-Octave's own
   Mass) on the wrong assumption the two share a Mass. Disproved by
   missalemeum's own extraction for both real Holy Name Sundays in its
   window, confirmed against the Missal itself, twice, both scans
   (Acts 4:8-12/Luke 2:21, not Gal 4:1-7/Luke 2:33-40).
2. RG 17(a)'s own "diebus ferialibus" rubric (immediately following the
   Holy Name heading, both scans) was never implemented: 2-5 January
   ferias repeat 1 January's Mass, 7-12 January ferias before Holy
   Family Sunday repeat Epiphany's, and Holy Family's own week has a
   named formula ("Missa Dominicae Primae post Epiphaniam"). All three
   fell to step 3's undifferentiated Sunday walkback instead. Fixed for
   three 5-weekday families, deliberately excluding Saturday from all
   three -- RG 78's BVM Saturday Office wins there unconditionally,
   confirmed against missalemeum's own title on this window's own such
   Saturdays.
3. Corpus Christi and Sacred Heart (both real, never-impeded I-class
   movable feasts) had no lectionary entry at all. Both engines
   independently fell back to Trinity Sunday's own citation and
   silently agreed on the wrong answer -- the "Holy Thursday violet in
   both" shape CLAUDE.md names for exactly this reason.

Because lectionary.sexp is shared with layer 3 (the lectio differential,
2005-2050), these fixes changed colitur's output for the whole domain,
not only 2026-2027. data/ef/expected-divergences.sexp and
test_differential.ml needed matching updates: C1 narrowed 361-&gt;173 and
C25 narrowed 57-&gt;13 (rows that now resolve correctly moved to new
entries), C16's note corrected (count unchanged), and six new entries
added (C29-C34, 397 rows total, all verdict colitur). test_lectionary.ml
and test_lectionary_ef.ml's own pins were updated to match (entry count
131-&gt;148; one step-3 regression test re-pointed to a date that still
genuinely exercises that step).

One entry, M26 (30 rows, verdict open), is a genuine unfixed gap: colitur's
step-3 "resume the preceding Sunday" fallback is its only ferial-Mass
mechanism, and missalemeum's own selection is more granular in three
confirmed ways (a rotating votive Mass of the BVM, a named weekly
formula for at least one week, and later Time-after-Pentecost weeks this
task's own investigation did not narrow to a single rule) -- the same
"needs a season-keyed selection mechanism, new behaviour not new data"
shape data/ef/expected-divergences.sexp's own C6/C25 and Task 6's own
residual concern already name, out of this task's own scope to build.

dune test: 358 tests green. COLITUR_EXHAUSTIVE_SWEEP=1 dune test
--force: 359 tests green, 89.5s.
</content>
</entry>
<entry>
<title>test(differential): compare reading citations, 16 801 days</title>
<updated>2026-08-15T00:58:00Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-15T00:58:00Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=459d2c74711e6a152fb338f88d2327f12180b61f'/>
<id>urn:sha1:459d2c74711e6a152fb338f88d2327f12180b61f</id>
<content type='text'>
Layer 3 is NOT blind to the ferial resumption rule, unusually for this
project: lectio implements the same rubric independently, so the differential
checks colitur's rule against a second implementation rather than against
silence.

It IS blind to the Commons -- lectio has no such concept -- so chain step 4
rests on layer 4 alone.

Divergence triage, 1 532 of 16 801 days differ (15 269 match exactly),
0 unexplained:

- A genuine colitur bug found and fixed: data/ef/lectionary.sexp carried
  lectio's own ini section names verbatim, never translated into the slugs
  Temporal_ef actually computes for the identical office. Data the bootstrap
  already held (Passiontide both weeks, the Pentecost Ember days, Holy Name
  Sunday) was unreachable by chain step 2, silently falling through to a
  wrong step-3 answer -- invisible until citation content became comparable.
  tools/bootstrap_lectionary.ml gained colitur_keys (rename/widen), a
  hand-authored ef-nativity-vigil entry cross-sourced from lectio's own
  sanctoral calendar and corroborated by colitur's own (overlay-suppressed)
  sanctoral bootstrap of the same source, and a derived ef-holy-name entry
  (RG 17(a)'s single Mass heading covers both the Sunday and 2-January
  shapes). One guess (giving the fixed Nativity-Octave days Holy Name
  Sunday's own citation uniformly) was tried and reverted once measured
  against the fixture -- Missal-verified to be right only for the genuine
  "Sunday within the Octave" case, wrong whenever the true preceding Sunday
  is Christmas Day or Advent IV instead.

- 10 existing/widened Layer C entries (C1/C6/C8/C14/C15/C16/C17/C18 --
  C6 and C17 narrowed with the removed population accounted for, not
  silently re-absorbed) plus two new ones: C19 (the already-adjudicated
  Time-after-Epiphany week-numbering offset, now visible in citation
  content), C20 (lectio computes no reading at all for the seven
  readingless saints Task 6 gave a Common or proper -- colitur is more
  complete, not wrong).

- One entry, C21, is a genuine colitur LOGIC limitation found but not
  fixed: Lectionary_ef.readings' step 3 is a single hop to the preceding
  Sunday, insufficient for a run of colitur-only fixed Christmastide slugs
  whose own preceding Sunday is itself another entry-less fixed slug.
  Recorded verdict open (data/ef/expected-divergences-missalemeum.sexp's
  own established precedent for this shape), not left silently failing --
  fully diagnosed in task-8-report.md, recommended as a dedicated
  follow-up task rather than a hasty fix to a shared, multi-round-reviewed
  kernel-adjacent function.
</content>
</entry>
<entry>
<title>test(differential): refresh the lectio fixture, close 9 entries, add C14</title>
<updated>2026-08-12T20:24:30Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T20:24:30Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=a4ffb0234d198ef295554e3202db15403346fbed'/>
<id>urn:sha1:a4ffb0234d198ef295554e3202db15403346fbed</id>
<content type='text'>
lectio moved 2386a45 -&gt; 3b32c00 (seven EF calendar defects fixed, plus a
sanctoral-generator root-cause fix); the committed fixture predates all
of them. Regenerated with the same command the provenance note already
named (`go run ./cmd/lectio-ef-dump 2005 2050`), read-only against
lectio -- nothing there was touched. New SHA-256 asserted in both the
provenance note and test_differential.ml's fixture_sha256. The dumper's
two new name_en/name_pl columns are kept verbatim (the fixture is meant
to be the exact command's raw output; the comparator already discards
everything past field 7).

Every C-entry's expected_rows was re-derived independently against the
refreshed fixture (a Python re-implementation of diff_fields/
layer_c_reason, cross-checked against the real OCaml comparator's own
failure output), not transcribed from a green run. Nine entries -- C2,
C3, C4, C5, C7, C10, C11, C12, C13 -- now match zero rows and are
closed: sexp row removed, layer_c_reason predicate and its now-dead
helper bindings removed, citation preserved in
docs/research/rules-register.md's new §3d with the specific lectio
commit that fixed each one. C1 (361 -&gt; 368) absorbs C13's former 7 rows
now that lectio's own slug matches there too. C6 (138, unchanged count)
narrows to a slug-only shape now that lectio's rank agrees. C8 (31,
unchanged) survives untouched -- lectio still computes no Rogation days.

C9's old shape ("Joseph observed ON a Lent Sunday") is also closed, but
a narrower, different divergence survived under the same saint's slug: 3
years (2008, 2035, 2046) where Joseph's own congested RG96 walk collides
with the Annunciation's separately-transferred "sedes propria". The old
predicate's broad "any diff involving this slug" match was silently
absorbing both under one citation -- split into a new id, C14, rather
than folded back into C9, since the two are unrelated rules. lectio's
own commit history (09a1444) documents this residual as a gap it
deliberately left unresolved; colitur gives Joseph a real transferred
day either way, which is why C14's verdict stands regardless of a
genuinely open sub-question (recorded in the register, not resolved
here) about which of the two feasts should claim the contested day
first under RG98's "prius impeditum" wording.

Re-triaged the full remaining 4975 raw differences: only 10 distinct
field-diff signatures now, all resolving to Layer A/B noise or the four
surviving citations, 0 unexplained. The crude "Sunday-rank" and "Holy
Thursday" residues the task flagged both fully resolve once the real
Layer A/B machinery runs (season-spelling and week-numbering artifacts,
not substantive divergences) -- see the task report for the derivation.

Teeth proof: perturbing ferial_rank to reproduce C4's old defect made
140 rows reappear as unexplained (the exact prior C4 count), reverted
after capturing the failure message.

277 tests green (dune test) and 278 with COLITUR_EXHAUSTIVE_SWEEP=1 (the
extra case is the 1583-9999 sweep itself).
</content>
</entry>
<entry>
<title>feat(test): oracle layer compares commemoration identity, not just count</title>
<updated>2026-08-12T13:37:08Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T13:37:08Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=76298db9b0fb5409bcfd4276b642f69f4da530e9'/>
<id>urn:sha1:76298db9b0fb5409bcfd4276b642f69f4da530e9</id>
<content type='text'>
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&lt;-&gt;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 -&gt; 273 tests (274 with the exhaustive sweep), all green.
</content>
</entry>
<entry>
<title>test: oracle vs missalemeum 2026-2027; audit the sanctoral</title>
<updated>2026-08-12T02:36:36Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T02:36:36Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=cb200a3f95e24f67c1d08b2ceb09404bf57a1636'/>
<id>urn:sha1:cb200a3f95e24f67c1d08b2ceb09404bf57a1636</id>
<content type='text'>
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-&gt;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.
</content>
</entry>
</feed>
