<feed xmlns='http://www.w3.org/2005/Atom'>
<title>colitur.git/data/ef/expected-divergences-lms.sexp, branch main</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=main</id>
<link rel='self' href='https://git.labunix.xyz/colitur.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/'/>
<updated>2026-08-22T16:46:27Z</updated>
<entry>
<title>fix(ordo): correct L5/F3 misadjudication -- Cum Sanctissima, not a gap</title>
<updated>2026-08-22T16:46:27Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T16:46:27Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=e5e304c4004089ea75ea472ebd56414197a4190f'/>
<id>urn:sha1:e5e304c4004089ea75ea472ebd56414197a4190f</id>
<content type='text'>
data/ef/expected-divergences-lms.sexp's L5 (16 dates, LMS Ordo Gloria=true
vs colitur's false) and data/ef/expected-divergences-fiuv.sexp's F3 (6
dates, FIUV Te Deum=true vs colitur's false) were both misadjudicated as
colitur's own gap under an RG 302(b)/431(b) hypothesis. Both are wrong.

These are occurrence differences from the 2020 decree Cum Sanctissima,
which colitur excludes from its 1962 core by binding design (CLAUDE.md
decision 2). RG 303(b) ("dici potest tantum si occurrit dies liturgicus IV
classis") already prohibits 302(b) on the Class3 privileged ferias both
entries cover -- the original text quoted 303(b) but never followed it to
its conclusion. Decisively, the FIUV Ordo prints BOTH readings on the six
shared dates, separated by a literal "-VEL-" token: the primary, strict-
1962 reading (feria wins, sine Gloria, no Te Deum) matches colitur exactly;
the second, Cum-Sanctissima reading (saint kept, Gloria, Te Deum) matches
the LMS Ordo exactly.

F3 itself was never a real Te Deum finding: tools/extract_fiuv_ordo.ml's
extract_te_deum scanned each block unbounded for "Ad Mat.", so on these six
days -- whose primary office states no "Ad Mat." of its own -- it silently
read the second office's own Te Deum instead. Fixed with a new
split_at_alt_office, cutting every block at "-VEL-" before any field
extraction runs; the alternative is captured, not discarded, in a new
alt_te_deum field. A hard characterisation probe asserts the split fires on
exactly the six known dates.

Auditing for the same trap elsewhere (this is the third such manufactured
divergence in this project) found a related but narrower marker, "Vel (sec.
decretum &lt;&lt;Cum sanct.&gt;&gt;) Missa ...", offering an alternate Mass formulary
within a single office. It never corrupted Gloria/Credo (always stated
before the marker on all 20 real instances, confirmed by diff), only the
uncompared praef field; hardened defensively anyway, before it could ever
fire live. The LMS Ordo (all three editions) carries no equivalent
dual-print mechanism at all. expected-divergences-missalemeum.sexp's M27
is the same genus but was already correctly adjudicated, not touched.

Both allow-list entries are rewritten, not deleted: the original SHAPE/
CITATION/WHY-NOT-FIXED-HERE reasoning is preserved verbatim as a recorded,
superseded hypothesis, matching this project's own correction convention.
test_lms_ordo.ml's matching predicate is unchanged (the 16-date population
still fires, and always will, because it reflects a standing exclusion,
not a bug); only its citation comment is corrected. test_fiuv_ordo.ml's
F3-specific predicate/count assertion is removed, matching this file's own
prior F2/F4 closure discipline.

lib/ is untouched. dune test: 676/676. make check
(COLITUR_EXHAUSTIVE_SWEEP=1, full 1583-9999 domain): 678/678.
</content>
</entry>
<entry>
<title>feat(ef): the Gloria in excelsis, RG 431-432, deferring to Breviary 237-238</title>
<updated>2026-08-22T15:56:42Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T15:56:42Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=f4cc032d7e812d716ff6b5df8192f79a2560e8f0'/>
<id>urn:sha1:f4cc032d7e812d716ff6b5df8192f79a2560e8f0</id>
<content type='text'>
Phase 2 of celebrant-rubrics-phase1: colitur rubrics gains a fifth
column, whether the Gloria is said. Follows the Creed's own seam
exactly -- Rite.t.gloria, Liturgical_day.t.gloria, wired through
calendar.ml the same way.

RG 431(a)/432(a) defer the Gloria to the Breviary's own Te Deum rule
(nn. 237-238), so te_deum is implemented as its own named predicate,
cited clause by clause, not collapsed into a colour heuristic. 431(c)
(Holy Thursday, the Easter Vigil Mass) and 432(b)/(d) (violet; a
Requiem) are independent overrides checked ahead of the Te Deum-derived
answer. Every clause this engine has no dimension to model
(votive Mass classes, the wider n.302 "Missa festiva" categories) is
stated as N/A with its own reasoning, not silently dropped.

Validated against the FIUV universal Ordo (Gloria and Te Deum) and all
three LMS editions (Gloria). A first pass over-trusted a clean-looking
15-for-15 FIUV contradiction of 237(b)'s own Septuagesima exception and
replaced it with a blanket "every Sunday" rule; the evidence was itself
corrupted -- the FIUV extractor recognised only one of the source's two
Te Deum negations ("non dicitur", not "sine"), so every "sine Te Deum"
Sunday read wrongly true. Fixed in tools/extract_fiuv_ordo.ml, fixture
re-extracted, and the literal 237(b) reading restored once the
corrected data confirmed it. A second bug surfaced alongside it (Palm/
Passion Sunday wrongly reading true via Temporal_ef.named's own table
membership, then Christ the King wrongly reading false from an
over-broad fix) is closed with an explicit two-slug exclusion.

Domain-wide 1583-9999: every violet or Rose day is gloria=false except
the Easter Vigil (RG 431(c) lex specialis), every Requiem is
gloria=false, both measured exhaustively, zero exceptions. Mutation-
proved: disabling 431(c) reddens 8 tests including all four oracle
comparisons; disabling 238(c)'s feria-I-classis exclusion reddens
exactly the dedicated Ash Wednesday unit test, a genuine blind spot in
both oracle layers, reported rather than hidden.

Two open, cited findings, neither fixed here (out of this task's
"follow creed's exact seam" scope): a privileged Lenten/Passiontide
feria carrying one commemoration reads Gloria=true in the LMS Ordo but
Te-Deum=true/Gloria=false in FIUV -- the two oracles disagree with each
other, not merely with colitur (data/ef/expected-divergences-lms.sexp
L5, expected-divergences-fiuv.sexp F3); and a pre-existing, uncited
Colour.Violet bug on Rogation Monday/Tuesday in Temporal_ef.temporal,
surfaced by this comparison but root-caused as a separate defect (L6).

day/readings verified byte-identical against a build from the branch
tip before this task (v0.10.1's own tag predates an already-landed
bissextile fix that legitimately changed both, so it is not the right
baseline).

671 tests green (dune test); 678 with the exhaustive sweep
(COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force, ~104s).
</content>
</entry>
<entry>
<title>feat(ef): implement the calendarium's bissextile February shift</title>
<updated>2026-08-22T14:40:24Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T14:40:07Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=60e87914718dd2c8e69bb89d8cc48d6bef9bfc74'/>
<id>urn:sha1:60e87914718dd2c8e69bb89d8cc48d6bef9bfc74</id>
<content type='text'>
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-&gt;25 February and St Gabriel of Our Lady of Sorrows
27-&gt;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 -&gt; (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-&gt;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" -&gt; "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.
</content>
</entry>
<entry>
<title>docs(L3): the bissextile rubric is scan-verified after all</title>
<updated>2026-08-22T13:19:25Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T13:19:25Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=219c0ca6884a634e83293c62b27cca990fa25854'/>
<id>urn:sha1:219c0ca6884a634e83293c62b27cca990fa25854</id>
<content type='text'>
L3 recorded that the leap-year shift rested on the LT.txt transcription
alone, the scans having been searched without result. It is in scan2.txt
at 3050-3058, OCR-damaged but unmistakable.

The earlier search missed it for a findable reason, now written into the
entry: the OCR mangles the saint and the keyword alike -- "Matthue",
"Cabrielis", "bi&amp;sextili" -- so neither "Matth" nor "bissext" matches. It
turns up on the undamaged phrase "februarius est dierum".

Transcription and scan now agree, which makes this two witnesses of one
document rather than one. Still one document; the citation continues to say
calendarium rather than RG, because a calendarium footnote is what it is.
</content>
</entry>
<entry>
<title>test(lms-ordo): extend the LMS witness layer from one year to three</title>
<updated>2026-08-22T12:51:07Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T12:51:07Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=72dd2426f020f83a392158ead7bd15b36088fd08'/>
<id>urn:sha1:72dd2426f020f83a392158ead7bd15b36088fd08</id>
<content type='text'>
Generalises tools/extract_lms_ordo.ml's start-of-body detection: the
hardcoded "End of November 2024" sentinel assumed every edition opens
with an "End of November" stub section. The 2023-2024 edition has none
(Advent Sunday 2023 fell on 3 December, so the compiler folded the two
tail days into the "December 2023" header directly) -- the generalised
detector anchors on the body's own "ORDO" title line instead, verified
unique in all three known editions and distinct from the Table of
Contents' lowercase "Ordo" entries.

Extracts test/fixtures/lms-ordo-2023-2024.sexp (397 rows) and
lms-ordo-2025-2026.sexp (399 rows), each with a provenance header
carrying its own SHA-256, source citation, and a per-edition
characterisation record: five opposite-prediction Creed probes,
independently re-verified against this run's own extracted rows (a
failed probe is now a hard die, not a printed claim). The 2025-2026
edition needed a different sharp II-class pairing than 2024-2025's
Joachim/Stephen one, because Joachim (16 August) is impeded by a Sunday
that year -- recorded in the fixture header, not silently swapped.

test/test_lms_ordo.ml is refactored into a parameterised make_suite,
instantiated once per edition; every count Task 6 hardcoded against the
single 2024-2025 window is now a per-edition parameter, several of which
turned out to differ once measured (BVM-Saturday population 12/14/13,
Ascension-week exclusion 1/3/2). Two mapping gaps surfaced only by the
new windows and fixed here (test-side, not colitur): Low Sunday reached
via Preceding_sunday for the first time (absent from 2024-2025's own
window), and the Ascension-week exclusion was wrongly keyed off week
number alone -- Rogation Monday also resumes week 6's Sunday but falls
BEFORE Ascension, not after, and the Ordo prints the ordinary Sunday
text there. Re-bounded by date, against Ascension and Pentecost.

Two genuine divergences surfaced in the 2023-2024 window and are
allow-listed (L3, L4) rather than fixed, per this task's no-lib-changes
scope:

- L3 (verdict ordo): colitur has no bissextile calendar rule. The 1962
  Missal's own calendarium moves St Matthias from 24 to 25 February in
  leap years (docs/research/LT.txt:5011); colitur keeps him on the 24th
  every year. Domain-wide upper bound measured with a throwaway sweep:
  1,650 of 2,041 leap years in 1583-9999 currently observe him there.

- L4 (verdict open): Christmas Eve falling on the 4th Sunday of Advent
  (2023-12-24, roughly 1 year in 7). colitur says the Creed is said,
  reading RG 475(a)'s Sunday clause; the Ordo says it is not. RG 30(a)'s
  own "locum tenet ... nulla fit commemoratio" for this exact vigil
  reads like RG 16(a)'s Feast-of-the-Lord-on-Sunday shape, which colitur
  already treats as Creed-preserving -- but RG 475(a) names "festo"
  specifically, and a vigil is its own liturgical-day category (RG 35),
  so the counter-reading is real too. Left open rather than adjudicated.

All 630 tests green (dune test), 631 with the exhaustive sweep.

Claude-Session: https://claude.ai/code/session_017ZBxCCRM2ojnBupp3SBxV9
</content>
</entry>
<entry>
<title>fix(ef): RG 476(f) -- the Creed is not said at a Requiem Mass</title>
<updated>2026-08-22T11:38:27Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T11:38:27Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=41263d60432fadd2aef3f04de66b60561f89cbec'/>
<id>urn:sha1:41263d60432fadd2aef3f04de66b60561f89cbec</id>
<content type='text'>
colitur said the Creed IS said on All Souls' Day and every other
Requiem-shaped day: RG 475(b)'s "in festis I classis" branch fired on
rank alone, with nothing checking RG 476(f), "Non dicitur symbolum ...
f) in Missis defunctorum". Allow-listed as L1 in
expected-divergences-lms.sexp on the argument that [creed] has no
notion of a Requiem Mass in its inputs and could not express the rule
without a signature change.

That argument does not hold. Colour.Black is used by exactly two
celebrations in the whole engine, verified by grepping every
occurrence in lib/ and data/: commemoration-of-all-souls
(data/ef/sanctoral.sexp) and Good Friday (temporal_ef.ml, already
false via the earlier RG 23(b) feria exclusion and has no Mass at all
in the 1955-restored Holy Week). So on every day this engine can
construct, colour = Black if and only if the Mass is a Requiem -- a
citable implication (RG 117 assigns black to Masses of the dead) on
this data, not a heuristic.

Rite_ef.Rubrics_ef.creed now reads observed.colour as RG 476(f)'s own
guard, positioned ahead of 475(b)'s rank branch. A new test,
test_colour_black_population_is_exactly_two, sweeps both the shipped
data and Temporal_ef's own code across a century and fails loudly the
day a third Colour.Black celebration is ever introduced, so the proxy
cannot silently rot.

L1 is closed in expected-divergences-lms.sexp, citation preserved.

Blast radius, measured (full 1583-9999 sweep, grouped by observed
slug): 8 416 days change from true to false, every one
commemoration-of-all-souls (missing from exactly 1 of the 8 417 domain
years, a boundary-year transfer effect at 1583/9999). A further 8 416
Colour.Black days are Good Friday, unaffected (already false before
this fix). colitur day/readings stay byte-identical to v0.10.1
(checked directly against a v0.10.1 worktree build, 9 domain-spanning
years); colitur rubrics changes on exactly the 8 416 days above.

colitur emit --format sexp's pretty-printed line count for 2027 moved
9010 -&gt; 9011 as a side effect: Sexplib.Sexp.to_string_hum wraps by
column width, and All Souls' Day 2027's record grew one wrapped line
because "false" is one character longer than "true". Cosmetic only --
no field's data changed -- and pinned in test/cli.t with the
measurement recorded.
</content>
</entry>
<entry>
<title>test(ef): the LMS Ordo as a sixth validation layer</title>
<updated>2026-08-22T10:58:15Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T10:58:15Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=3bfa0c459e3c0b5bfa962b7dbb0227db5a8ba09f'/>
<id>urn:sha1:3bfa0c459e3c0b5bfa962b7dbb0227db5a8ba09f</id>
<content type='text'>
An independent lineage -- neither Divinum Officium, missalemeum nor
lectio -- covering the Mass formulary and the Creed. Characterised
before use, per the discipline the extraordinaryform.org Ordo's
blanket St Lawrence vigil gap taught this session: five opposite-
prediction Creed probes (Sunday/feria, octave-override vs plain
II-class, I-class) all confirmed against the raw extracted text
before a single divergence was adjudicated, recorded in the
fixture's own provenance header.

tools/extract_lms_ordo.ml hand-parses pdftotext -layout output (no
Str/regex, frozen deps) into test/fixtures/lms-ordo-2024-2025.sexp,
400 day-rows (2024-11-27..2025-12-31). Gl/Cr print per Mass-option,
not per day; the extractor takes the first pair in reading order,
which the source's own layout guarantees is the universal entry's,
since a diocesan variant always follows it, never precedes it. The
Ordo's I-V roman numeral ("Missae de sancta Maria in sabbato", RG
309(a)) is matched whole-line only, never by substring -- "V Mass of
BVM" is a substring of "IV Mass of BVM".

test/test_lms_ordo.ml compares two axes 1:1 by date:
  - the Creed (RG 475-476): 399 of 400 days comparable (Good Friday
    has no Mass at all, asserted as the only such day); one genuine
    divergence, adjudicated to the ORDO, not colitur -- All Souls'
    Day 2025-11-03 is a Requiem Mass, and colitur's own creed
    predicate has no notion of one, a pre-existing scope gap
    rubrics_ef.ml already documented in its own header before this
    task existed.
  - the BVM-Saturday seasonal Mass selection, the addendum's own
    "sharper check": all 14 Votive days in the window match their
    season's own numeral exactly, both directions, independently
    re-derived from RG 309(a) rather than calling colitur's private
    function.
  - the formulary override, for the three sources it can honestly
    discriminate (Proper 179, Preceding_sunday 66, Common 2, all
    clean); Own_slug (139) is excluded with evidence, not silently --
    several ferial slugs carry citations byte-identical to their
    Sunday's own, so the Ordo's override line cannot distinguish the
    two representations.

data/ef/expected-divergences-lms.sexp carries the one adjudicated
entry (L1), cited to RG 476(f).

Mutation-tested: inverting RG 475(a)'s Sunday clause reddens 10
existing Rubrics_ef unit tests AND this new layer's own comparator,
independently, on a data source none of the other five layers touch.
Reverted after confirming.

No lib/ changes. day/readings/rubrics output re-confirmed byte-
identical (1583, 2026, 2038, 9999) after this task; all three gates
green (dune test, exhaustive sweep, make check).
</content>
</entry>
</feed>
