<feed xmlns='http://www.w3.org/2005/Atom'>
<title>colitur.git/CLAUDE.md, branch v0.1.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.1.0</id>
<link rel='self' href='https://git.labunix.xyz/colitur.git/atom?h=v0.1.0'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/'/>
<updated>2026-08-17T14:11:25Z</updated>
<entry>
<title>feat(cli): a Makefile, a man page, and --help</title>
<updated>2026-08-17T14:11:25Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T14:11:25Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=7055723f8b79240ab2df1353eaaf3761f65414a9'/>
<id>urn:sha1:7055723f8b79240ab2df1353eaaf3761f65414a9</id>
<content type='text'>
Three things the project had no answer for: how to install it without
knowing dune, where to read about it, and what it does when asked.

Makefile, same shape as lectio's -- PREFIX ?= $(HOME)/.local, BINDIR,
MANDIR, and the '## '-comment help target -- so the two siblings are
driven the same way. Every recipe wraps dune in `opam exec --`, which is
the actual point of having one here: `make build` works from a plain
shell with no `eval $(opam env)` first. install goes through `dune
install` rather than a hand-rolled copy, because the binary finds its
calendar data relative to its own path; the man page is installed
separately to share/man/man1, matching lectio. install and uninstall
were both run against a scratch prefix and checked: uninstall leaves
zero files behind.

PREFIX defaults to ~/.local because that is where lectio installs and
where it actually lives on this machine, so colitur lands on an existing
PATH with no shell change. An earlier install this session went to
~/opt/colitur, which was me over-applying a rule meant for third-party
tools to one of the author's own projects; it has been removed rather
than left as a second, staler binary competing on PATH.

man/colitur.1 documents the four commands, both output formats and why
they differ, COLITUR_DATA_DIR and its refusal to fall back, the data
resolution order, exit statuses, and -- deliberately -- the limitations:
EF only, Epistle and Gospel only with the chants unbuilt and rejected
rather than guessed, and the BVM Saturday Mass-selection gap. A man page
that only lists what works is half a man page. Renders clean under
`groff -ww -z`, no warnings.

--help prints to stdout and exits 0; a usage error prints one line to
stderr and exits 2. That is the Unix convention rather than a
preference: asking for help succeeded and should be pipeable, being
invoked wrongly did not and must not pollute stdout. Both directions are
asserted in cli.t, along with a loop confirming every command the help
text advertises is one the dispatch actually accepts -- the check that
catches help drifting away from the code.
</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>feat(cli): colitur readings, one line per day</title>
<updated>2026-08-17T13:24:27Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T13:24:27Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=cba04b3033f23b5c2515c9e648f2b83344716224'/>
<id>urn:sha1:cba04b3033f23b5c2515c9e648f2b83344716224</id>
<content type='text'>
The lectionary has been resolvable since Task 4 but invisible from the
command line: `colitur day` prints no citations, so the branch's whole
deliverable could only be seen through the test suite.

A separate command rather than extra columns on `day`, which is where the
plan pointed. Its instruction was to append the Epistle and Gospel to
each row "matching the existing column style", and that turns out not to
be possible: a citation contains spaces and commas ("Ezech 34:11-16",
"Ecclus 51:1-8, 12") while a day row is space-separated with a
variable-length +slug commemoration tail, so appending them leaves the
row unsplittable -- no awk or cut field number recovers where the Epistle
ends. That is the opposite of what the row is shaped for.

So `day` keeps its format byte-identical, asserted directly in cli.t
rather than left implicit, and the citations get their own row with
" | "-delimited fields, safe for values containing spaces. Both formats
are a stopgap and say so in the source: the design calls for one schema
rendered through a logic-less template engine, and two ad-hoc formats are
easier to retire later than one overloaded format whose parsing rules
nobody wrote down.

The year walk is now shared. day_report and readings_report differ only
in how a day is printed, and the two-liturgical-year indexing -- with its
own reasoning about civil-versus-liturgical spans -- is exactly the part
that must not be duplicated and drift.

"-" for an absent part, though no EF day can currently print one: layer 2
asserts exactly one First and one Gospel on every day of every year
1583-9999. The CLI still does not assume a guarantee the kernel makes
about data rather than about types.

cli.t gains the four chain-step cases test_golden.ml pins against the
scans, so the CLI path is checked to agree with the library path, plus
the 2 January line, which reads the Circumcision's Mass under the
Missal's own ferial rubric (scan1:6523-6526) and not RG 17(a). Verified
the cram tests actually run and have teeth: corrupting one expectation
produces a diff and exits 1.

CLAUDE.md: state, test count (369, 370 with the sweep), the readings
command and why it is separate, and What's next -- the lectionary landed
early rather than inside Plan 4, so what remains there is OF's own
lectionary, not the mechanism. Chants stay deliberately unbuilt, and
Validate now rejects any part outside First/Gospel.
</content>
</entry>
<entry>
<title>docs(ef): fix round 2 -- three miscitations and a recorded blind spot</title>
<updated>2026-08-17T12:26:42Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T12:26:42Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=1915f3bb9d74998a411bd55ae658cb3f58fd3477'/>
<id>urn:sha1:1915f3bb9d74998a411bd55ae658cb3f58fd3477</id>
<content type='text'>
Comment and citation corrections found by review, plus one finding that
survived an attempt to reconstruct it. No behaviour change; the suite is
unchanged at 358 green.

The ferial rubric "Diebus ferialibus a 2 ad 5 ianuarii Missa dicitur ut
die 1 ianuarii" was attributed to RG 17(a) in three test comments. It is
not RG 17(a). RG 17(a) (LT.txt:843) fixes only WHEN the Holy Name is
kept -- "celebrandum dominica quae occurrit a die 2 ad 5 ianuarii; secus
die 2 ianuarii". The rubric quoted is a Mass-propers rubric printed
under the Sanctissimi Nominis Iesu heading (scan1:6523-6526, corroborated
scan2:7216), governing what the ordinary ferias of that window say when
they are not the feast at all. Two rules sharing a date window. Fix
round 1 had already corrected this on the data side; the generator's own
comment was right throughout. Only the test comments were stale.

test_differential.ml named bootstrap_lectionary.ml's derived_entries as
the source of ef-holy-name's citations. That binding no longer exists --
it was the mechanism that derived them from ef-holy-name-sunday's
wrongly-widened ini translation, removed in Task 9 because the
derivation was itself the error. They are hand-authored from the scans
now, as holy_name_entries.

M26's shape 1 described its 21 rows as votive Masses of the BVM "on an
otherwise-unoccupied feria, not only a Saturday", splitting them into 4
BVM-Saturday rows and 17 "ordinary weekday ferias". Every one of the 21
is a Saturday, each checked individually against date -d. The error was
not merely verbal: it made the gap look broader than a single cause and
pointed away from the one rule that explains all 21. The sub-groups
differ by season, not weekday, and only in what colitur shows in the
votive Mass's place. One gap -- the office is built (RG 91 entry 27),
the seasonal selection among the five Masses is not.

Recorded, not fixed: step 4 of the reading chain has no oracle witness
at all. This began as a note to write up a live-oracle confirmation for
Felicitas and Perpetua; the reconstruction contradicted its premise. The
sweep ran over 2028, where 6 March resolves as a Lenten feria with the
saint admitted only as a commemoration, so her own Mass is never read
that year. The finding underneath is firmer: only five saints route
through a Common, they are the observed office on five days in all of
2005-2050 (isidore-of-seville 2008/2035/2046, frances-rome and
sts-felicitas-perpetua both 2038), two are never observed in 46 years,
and none falls in layer 4's window. Layer 3 does not cover it either --
lectio resolves the literal "-"/"-" sentinel there, which is what C18 is
gated on, so it confirms only that colitur emits a citation where lectio
emits none, never that it is right. Closing it needs the oracle fixture
extended to 2035, 2038 or 2046; that is a fixture-scope decision.

Register: sections 6.6 and 6.7. CLAUDE.md's layer-blindness list gains
the step-4 entry.
</content>
</entry>
<entry>
<title>docs(ef): fix round 1 corrections (F2-F5) -- inert fields, a date, an attribution, RG434(b)</title>
<updated>2026-08-13T18:55:43Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-13T18:55:43Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=cbf6826edc77e3ad5a813237bae27e367221452c'/>
<id>urn:sha1:cbf6826edc77e3ad5a813237bae27e367221452c</id>
<content type='text'>
F2: the task report's "colour/subject/names on the Litanies entry are
currently inert" was false for names -- test_oracle.ml's identity axis
reads Names.find on every commemoration, and the invented English name is
exactly why 2026-04-25 registers as a Comm_identity_mismatch, the reason
M5 had to be re-gated. Corrected precisely, field by field, in the report.

F3: Easter 2027 is 28 March, not 18 April, as previously stated in the
report's own "layer 4 is blind to the transfer" reasoning. The conclusion
survives (28 March is not 25 April); the date is corrected.

F4: "the exhaustive property sweep caught this immediately" was a wrong
attribution, in the report, the register, and calendar.ml's own comment.
The committed exhaustive sweep walks 1583-9998 in order and aborts at the
first failure; the years actually reported (5700, 4747) were draws from
prop_invariants, the default dune test run's 200-year random sample.
Corrected in all three places.

F5: the Litanies' privileged commemoration is due in the MASS specifically
(RG 108 + RG 81), never a separate Office answer -- colitur emits one
resolved day, and the M20 adjudication rests on that being the Mass
reading. Stated explicitly now in M20's own note, the register, and
precedence_ef.ml's own RG111(b) comment.

Also added to M20 and the register: Rubricae Generales Missalis Romani
n. 434(b) ("VIII - De diversis Missae partibus", "D) De orationibus", "I
- De orationibus in genere"), verified word for word against all three
documents -- word-identical to RG 111(b) but explicitly scoped to the
Mass ("post orationem Missae"), answering the objection that RG 111
(Caput XVI, which RG 106 says governs both Office and Mass) might be read
as Office-shaped. Moves the M20 adjudication from "moderate-high, not
certain" to near-certain.
</content>
</entry>
<entry>
<title>docs: CLAUDE.md for the Major Litanies</title>
<updated>2026-08-13T18:16:04Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-13T18:16:04Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=f37c9126292670def8e7a43903b99721181556a5'/>
<id>urn:sha1:f37c9126292670def8e7a43903b99721181556a5</id>
<content type='text'>
Records RG80/109(f) as RESOLVED (was "NARROWED, deliberately not built"),
corrects a mis-citation carried in that entry (RG111(b), not RG111(c), is
the clause that makes a privileged Litanies commemoration displace St
Mark's own ordinary one), and narrows the shared "no channel for a
movable, Easter-relative commemoration candidate" blocker to Rogation
Wednesday alone -- the Major Litanies' own version of that blocker
dissolved by reusing the existing RG96 transfer machinery, a route not
available to Rogation Wednesday (nothing there is being transferred FROM
a fixed civil date).

Adds a "know what each layer cannot see" bullet: layer 3 (lectio) is
entirely blind to this whole change; layer 4 (missalemeum) sees the entity
and the RG111(b) question but is blind to the transfer specifically,
confirmed by mutation, since neither year in its 2026-2027 fixture window
is a trigger year.

Updates the stale Plan-3-era test count and the allow-list summary
(expected-divergences-missalemeum.sexp now 12 active entries, M5
corrected, M20 added, M18's count adjusted).
</content>
</entry>
<entry>
<title>docs: fix round 1 ride-along findings (F2-F7)</title>
<updated>2026-08-13T15:09:41Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-13T15:09:41Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=da0eca73fa2a7b2357bcc28c4dd7d8b001066685'/>
<id>urn:sha1:da0eca73fa2a7b2357bcc28c4dd7d8b001066685</id>
<content type='text'>
F2: test_christmastide_feria_slugs's 26 December assertions removed --
St Stephen/John/the Holy Innocents (RG 67-70) always outrank a Class4
Saturday candidate there, in every year, so the office can never
actually be observed on any day in the 26-28 December stretch. 3
January (no competing sanctoral entry, any year) used for the "-1-"
stretch demonstration instead, alongside the pre-existing 10 January
one.

F3: test_differential.ml's shared row type gains a subject field
(populated for colitur's own rows only; lectio's fixture has no such
column). C17's own predicate now also requires subject = "bvm" --
defence in depth against a future bug producing a white Class4
Saturday candidate some other way, particularly in Christmastide/
Paschaltide where colour alone could not catch it.

F4: Precedence_ef.band's entry-27 comment gains its RG 78 citation,
replacing "per the historical default that fills it".

F5: two report inaccuracies corrected -- band was already receiving a
real candidate 312,966 times pre-change (what was missing was its
identity, not its reality); the "Missae de S. Maria in sabbato" heading
quote was presented as "both scans, word for word" when both scans are
OCR-noisy there AND genuinely differ in abbreviation from each other --
corrected in temporal_ef.ml's own comment and the register alongside
the report.

F6: the colour rule gains a tighter citation chain -- RG 431(e) (the
Missal's own classification of this Mass as a "Missa votiva IV
classis... de B. Maria Virg.") -&gt; RG 121(a) (votive Masses take the
colour of the feast-type they correspond to) -&gt; RG 120(b) (BVM feasts
are white) -- reaching the same conclusion through the category (votive)
the Missal's own text actually places this Mass in, not by treating it
as a festum RG 91's own table structure says it is not.

F7: the oracle's real seasonal coverage recorded precisely in CLAUDE.md
and the register -- of 26 BVM-Saturday-office days in the 2026-2027
fixture only 17 are colour-discriminating; Time after Epiphany (5,015
observed days domain-wide) has zero oracle witnesses.

Full account in .superpowers/sdd/2026-08-12-colitur-rg16a/
bvm-saturday-report.md (local, gitignored).
</content>
</entry>
<entry>
<title>docs: RG 91 entry 27 (BVM Saturday) resolved</title>
<updated>2026-08-13T14:10:00Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-13T14:10:00Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=d5df5e79c731ac7f7f89969c0cafe564fdc6e8ab'/>
<id>urn:sha1:d5df5e79c731ac7f7f89969c0cafe564fdc6e8ab</id>
<content type='text'>
CLAUDE.md's "Unbuilt, recorded" list and Data section move to reflect
the closed gap: a new item 9 records the office's own build, citations
and measured blast radius; the allow-list counts move to 7 active
lectio entries (C17 new) and 11 active missalemeum entries (M2 closed).

docs/research/rules-register.md (gitignored, not tracked) gets the
matching update: §4's entry marked RESOLVED with a cross-reference,
the §6 open-item checkbox closed, and a new §6.4 with the full
primary-source account -- every scan reading quoted, the blast-radius
reconciliation, and the mutation-test record.
</content>
</entry>
<entry>
<title>docs: a name that matched no scan, and a blocker that was not real</title>
<updated>2026-08-13T11:45:46Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-13T11:45:46Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=67855ae3125148116df870bf1a9abeac5b501d5b'/>
<id>urn:sha1:67855ae3125148116df870bf1a9abeac5b501d5b</id>
<content type='text'>
Two corrections from the fix-round review, both to the record.

"Sabbato Sancto" is attested zero times in either photographic scan. The
scans print SABBATO SANCTO as the heading (once) and "Sabbato sancto" as
the running header (28x and 30x); the shipped casing appears only in the
electronic transcription's table of contents -- the source this
project's own methodology rule deprecates -- while the comment beside it
called the value "both photographic scans, word for word". Recased to
the running-header form, which is the convention the other three Latin
names in the file already follow, with a source note recording the
count. Third source-fidelity slip this week, and the first where the
wrong value came from the deprecated source itself.

The Major Litanies deferral was recorded with two false blockers. It
claimed a kernel signature extension was needed to suppress the feast in
transfer years: admit already takes ~temporal and disposition already
takes ~winner, both carrying the Easter office on 25 April, so a
rite-local slug test does it with zero kernel surface. And it implied
Easter Monday is unmarkable: ef-easter-1-monday occurs exactly 8417
times in 8417 years, as reliable as ef-easter-sunday. So the guarded
build -- never scored -- is a strict improvement, 8223 years newly
correct against 194 unchanged, and "worse than the gap" was true only of
the unguarded one.

Deferring is still right, for a reason nobody had found: 25 April is St
Mark, II class, so under RG 111(c) a privileged Litanies commemoration
would displace the day's existing ordinary commemoration in ~97.7% of
years -- an unmeasured blast radius through layers 3 and 4. That
measurement is the prerequisite. The 194 figure is exact and reproduces.

Also corrects a subject-audit list that named five months for six
entries, omitting the Precious Blood on 1 July.
</content>
</entry>
<entry>
<title>docs: close/narrow the Triduum and Litanies open items in CLAUDE.md</title>
<updated>2026-08-13T11:19:40Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-13T11:19:40Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=08c18dd43f0fb891806df1077cdf1bab35a59341'/>
<id>urn:sha1:08c18dd43f0fb891806df1077cdf1bab35a59341</id>
<content type='text'>
Item 5: the Sacred Triduum's own identity is RESOLVED (RG 91 entry 2),
full 1583-9999 blast radius measured at zero differing CLI lines --
the change is invisible to layers 2-4, visible only to the two golden/
unit tests built for it.

Major Litanies (RG 80) and Rogation Wednesday's own commemoration
(RG 87-89) are established from a photographic scan and fully cited,
but deliberately not built: both need a rite-computed, Easter-relative,
non-competing commemoration candidate -- a kind of thing
Precedence.resolve's architecture has no channel for. Measured, not
assumed: RG 80's own transfer clause triggers in 194 of 8417 domain
years (~2.3%), so building only the ordinary case would trade a known,
understood gap for a new wrong answer in those years.

Renumbers the trailing three architectural-debt items (5-7 -&gt; 6-8) to
make room.
</content>
</entry>
</feed>
