<feed xmlns='http://www.w3.org/2005/Atom'>
<title>colitur.git/test/test_golden.ml, branch v0.8.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.8.0</id>
<link rel='self' href='https://git.labunix.xyz/colitur.git/atom?h=v0.8.0'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/'/>
<updated>2026-08-18T09:36:33Z</updated>
<entry>
<title>fix(ef): the Assumption and St Lawrence vigils are violet (RG 128)</title>
<updated>2026-08-18T09:36:33Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T09:36:33Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=0281a846ac7c22d22990a6664a37205930a94b7d'/>
<id>urn:sha1:0281a846ac7c22d22990a6664a37205930a94b7d</id>
<content type='text'>
RG 128, transcribed in the rules register since 2026-08-11, gives violet to
"vigils of II and III class outside Paschaltide". The Vigil of the Assumption
(14 August, II class) carried White and the Vigil of St Lawrence (9 August,
III class) carried Red. Both are outside Paschaltide, so both are violet. The
Ascension's vigil is untouched: it is the one II-class vigil inside
Paschaltide and was already correctly white.

The rule had been sitting in the register, disagreeing with the shipped data,
since before the data was bootstrapped. It was invisible because colitur,
lectio and missalemeum all carried the same two wrong colours -- colitur was
bootstrapped from lectio, lectio's ini is generated from missalemeum, and
missalemeum uses Divinum Officium's data files. Three sources agreeing is one
source counted three times, and the differential and the oracle both went
green on the shared error. It surfaced only against witnesses outside that
tree: a published 1962 Ordo flagged the Assumption's, and O'Connell, The
Celebration of Mass 4th ed. (1964), section 4(c) and footnote 169, gave the
general rule and with it St Lawrence's, which the Ordo omits entirely.

Two golden pins added, in years where each vigil is actually observed rather
than impeded. The divergence this creates against every DO-lineage source is
cited in both allow-lists: C37 (lectio, 77 rows -- 92 possible minus 15 where
the vigil falls on a Sunday) and M29 (missalemeum, 3 rows in 2026-2027 and 2
in each of 2035 and 2038). Both gated on the exact slugs or dates and on
colour alone, so any other divergence on those days would still surface.

Also recorded, no code change: rose on Gaudete and Laetare stays. RG 131 is
permissive ("adhiberi possunt") and the Ordo prints violet, so the colour
field carries a permission rather than a requirement on those two Sundays a
year -- a decided position now, not an unexamined one.
</content>
</entry>
<entry>
<title>fix(ef): Good Friday is black, not violet (RG 128(b), RG 132)</title>
<updated>2026-08-18T09:26:04Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T09:26:04Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=01219763c87c84175fcfa469882c6f30a56720d5'/>
<id>urn:sha1:01219763c87c84175fcfa469882c6f30a56720d5</id>
<content type='text'>
RG 128(b)'s own exception list, transcribed in the rules register and
primary-source-verified since Task 16, excepts "Actione liturgica feria VI
in Passione et Morte Domini usque ad Communionem exclusive" from the violet
that otherwise runs from Septuagesima to the Easter Vigil. RG 132 assigns
black there. The register recorded this as an acknowledged gap rather than a
disputed reading -- the code comment beside the Holy Thursday exception says
so in as many words -- and it is closed here.

Found by two witnesses outside the Divinum Officium lineage that colitur,
lectio and missalemeum all share: O'Connell, The Celebration of Mass, 4th ed.
(1964), revised throughout to the Codex Rubricarum (1960) and the 1962
Missal, and a published 1962 Ordo. Both say black. So does missalemeum's own
colour set, which orders the day "bv".

The rubric is per-action ("usque ad Communionem exclusive") and the model
emits one colour per day; black is the day's principal one, the same
acknowledged limit RG 126's Palm Sunday blessing already carries.

Blast radius: one day per year, colour only, across the whole 1583-9999
domain. Two golden pins re-pinned. Good Friday's 46 differential rows leave
C23 for a new C36 gated on the exact triple [First_f; Gospel_f; Colour_f],
so C23's own exact-pair gate still means what its note says for its
remaining four days: 184 + 46 = 230, no residue, both counts from the
comparator rather than hand-counted.
</content>
</entry>
<entry>
<title>feat(kernel): movable Date_spec variants, and Rogation Wednesday</title>
<updated>2026-08-17T15:22:43Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T15:22:43Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=2b9f8133a22ce6dc309644a98bbe61507f574b38'/>
<id>urn:sha1:2b9f8133a22ce6dc309644a98bbe61507f574b38</id>
<content type='text'>
Date_spec carried one variant, Fixed(month, day), and its own header said
Sunday- and Easter-relative forms would arrive with the OF sanctoral. They
arrive early because two things needed them at once: a user-supplied
overlay carrying a local movable feast had no way to express "the first
Sunday of October", and Rogation Wednesday's commemoration has been
recorded as architecturally blocked since 2026-08-13.

That blockage turns out to have been a premise, not a fact. The register
concluded the Rogation "is not Commemoration_only sanctoral data by
nature... it needs a genuinely THIRD kind of thing this architecture has
no name for" -- but the reasoning rested on there being "no civil (month,
day) pair to anchor a Fixed entry to". That is a statement about
Date_spec's expressiveness. With Easter_offset the entity is ordinary
sanctoral data, the identical shape Add major-litanies already ships,
differing only in how the date is written. No third channel was needed.
The register is corrected rather than left contradicting the code.

Two variants: Easter_offset of int, and Nth_weekday of {month; nth;
weekday} with negative nth counting from the end. Fixed's sexp
representation is untouched, so all 327 sanctoral entries and the whole
overlay parse unchanged. Both are re-validated in t_of_sexp through their
smart constructors, extending the idiom Fixed already used -- the failure
that guards against is invisible, a spec deserialising into something
that silently never resolves and a celebration vanishing with no
diagnostic.

Easter is supplied by the rite, not computed in the kernel. Computus
ships Gregorian and Julian both, and picking one here would hard-code a
Roman assumption into rite-agnostic code and be silently wrong for a
Julian-reckoning rite. Rite.t gains an easter field; Rite_ef supplies the
Gregorian one.

Layer keeps a split index. Fixed entries stay in the year-independent
(month, day) table, which preserves the fast path and the "30 November
counted twice in a 371-day span" behaviour validate.mli documents for St
Andrew. Movable entries have no year-independent key by construction --
the same spec lands on a different (month, day) each year -- so they
resolve per civil year into a rata-die table. index_by_date is removed
rather than kept as an alias: two ways to index a layer, one of which
silently ignores movable entries, is the trap this change exists to
avoid.

Two domain-edge defects, both found by the suite rather than reasoning. A
liturgical year is Advent-anchored, so resolving civil year y names y +/-
1, and at the edges those are 1582 and 10000, which Computus correctly
refuses by raising. The ceiling surfaced through the domain-ceiling test,
the floor through `colitur day 1583` failing outright. Fixed once, in
Layer.index, the single point that calls the rite's easter -- a clamp
repeated per caller would have been two places to get wrong a third time.

Rogation Wednesday: RG 87 assigns the Litaniae minores to the Monday,
Tuesday AND Wednesday before Ascension (scan1:691); colitur built the
first two from the start and never the third. RG 88 keeps it out of the
Office, so the Ascension Vigil remains observed. RG 89 routes it through
the Major Litanies' rules, but RG 109's closed list names only maiores,
so by RG 107 it is an ORDINARY commemoration -- confirmed in the output,
not assumed. Name from the Missal's own "feria IV" (scan1:20495-20497),
violet to match the Monday and Tuesday offices.

Blast radius, full 1583-9999 sweep against the pre-change binary: 2257
days, every one the same shape, zero unclassified, line counts equal both
sides. The complement is the informative half -- in the other 6160 years
the Rogation does not appear at all, because RG 111 admits one
commemoration on a II-class day and an impeded feast takes it under RG
113, a Commemoration_only candidate having no row in RG 91's table. Both
shapes are pinned.

Allow-lists unmoved: layer 3 compares no commemorations and is blind by
construction, and layer 4's 2026-2027 window has a competing feast on
both Wednesdays, so the Rogation is capped out in exactly the years the
oracle can see. C8 is unchanged, asserted by its own count pin.

Not built: Sunday-relative specs, which nothing needs yet, and the
--overlay plumbing that would let a user actually supply a local movable
feast. Nth_weekday therefore ships with synthetic and property coverage
only; inventing a shipped entry to exercise it would be fabricating
calendar data.

Register: section 6.10.
</content>
</entry>
<entry>
<title>test: lectionary properties, golden pins, and the blast radius</title>
<updated>2026-08-17T12:56:46Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T12:56:46Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=947cadfab527829f8e42a896339a0fa6c2e81ad9'/>
<id>urn:sha1:947cadfab527829f8e42a896339a0fa6c2e81ad9</id>
<content type='text'>
Layers 2 and 5 for the reading citations, which until now had coverage
from layers 3 and 4 only -- both oracle-bounded, at 2050 and 2027.
test_validate.ml said so in its own words ("No fixture here exercises
citations") and test_golden.ml's describe pinned twelve fields, none of
them a citation. 358 tests -&gt; 369, and 370 under the sweep.

Layer 2 as two Validate checks rather than standalone QCheck properties,
so they ride the existing prop_invariants and the exhaustive sweep
instead of duplicating that machinery. "citations" asserts a day's parts,
sorted, are exactly [First; Gospel] -- one condition carrying three
invariants: zero or two but never one, nothing outside First and Gospel
since the chants are deliberately unbuilt, and no part twice, which a
bare cardinality test would miss. "citations-unresolved" is the separate
coverage half: the chain fell through every step. Both are gated on the
rite producing some citation somewhere, so a rite whose lectionary is not
built is held to neither and the synthetic fixtures stay unaffected.

The result over the whole domain: every day of every liturgical year
1583-9999 resolves exactly one Epistle and one Gospel. Mutation-proved
live rather than merely silent -- treating a well-formed pair as
malformed reddens the suite with real days showing [first,gospel].
citations-unresolved has no live witness at all, which is why
test_validate.ml gains five fixtures driving both checks through a new
?readings override, including the gate itself.

Layer 5 as six pins, one per chain step, so a regression names the step
that broke. Every literal was read out of the scans before being
compared with colitur, per that file's standing rule; scan lines are in
each pin's comment. Two of the six cover step 4, and the plan's own dates
for steps 1 and 4 were wrong: 2030-01-13 is a temporal day (Holy Family
on the generic Sunday slug) and would not have exercised step 1, while
2038-03-08 is John of God, who has a full proper Mass and never routes
through a Common -- so he becomes the step-1 pin instead.

A separate formatter rather than widening describe: widening would
invalidate all thirty existing literals at once and the only practical
way back would be pasting in whatever colitur printed, which is what the
file's header forbids. Restoring them honestly means hand-verifying
thirty more Masses against the scans, a task of its own. Stated rather
than hidden, and defensible because layer 2 now checks the shape of
every day in every year, which is the breadth that widening would have
bought.

Two pins earned their keep immediately. Lent I Monday failed on "Ezek"
against colitur's "Ezech" -- notation only, and colitur matches the
Missal's own abbreviation; layer 3 normalises this away and cannot see
it. The displaced-Sunday feria pins M26 shape 2(b)'s known-wrong
walkback deliberately, labelled as such so a future fix fails loudly,
and established two things M26 had not recorded: both parts come from
the displacing feast, not only the Gospel it cites, and the reference
carries a stray trailing period inherited through the bootstrap.

Blast radius: zero. The CLI never calls Validate, no data file changed,
and 20 years spanning 1583-9998 produce 7301 byte-identical lines
between the pre-change binary and HEAD.

Step 4's blind spot is now measured rather than argued. Corrupting the
Common of Non-Virgins I's Epistle leaves layer 3 (16801 days) and layer
4 (730 days) both green, reddening only one unit test and one new pin.
Both step-4 pins matched the scans on the first attempt -- the first
independent confirmation that route has ever had. It narrows the gap
without closing it: two of five Common-routed saints are witnessed,
isidore-of-seville is not, and gregory-the-great and patrick are
unreachable in any year 2005-2050.

Register: section 6.7 addendum. validate.mli documents both new labels;
liturgical_day.mli's "always empty until Plan 4" was outlived by the
lectionary and is corrected.
</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>ef(lectionary): the Commons, chain step 4</title>
<updated>2026-08-14T23:40:54Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T23:40:54Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=1299815ea03c2b1e4ff19d92d32e386fec24f4e4'/>
<id>urn:sha1:1299815ea03c2b1e4ff19d92d32e386fec24f4e4</id>
<content type='text'>
Fifteen class-3 saints had no readings anywhere in colitur -- the 6 March -
5 April cluster whose RANKS lectio's generator fix of 2026-08-12 restored
without backfilling readings, and lectio has no Commons concept to have
backfilled them from. They are exactly the fifteen `status Feast` entries in
data/ef/sanctoral.sexp carrying `(citations ())`.

The Missal splits them eight/seven, and NOT as the plan predicted. It
expected propers for Benedict, Patrick, Thomas Aquinas and Gregory the
Great; only Thomas Aquinas has one. Benedict ("Missa Os iusti, de Communi
Abbatum"), Patrick ("Missa Statuit, de Communi Confessoris Pontificis I
loco") and Gregory the Great ("Missa Si diligis me, de Communi unius aut
plurium Summorum Pontificum") are all sent to a Common, with only Oratio,
Secreta and Postcommunio printed at the date. All three reversals verified
on the page images (pp. 488, 492) as well as in both OCR text layers.

PROPERS (data/ef/adjustments.sexp, `Edit ... Set_citation`):
  thomas-aquinas         7 Mar  Sap 7:7-14      / Mt 5:13-19
  john-of-god            8 Mar  Eccli 31:8-11   / Mt 22:34-46
  forty-holy-martyrs    10 Mar  Hebr 11:33-39   / Luc 6:17-23
  cyril-of-jerusalem    18 Mar  Eccli 39:6-14   / Mt 10:23-28
  gabriel-the-archangel 24 Mar  Dan 9:21-26     / Luc 1:26-38
  john-damascene        27 Mar  Sap 10:10-17    / Luc 6:6-11
  john-of-capistrano    28 Mar  Sap 10:10-14    / Luc 9:1-6
  francis-of-paola       2 Apr  Philipp 3:7-12  / Luc 12:32-34

COMMONS (data/ef/commons.sexp), each quoting the Missal's own instruction at
the saint's date:
  sts-felicitas-perpetua  6 Mar  non Virginum I   Eccli 51:1-8,12 / Mt 13:44-52
  frances-rome            9 Mar  non Virginum II  Prov 31:10-31   / Mt 13:44-52
  gregory-the-great      12 Mar  Summ. Pontificum 1 Petri 5:1-4,10-11 / Mt 16:13-19
  patrick                17 Mar  Conf. Pont. I    Eccli 44:16-27;45:3-20 / Mt 25:14-23
  benedict               21 Mar  Abbatum          Eccli 45:1-6    / Mt 19:27-29
  isidore-of-seville      4 Apr  Doctorum         2 Tim 4:1-8     / Mt 5:13-19
  vincent-ferrer          5 Apr  Conf. non Pont. I Eccli 31:8-11  / Luc 12:35-40

Every value read in three independent places -- both OCR text layers (two
DIFFERENT printings, whose Commune Sanctorum pagination differs by 1-2, so
the data keys on heading plus Mass incipit and never on the bracketed page
number) and the rendered page images. That caught a genuine typographical
error in one printing: it gives St Gabriel's Gospel as "Luc. 2, 26-38" (on
the page image, so not an OCR artefact). Luke 1:26-38 is settled by the
other printing, by the pericope text in both, and by the SAME edition citing
the identical pericope correctly two pages later at the Annunciation.

Step 4 EXECUTES SECOND (order 1, 4, 2, 3), not last as the plan sketched.
Measured: every day on which one of the fifteen is actually the observed
office already has a non-empty step-2 or step-3 answer waiting, so a step 4
placed after the ferial fallback is unreachable on every date in 1583-9999 --
and wrong where it would fire (2038-03-06 would emit Septuagesima II
Saturday's Mass on a day whose office is Sts Perpetua and Felicity). Step 4
is also the only step in the chain with a direct primary-source warrant: the
Missal names the Mass at each such saint's own date, while steps 2 and 3 rest
only on lectio's observed behaviour. Guarded so it can never divert a day
whose observed office IS its temporal office -- ferias, Sundays, the Triduum
and the RG 78 Saturday Office of the BVM (which deliberately shares the
ferial slug) are structurally excluded. Step NUMBERS are unchanged so every
"step 3" already written down still names the same branch.

The Commons are caller-supplied, like the lectionary: `Rite_ef.context` gains
a REQUIRED `~commons`, not an optional one -- a silently-defaulted empty
table would give a rite whose class-3 saints quietly lose their Mass, and
nothing in layers 3-5 compares citations, so that loss would be invisible.
`Commons.load` rejects the four defects indistinguishable downstream from
"this saint has no Common": duplicate common id, duplicate assignment, empty
formulary, assignment naming a common that does not exist.

KNOWN LIMITS, recorded rather than papered over. There is no oracle: lectio
has no readings for these feasts and missalemeum's 2026-2027 window never
observes one of the fifteen. Eight of the fifteen are NEVER the observed
office anywhere in the domain (10-28 March always falls to a Lenten or
Passiontide feria that outranks a III-class feast), so they have no
end-to-end witness and are covered by dedicated table tests instead. The
Commune Sanctorum's own opening rubric permits any Epistle or Gospel of a
Common in any Mass of that Common unless one is assigned, so what is emitted
is the reading PRINTED WITH the named formulary, not the only lawful one;
labelled alternatives (e.g. the widow's Epistle 1 Tim 5:3-10, squarely
available to St Frances of Rome) are noted in the data and deliberately not
encoded. The BVM Common is NOT authored: the RG 78 Saturday Office shares the
ordinary ferial slug, so assigning a Common to it would hand the BVM Mass to
every feria sharing that slug; routing it needs a subject-keyed lookup and a
season-keyed choice among the Missal's five "Missae de sancta Maria in
sabbato" -- new behaviour, not new data. It currently emits its feria's Mass,
now pinned as such.

Blast radius, measured (git archive HEAD binary vs HEAD, full 1583-9999
`colitur day` sweep, diffed): ZERO differing lines, 3 074 246 lines each
side, byte-identical -- the CLI prints no citations, so this change is
invisible to layers 2-5 by construction, and the sanctoral overlay perturbed
nothing else.

357 tests green (344 before), 358 with the exhaustive sweep. Mutation-tested
six ways, all reverted after confirming: relegating step 4 to last reddens
exactly the four step-4 pins and nothing else; corrupting a Common's citation,
dropping an assignment, dropping a proper Edit, and corrupting either an
unreachable proper or an unreachable Common each redden their own pins. The
load-bearing assertion is stated over the loaded layer rather than a
hard-coded list: every sanctoral entry that can ever BE the observed office
now has either a proper or an assigned Common -- fifteen failures before,
zero after, and a future re-bootstrap adding a readingless class-3 feast
fails there instead of silently emitting its feria's Mass.
</content>
</entry>
<entry>
<title>kernel+ef: fix round 1 -- lectionary caller-supplied, not eager</title>
<updated>2026-08-14T22:36:43Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T22:36:43Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=f8d694d0cc19b71598e1ab64254efb069969f0a0'/>
<id>urn:sha1:f8d694d0cc19b71598e1ab64254efb069969f0a0</id>
<content type='text'>
Critical (coordinator review): a clean `dune build` produced a `colitur`
that died at startup on EVERY subcommand, including ones touching no
lectionary data at all. Root cause was two-fold: data/ef/lectionary.sexp was
never added to the root default-build alias (only materialised as a side
effect of the test suite's own deps, which is why every check in the prior
report passed), and Rite_ef.context loaded it as a module-init side effect
via failwith, undoing Lectionary.load's own "never raises" promise at a
point no caller could catch.

Fixed structurally: Rite_ef.context is now a function taking ~lectionary,
Lectionary_ef.readings takes ~lectionary, and neither touches the filesystem
any more -- the same caller-supplied discipline the sanctoral layer already
had, restoring rite_ef.mli's own pre-existing claim about it and leaving a
seam for a future diocesan lectionary overlay. bin/main.ml grows
load_ef_lectionary, a sibling of load_ef_layer, routed through the same
colitur: %s / exit 2 path. data/ef/lectionary.sexp added to the root default
alias. Every caller of Rite_ef.context updated to supply it.

Also: two new tests that genuinely distinguish chain step 1 from step 2
(19 March 2026, Joseph's own proper over a competing temporal entry; 13
January 2030, Holy Family reached only through the temporal slug, the
Baptism entirely absent) -- the prior two tests both survived swapping the
chain order. Both new pins verified directly against the real data. The
chain's own comment now states plainly that its warrant is lectio's observed
behaviour, not a confirmed Missal citation, per the rules register's own
open item.
</content>
</entry>
<entry>
<title>fix(ef): three colour corrections that contradicted the Missal by name</title>
<updated>2026-08-14T10:40:24Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T10:40:24Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=112781d6e3b92310d9d657c53a7e0fc789aefdfb'/>
<id>urn:sha1:112781d6e3b92310d9d657c53a7e0fc789aefdfb</id>
<content type='text'>
The sanctoral audit set chair-of-st-peter (22 Feb), conversion-of-st-paul
(25 Jan) and peter (25 Jan, commemoration) to Red on RG 124(b). All three
are reverted to White.

RG 120(f), fifteen lines above RG 124(b) in the same column of the same
page, names two of them in its enumeration of white: "Cathedrae S. Petri
(22 februarii); Conversionis S. Pauli (25 ianuarii)". RG 124(b)'s own
qualifier "in eorum die natalicio" independently excludes them, and RG
475(e) confirms it a third time by naming the Chair separately from
"natalician feasts of Apostles". lectio and missalemeum both said white
because both were right. peter rested on "match the host day's Red",
whose host is white by that same clause, so the precedent inverts.

Root cause: the audit's page-image method, its real advance, was applied
to the calendarium and not to the rubric. RG 124 was read from the OCR
text layer, where the two-column interleave shreds RG 120(f) across rows
belonging to RG 115 and hyphen-splits Cathedrae, so a text-layer grep
for it returns nothing while RG 124's enumeration survives cleanly. That
read finds 124 and structurally cannot find 120(f).

Two sentinels had been reporting this correctly and were overridden. The
golden pin at 1902-02-22 asserted colour=white, was changed to red, and
had its comment rewritten to guard against "a regression back to the old
one" -- the only pin asserting a colour for any of the 21 slugs. And C18
and M21 both listed the two slugs under an RG 124(b) citation where both
oracles were right. Pin restored; slugs dropped; C18 re-derived 526-&gt;450
from the observed-day counts, M21 20-&gt;18, M15 17-&gt;18.

The audit's own discriminator would have isolated these. Its stated
corroboration was that lectio's name.pl contradicts lectio's colour; run
as a gate across all 21 that splits 17 genuine defects from 4 needing
adjudication, and three of those four are these. It was quoted as
illustration rather than used as a gate.

18 of 21 corrections stand, and the twelve whites are recited to RG
120(e) "Sanctorum non Martyrum" rather than to RG 117's negative
residual. Also records Anastasia's deliberate non-fix in the tracked
tree beside barbara, where the next auditor will be standing.
</content>
</entry>
<entry>
<title>data(ef): sanctoral audit — one genuine gap, 21 wrong colours (RG124)</title>
<updated>2026-08-14T10:00:24Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T10:00:24Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=bf326ab963f46c42dc1a3b5141f2022bed81756d'/>
<id>urn:sha1:bf326ab963f46c42dc1a3b5141f2022bed81756d</id>
<content type='text'>
Full re-extraction of the primary CALENDARIUM (both photographic scans,
missale-romanum-1962.pdf and Missale Romanum 1962_text.pdf, rendered page
images read directly rather than trusting either PDF's own OCR text
layer) against all 327 base sanctoral entries plus the two prior overlay
Adds. Both scans agree throughout; no OCR ambiguity required adjudication
this round.

Add `barbara` (4 December): both scans carry a Commemoratio nested under
Peter Chrysologus's own entry, absent from data/ef/sanctoral.sexp AND
from lectio's own tridentine-calendar.ini (confirmed directly) — the same
upstream-gap shape as the five entries the ef-rebootstrap task already
added (agnes-secundo/boniface-martyr/eusebius-confessor/evaristus/
theodore).

Correct 21 sanctoral colours against RG 124 ("De coloribus paramentorum"),
scan-verified word for word: 124(b) red for an Apostle/Evangelist's own
feast day except John's (27 December, already correct); 124(e) red for a
Martyr's own martyrdom; RG 117's five-colour residual otherwise white.
Every one of the 21 is a confirmed lectio/missalemeum bootstrap defect —
checked individually against lectio's own ini, several of whose Polish
name fields already contradict that same record's own colour tag (e.g.
`martha`: "Dziewicy", Virgin, no "Męczennicy", yet `colour = red`) — the
identical root cause and mechanism the `eusebius-confessor` fix already
established. Colour is confirmed read nowhere in Precedence_ef's
resolution logic (grep), so these are output-correctness fixes with zero
observed-office blast radius; three (apollinaris/josaphat/chair-of-st-
peter) additionally disagree with missalemeum's own oracle, not only with
lectio, so they are adjudicated from RG 124's text directly rather than
by which engine happens to agree.

Both corrections applied via data/ef/adjustments.sexp's established
Overlay mechanism (data/ef/sanctoral.sexp stays generated, untouched).

Pinned: test_rite_ef.ml (two new tests, verified to fail against the
pre-fix data); test_differential.ml's new C18 predicate (526 rows,
2005-2050) and test_oracle.ml's new M21/M22 predicates (20 + 2 rows,
2026-2027), each with data/ef/expected-divergences{,-missalemeum}.sexp
entries citing RG124 or the matching upstream-gap precedent;
test_golden.ml's 1902-02-22 pin corrected (chair-of-st-peter was white in
the stale pin, RG124(b) makes it red). All 329 tests green, including the
full 1583-9999 exhaustive sweep.

Full method, per-entry adjudication table and corrected bucket counts:
docs/research/rules-register.md (gitignored) and
.superpowers/sdd/2026-08-12-colitur-rg16a/sanctoral-audit-report.md
(gitignored).
</content>
</entry>
<entry>
<title>test(ef): commemoration, transfer, and privilege coverage for the Major Litanies</title>
<updated>2026-08-13T18:15:42Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-13T18:15:42Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=84333a8c74ddb3988ad88398632ca5e1c7788e56'/>
<id>urn:sha1:84333a8c74ddb3988ad88398632ca5e1c7788e56</id>
<content type='text'>
test_precedence_ef.ml: a privilege_cases row for RG109(f), deliberately
rank Class4 so it cannot pass via the pre-existing "of a I-class day"
branch by accident. Three disposition_cases rows: the two RG80 trigger
shapes (Transfer, not Commemorate) and a synthetic third row proving the
winner-slug guard is specific to the two named trigger days, not "any
I-class winner". Two transfer_target unit tests, both using a pathological
always-blocking occupant to prove no RG96 search runs at all for this
candidate -- a much stronger witness than a cooperative occupant, which
could pass by accident.

test_golden.ml: three new pinned tests through the real data pipeline --
the ordinary case (2026-04-25, matches the oracle's own M5 date), the four
Sunday-displacement years in 2005-2050 (2010, 2021, 2027, 2032, RG111(b)),
and the Easter-Monday transfer shape (2011, complementing the
Easter-Sunday shape already pinned by the existing 1666/2038 Easter-extreme
tests, now widened to include the transfer and its target).

test_rite_ef.ml: the existing "no transfer lands inside the Easter octave"
property gets a named, cited exemption for the Major Litanies (RG80's own
deliberate exception), plus a positive companion test asserting the
exemption is not vacuous (exactly two landings in 2005-2050, both
Easter+2). That companion test was written but never registered in its
own suite list -- caught while mutation-testing the transfer (a mutation
that should have failed it passed silently); fixed by registering it.

Mutation-tested, each of the three parts separately (recorded in the
task's own report): moving the data entity off 25 April fails 7 tests
(golden + oracle only -- zero unit tests, since they build synthetic
candidates); corrupting the transfer's winner-slug guard fails 6 (the two
disposition_cases rows, 3 golden pins, and the newly-registered
transfer-count test); flipping the privilege to Ordinary fails 9
(privilege_cases, the disposition SYNTHETIC row, the oracle's count pin,
5 golden pins, and the exhaustive Validate property sweep).
</content>
</entry>
</feed>
