<feed xmlns='http://www.w3.org/2005/Atom'>
<title>colitur.git/test/dune, branch v1.0.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=v1.0.0</id>
<link rel='self' href='https://git.labunix.xyz/colitur.git/atom?h=v1.0.0'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/'/>
<updated>2026-08-24T14:16:59Z</updated>
<entry>
<title>feat(ordo): wire the extraordinaryform.org preface column in as a third witness</title>
<updated>2026-08-24T14:16:59Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-24T14:16:59Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=0d061abc7cc5cdc51ded6ee69e00e187813f5e1b'/>
<id>urn:sha1:0d061abc7cc5cdc51ded6ee69e00e187813f5e1b</id>
<content type='text'>
Extends the preface comparison (RG 482-499) with a third, independent
publisher, extraordinaryform.org's three annual Ordo editions
(2024-2025, 2025-2026, 2026-2027), previously declined for two reasons
that are now resolved:

- "Advent" is not a preface: RG 494(b) grants the Trinity preface on
  every Advent SUNDAY, RG 498 the residual Common on every Advent
  FERIA; this source's own "Advent" label covers both indiscriminately
  (confirmed live on all 11 non-impeded Advent Sundays in the corpus).
  Classified by the day's own civil weekday, not a static table.
- The known Vigil-of-St-Lawrence gap is reconfirmed, with a nuance not
  present in the earlier audits: colitur's own RG33-third-trigger now
  omits the vigil in some years too, so the corpus's gap and colitur's
  answer coincide in 2025 (a full match, not a coincidence) while 2027
  still shows the classic identity-wrong-but-preface-invisible shape.

Re-derives the known menu-trap office filter (Requiem-skip, "and "-chain)
against the live JSON and finds a second, general pattern: "Saturday of
Our Lady" (RG78's BVM Saturday Office), whenever listed, is
unconditionally the office -- checked exhaustively across all 38
instances in the corpus, zero counter-examples. A third, generic
"absorption" rule was deliberately not built: it would resolve 2 of the
11 residual divergences but wrongly misfires on a structurally identical
but semantically different shape (an optional Rogation-day Mass option).

The JSON's own extraction carries a genuine classifier gap: parse_ordo.py's
hardcoded PREFACES set omits "Christ the King", misfiling it into comms;
recovered in the generator, not left blank.

11 of 1088 comparable rows diverge, resolving to 7 adjudicated root
causes (E1-E7): two Commemoration_only Marian titles reduced to
commemorations (Mt Carmel, Ransom), two genuine sanctoral data gaps
cross-confirmed absent by the FIUV/LMS witnesses (Miraculous Medal,
St John before the Latin Gate), two single-witnessed efdotorg outliers
against FIUV/LMS agreement (St Michael's Dedication, All Saints on a
Sunday), and one isolated source labelling slip.

Mutation-tested: corrupting the RG495 BVM-Saturday clause reddens 9
tests across this new layer and both existing Ordo witnesses.

Per-edition agreement: 358/363 (2024-2025), 358/363 (2025-2026),
361/362 (2026-2027).
</content>
</entry>
<entry>
<title>test(fiuv-ordo): add the FIUV universal Ordo as a second, independent witness</title>
<updated>2026-08-22T13:11:43Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-22T13:11:43Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=96aed1b6f04ef89e8f3d18af8b13e6fd30dbd4d2'/>
<id>urn:sha1:96aed1b6f04ef89e8f3d18af8b13e6fd30dbd4d2</id>
<content type='text'>
Wires in the FIUV (Foederatio Internationalis Una Voce) Ordo for
2025-2026 as validation layer seven -- the first UNIVERSAL (not
diocesan) source in this project, and the first compiled by someone
other than the LMS editions' own Peter Day-Milne (Joseph Shaw, FIUV
President).

tools/extract_fiuv_ordo.ml hand-parses pdftotext's -layout dump of the
Latin-language ordo (no Str/regex, frozen deps). Three real parsing
traps were found and fixed by tracing actual false results against the
raw source, not assumed in advance:

- "Gloria" is also the first word of "Gloria Patri" (the psalm
  doxology), which can appear INSIDE the very Mass clause being scanned
  (Good Friday: "...omittuntur ps. Iudica me et Gloria Patri), Gloria,
  sine Credo..."). Guarded by rejecting any "Gloria" hit whose next
  token is "Patri".
- Christmas Day's own rubric uses the PLURAL "Missae"/"Missae" ("tres
  Missae celebrantur..."), never the singular "Missa" every other real
  day anchors on -- silently produced gloria=None/credo=None on the one
  most doctrinally unambiguous day in the calendar until traced and
  fixed, guarded in turn against "Missae defunctorum" (an unrelated
  Requiem-prohibition notice appearing at the end of many day-blocks).
- The Vespers boundary (bounding the primary Mass option before a
  second "Vel Missa" alternative or before Vespers information) missed
  the ligature spelling "VESPERÆ", the dominant form in this source,
  letting a whole day's trailing prose leak into the captured [praef]
  field on the task brief's own worked example day (19 September).

A distinct second stop-marker bug: the malformed trailing entry this
source shares structurally with the LMS PDFs (a stray, mislabelled
duplicate of 1 January) was initially over-matched by a generic
"first token is 4 digits" heuristic, which false-positived on an
indulgence-decree date citation wrapped mid-sentence in October
("...20 augusti / 1885, 26 augusti 1886..."), truncating the extraction
to 308 of 400 real days. Fixed by anchoring on the tail entry's own
distinctive "1st Jan" opening instead.

Five opposite-prediction Creed probes are re-verified by the tool
itself against its own extracted rows (a failed probe is a hard exit,
not a printed claim) before the fixture is written.

test/test_fiuv_ordo.ml compares the Creed against colitur across all
399 comparable days (Holy Saturday excluded, no Mass that day) --
CLEAN, zero unexplained divergences, a genuine second confirmation of
{!Rite_ef.Rubrics_ef.creed} independent of the LMS lineage. [praef],
[te_deum] and [class_] (including the FIUV ordo's own "III cl." vs
"III cl. (Priv.)" Cum Sanctissima convention, stated on its title
page) are captured into the fixture but deliberately not compared --
colitur has no Gloria/preface predicate yet, and its default
configuration models no Cum Sanctissima overlay to compare the class
convention against.

All 634 tests green (dune test), 635 with the exhaustive sweep and
make check. No lib/ file touched.

Claude-Session: https://claude.ai/code/session_017ZBxCCRM2ojnBupp3SBxV9
</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>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>
<entry>
<title>feat(lang): traditions.ini, and its install rule</title>
<updated>2026-08-20T14:01:39Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-20T14:01:39Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=9dfa264f2941f1ca38eff08b6157a94d332cffbd'/>
<id>urn:sha1:9dfa264f2941f1ca38eff08b6157a94d332cffbd</id>
<content type='text'>
Which book a reference denotes does not vary by language, so it lives in
its own file rather than in la.ini beside [weekday].

Six mappings, not four: Osee/Jonas are the same question as 3 Kings in
transliteration form.

The install rule is added in the same commit deliberately -- lang/ once
shipped without one, so the feature worked from the source tree and was
broken once installed.

bin/dune gains colitur_citation as a linked library, needed for the new
loader; lang_list's directory scan now excludes traditions.ini, which is
not a language file and does not parse as one.
</content>
</entry>
<entry>
<title>feat(citation): canonical book ids and tradition mapping</title>
<updated>2026-08-20T12:40:12Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-20T12:40:12Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=405910d2fd245e7a11e09eecb8c6fffb68d2169c'/>
<id>urn:sha1:405910d2fd245e7a11e09eecb8c6fffb68d2169c</id>
<content type='text'>
Seven books arrive in two spellings, inherited from lectio's ini and
ultimately from Divinum Officium. Collapse them onto one id here rather
than editing generated data.

Naming and renumbering are kept apart: a tradition decides which book an
id denotes, a language file decides what it is called.
</content>
</entry>
<entry>
<title>feat(templates): ordo booklet and wall calendar in Typst</title>
<updated>2026-08-20T08:07:37Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-20T08:07:15Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=6aebb3ec513c0177a39c2eb8d4b741e90d6f53f4'/>
<id>urn:sha1:6aebb3ec513c0177a39c2eb8d4b741e90d6f53f4</id>
<content type='text'>
Adds templates/ef/ordo.typ (A5, one week per page, each day framed with
a colour swatch, real names, every fixed string through term.*) and
templates/ef/grid.typ (A4 landscape, one month per page, 7 columns,
colour-filled cells, Epistle/Gospel sigla), matching what ordo.tex and
grid.tex already do.

Typst resolves its own table of contents inside a single compile: no
pageref/aux-file dance, unlike pdflatex's own two-pass need for
ordo.tex. ordo.typ's TOC is one flat heading per week (Month . Week N)
rather than ordo.tex's own month-once/weeks-nested layout, since the
view model has no first-of-month flag for a template to test and
inventing one would be new engine state for a cosmetic grouping.
grid.typ deliberately diverges from grid.tex's own partial-fill
behaviour for a 5-week month: Typst's row-size list repeats its own
last entry for every remaining row, so a two-entry rows spec fills the
page completely regardless of week count, where LaTeX's fixed cellh
leaves a 5-week month's bottom sixth blank on purpose. Both divergences
are documented in the templates' own headers.

Two bugs found and fixed while building these against the real typst
0.14.2 binary: two stray hash characters in grid.typ's header comment
that were not actually inside a line-comment (would have been parsed
as Typst code, not prose); and two lines merging into one wherever they
were separated only by a bare newline (still the same soft-wrapped
paragraph in Typst, unlike LaTeX's own explicit paragraph break) --
fixed with a trailing backslash to force a real line break without
adding inter-paragraph spacing, verified against a full-year render
(zero typst warnings across all 365 days of 2027, in both templates).

Goldens (test/golden/ordo-2027.typ, test/golden/grid-2027.typ) were
generated through the harness's own View.of_days/Template.render_string
path, via a throwaway generator, NOT through the CLI: the CLI's default
language table differs from the harness's own English-chained-to-Latin
table, confirmed live (diffing CLI output against the harness's own
render showed exactly the expected language divergence and nothing
else) -- the same trap this project has hit before.

make check-templates now typesets both templates with the typst binary,
using the same SKIPPED-and-exit-0 shape the pdflatex/groff blocks
already use when their own tool is absent, verified in both directions:
absent (PATH without typst) skips loudly and exits 0, and a
deliberately corrupted template fails the target with a non-zero exit
and typst's own error text.
</content>
</entry>
<entry>
<title>feat(lang): Latin sanctoral names, and English</title>
<updated>2026-08-19T13:07:06Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-19T13:07:06Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=92559825f9ad3e0f751d2c2022ffe000f23358ef'/>
<id>urn:sha1:92559825f9ad3e0f751d2c2022ffe000f23358ef</id>
<content type='text'>
Sanctoral names are transcribed from the Missal's own calendarium and
kept in the GENITIVE, as the Missal prints them -- noted in the file so
nobody corrects them to the nominative.

English reuses the 327 names already in data/ef/sanctoral.sexp rather
than retyping them, and declares fallback = la, so an untranslated day in
an English booklet shows Latin rather than a slug. The test asserts the
FALLBACK works rather than that en.ini is exhaustive: that is what makes
a partial translation shippable from its first line.

Coverage now demands a name for every slug the engine can emit across
2020-2045, temporal and sanctoral alike.
</content>
</entry>
<entry>
<title>feat(lang): Latin temporal names from the Missal</title>
<updated>2026-08-19T12:12:52Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-19T12:12:52Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=f00f7a66d073815249e94cec1b6ef10539d773e7'/>
<id>urn:sha1:f00f7a66d073815249e94cec1b6ef10539d773e7</id>
<content type='text'>
Every entry is transcribed from the 1962 Missal's own propers headings in
docs/research/LT.txt and cites where it came from; names constructed by
following a neighbouring pattern are marked as such, so a reader can tell
transcription from inference.

The coverage test is the point of this commit. It walks every day of
2020-2045 and fails naming any slug with no Latin name -- the test that
would have caught the original defect, where a printed booklet said
ef-septuagesima-sunday-2 because nothing asserted that names exist.

The three Triduum names reuse the exact strings temporal_ef.ml already
carries, so the engine and the language file cannot disagree.
</content>
</entry>
<entry>
<title>feat(naming): the language table</title>
<updated>2026-08-19T11:34:53Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-19T11:34:53Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=45bcbde502e07ad73b96039fcbb62471a3c94781'/>
<id>urn:sha1:45bcbde502e07ad73b96039fcbb62471a3c94781</id>
<content type='text'>
Maps strings to strings and nothing else -- no calendars, no dates, no
filesystem. That is what lets every command use it without the kernel
learning about presentation.

Every lookup is total, and a miss returns THE KEY rather than the empty
string. A partial translation is therefore usable from its first line,
and the fully-degraded case is exactly today's output (bare slugs) rather
than a blank page.

--raw is a real identity table, not a special case threaded through every
call site: one value the whole program passes around.

Reuses Overlay_ini's INI reader rather than growing a second one that
would drift in its comment, quoting and trimming rules; parse_sections is
exposed in the .mli for that, with no behaviour change.

Fixes one defect found while running the brief's own tests rather than
transcribing them blind: weekday's internal lookup key is an English
day-name word (month's is already the numeral string), so on a miss it
echoed that word instead of the documented numeral, breaking both the
0=Sunday convention and Lang.raw's own identity contract for weekday.
weekday/month now fall back to string_of_int n directly on a miss
instead of through get's generic echo-the-search-key path; month is
byte-identical since its key already equals string_of_int n.
</content>
</entry>
</feed>
