| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Groundwork for tagging. The project had no version anywhere: not in
dune-project, not in the binary, no CHANGELOG, no tags.
The version lives in two places -- dune-project, which generates
colitur.opam, and a constant in bin/main.ml, which is what --version
prints. Two rather than one because dune's watermarking only substitutes
in a release tarball, so a binary built the ordinary way from a checkout
would report a placeholder. The release target rewrites both and then
re-checks both, and finally requires the freshly built binary to report
the version it just wrote: a release that bumped one and not the other
would ship a binary disagreeing with its own package metadata.
--version is deliberately not embedded in the help text. cli.t pins
help's first line, and a version there would mean editing a test
expectation every release for no gain.
The release target mirrors lectio's, refusals included: no release from a
dirty tree, none without a CHANGELOG entry for that version, none whose
version bump silently failed to apply, and `make check` -- the full
1583-9999 sweep, not the sampling suite -- must pass before the tag is
created.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`dune install` produced a colitur that could not run: the binary locates
its data relative to its own path, nothing installed the four .sexp files
anywhere, and an installed colitur exited 2 unable to read sanctoral.sexp.
`dune build @install` produced an empty tree.
data/dune installs the four RUNTIME files into <prefix>/share/colitur/ef.
Deliberately not the two allow-lists: those describe where colitur and a
comparison oracle disagree, are read only by the differential and oracle
tests, and are meaningless to a running colitur -- installing them would
ship an assertion about lectio's and missalemeum's behaviour as though it
were calendar data. No glob, on purpose: a glob would silently start
shipping them again the moment one was renamed.
Resolution now probes rather than computing one path and hoping. An
installed prefix is tried first, the build tree second, and a candidate
counts only if sanctoral.sexp is actually readable inside it -- so a
failed or half-removed install falls through to a working tree instead
of shadowing it and failing later with a per-file error.
COLITUR_DATA_DIR overrides both and NEVER falls through. This was the one
real design question and the first version got it wrong: it treated the
override as just another candidate, and a deliberately bogus value
produced a full, plausible, entirely un-flagged year computed off the
build tree. Someone who names a directory has stated an intent, and
silently calendaring off a different one is the silent substitution this
project refuses everywhere else. It is now exit 2 naming the directory.
Verified end to end, not inferred: installed to a scratch prefix, then
ran the binary from an unrelated cwd with no build tree near it, and
confirmed 2038-03-06 still resolves Perpetua and Felicitas through the
Common route. All four paths exercised -- build tree, valid override,
bogus override, and an empty share/ falling through.
Environment reads stay confined to bin/. The kernel's contract forbids
them and nothing below the CLI learns where the data came from; the
loaders take a path.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 -> 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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A live-missalemeum sweep over a full liturgical year (2028, 364 days)
returned 333 matching and 31 differing days: 17 already-known or pure
notation, 3 new. All three now adjudicated against the photographic
scans of the 1962 Missal.
The Assumption's Epistle reads "Iudith 13, 22-25; 15, 10" (scan1:35357).
Both engines carried "Judith 13:22-25; 13:15; 13:10" -- a chapter
carry-over defect that re-applied chapter 13 to the second citation and
so invented two verses the Missal never cites. The Seven Sorrows reads
"Iudith 13, 22 et 23-25" (scan1:36938, corroborated at 28468); both
carried "Judith 13:22; 13:25", dropping the range. The third, St Monica,
resolves the other way: the Missal gives 1 Timothy (scan2:32679, heading
and incipit both legible; scan1:29524 agrees) where missalemeum serves
the Common of Holy Women's Proverbs -- colitur is right, no change.
Layer 3 could not have found either citation defect. colitur's data is
bootstrapped from lectio, and lectio is the other side of that
differential, so while both engines produced the identical wrong answer
the comparison held it against itself and reported agreement -- the
shared-lineage blindness CLAUDE.md names, now with a second live witness
beside Holy Thursday's colour. Only an external oracle could see it, and
only outside the committed fixture's own window.
Fixed upstream in lectio, re-bootstrapped here (provenance SHA-256 moved
to 54f6bfc5, verified against the source), fixture regenerated.
The upstream fix inverted layer 3 from blind to load-bearing here:
reverting the Assumption citation now reddens both layers, where before
it would have reddened neither. Verified by mutation, both directions.
Allow-lists:
- C22 closed and removed (128 rows -> 0), not re-adjudicated -- the other
engine was fixed to agree, the same shape as the C2-C5/C7/C9-C13/C21
closures. Its own note had already flagged the Lenten Ember dead-key
bug for upstream; lectio now also fails its build on any unreachable
lectionary key rather than serving a plausible wrong Mass.
- M28 opened (3 rows, verdict colitur), pinning both sides' citation
text rather than the date and diff shape alone, so a different
divergence landing on the same date cannot be swallowed.
- M8's gate widened, expected_rows unchanged at 2: 2027-08-15 carries
both its cause and M28's, and one entry is admitted per day. It stays
under M8, which now requires its own commemoration difference to be
present and admits the citation difference only when it satisfies
M28's two-sided predicate. Neither cause absorbs the other.
layer_m_reason's oracle-row parameter, kept named since M2 closed for
exactly such a future reader, is live again.
Register: docs/research/rules-register.md section 6.6.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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->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->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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Layer 4 (test_oracle.ml) now extracts and compares the Epistle/Gospel
citation for every one of the 730 days in the 2026-2027 fixture, the
same axis Task 8 already added to layer 3. tools/
extract_missalemeum_oracle.py gained a structural citation-span
detector (the first "*...*"-wrapped span under 40 chars containing a
chapter:verse-shaped digit pair), verified exhaustively over all 1 458
Lectio/Evangelium sections. 728 of 730 days are comparable; the 2 that
are not (Good Friday, both years) have no such section in missalemeum's
own JSON at all -- a structural limit on the oracle's own side (M23),
not a colitur gap. 451 of 730 days differ and are all explained across
19 cited entries; 0 unexplained. Chain step 4 (the Commons) has no
layer-4 witness: confirmed empirically (a scratch sweep, not merely
re-asserted from Task 6's own report) that none of the 15 Commons/proper
saints is ever the observed office in this window.
The comparison surfaced three genuine colitur bugs in
data/ef/lectionary.sexp, all fixed at the source in
tools/bootstrap_lectionary.ml:
1. Holy Name of Jesus (ef-holy-name-sunday/ef-holy-name) carried a
mis-derived citation, borrowed by analogy from an unrelated ini
section ("ef-christmas-sunday-0", the Sunday-within-the-Octave's own
Mass) on the wrong assumption the two share a Mass. Disproved by
missalemeum's own extraction for both real Holy Name Sundays in its
window, confirmed against the Missal itself, twice, both scans
(Acts 4:8-12/Luke 2:21, not Gal 4:1-7/Luke 2:33-40).
2. RG 17(a)'s own "diebus ferialibus" rubric (immediately following the
Holy Name heading, both scans) was never implemented: 2-5 January
ferias repeat 1 January's Mass, 7-12 January ferias before Holy
Family Sunday repeat Epiphany's, and Holy Family's own week has a
named formula ("Missa Dominicae Primae post Epiphaniam"). All three
fell to step 3's undifferentiated Sunday walkback instead. Fixed for
three 5-weekday families, deliberately excluding Saturday from all
three -- RG 78's BVM Saturday Office wins there unconditionally,
confirmed against missalemeum's own title on this window's own such
Saturdays.
3. Corpus Christi and Sacred Heart (both real, never-impeded I-class
movable feasts) had no lectionary entry at all. Both engines
independently fell back to Trinity Sunday's own citation and
silently agreed on the wrong answer -- the "Holy Thursday violet in
both" shape CLAUDE.md names for exactly this reason.
Because lectionary.sexp is shared with layer 3 (the lectio differential,
2005-2050), these fixes changed colitur's output for the whole domain,
not only 2026-2027. data/ef/expected-divergences.sexp and
test_differential.ml needed matching updates: C1 narrowed 361->173 and
C25 narrowed 57->13 (rows that now resolve correctly moved to new
entries), C16's note corrected (count unchanged), and six new entries
added (C29-C34, 397 rows total, all verdict colitur). test_lectionary.ml
and test_lectionary_ef.ml's own pins were updated to match (entry count
131->148; one step-3 regression test re-pointed to a date that still
genuinely exercises that step).
One entry, M26 (30 rows, verdict open), is a genuine unfixed gap: colitur's
step-3 "resume the preceding Sunday" fallback is its only ferial-Mass
mechanism, and missalemeum's own selection is more granular in three
confirmed ways (a rotating votive Mass of the BVM, a named weekly
formula for at least one week, and later Time-after-Pentecost weeks this
task's own investigation did not narrow to a single rule) -- the same
"needs a season-keyed selection mechanism, new behaviour not new data"
shape data/ef/expected-divergences.sexp's own C6/C25 and Task 6's own
residual concern already name, out of this task's own scope to build.
dune test: 358 tests green. COLITUR_EXHAUSTIVE_SWEEP=1 dune test
--force: 359 tests green, 89.5s.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two Ember Saturdays shipped an apostle's Mass verbatim from lectio's
own ini, the exact shape already found and fixed for Passion Tuesday
(C26): ef-advent-ember-sat carried St Thomas the Apostle's Mass (Eph
2:19-22 / John 20:24-29, 21 December) instead of the real "Sabbato
Quatuor Temporum Adventus" (2 Thess 2:1-8 / Luke 3:1-6); ef-september-
ember-sat carried St Matthew's Mass (Ezek 1:10-14 / Matt 9:9-13, 21
September) instead of the real "Sabbato Quatuor Temporum septembris"
(Heb 9:2-12 / Luke 13:6-17). Both verified against both primary-source
scans independently. Both readings are explicitly labelled "Lectio
Epistolae" in the Missal on both days, so neither needed the "last
lesson before the Gospel" convention Holy Wednesday/Good Friday relied
on -- a textual fact, not an editorial choice.
Fixed at the source in tools/bootstrap_lectionary.ml: colitur_keys
excludes both wrong ini sections; a new ember_saturday_corrections list
hand-authors the real citations. New allow-list entries C27/C28 (40
rows each, not the naive 46 -- traced to the identical 6 civil years
where 21 September and 21 December, always exactly 91 days apart, land
on a Saturday and the fixed saint's feast wins outright). Both values
pinned in test_lectionary.ml and mutation-tested.
Also: C25's per-weekday breakdown was mislabelled (right multiset,
rotated weekday labels) in both test_differential.ml and expected-
divergences.sexp -- corrected to Wednesday 6/Thursday 19/Friday
19/Saturday 13, and the claim that this split came directly from the
comparator's own output is narrowed to what's actually true (only the
total, 57, does). C26's scan2 citation range was extended to include
the Gospel (previously stopped after the Epistle).
lib/kernel/liturgical_day.mli's "citations always empty until Plan 4"
comment is now stale on this branch -- left untouched (Task 11's own
documentation pass), noted in the task report so it isn't lost.
dune test: 358 tests green; COLITUR_EXHAUSTIVE_SWEEP=1: 359 green.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Critical, and worse than what it replaced: removing a lectionary key does
not mean "no reading" to Lectionary_ef.readings -- it means step 3 silently
resumes the preceding Sunday. Good Friday, which has no Mass at all, was
emitting Palm Sunday's own Epistle and Passion narrative every year; Holy
Wednesday had the same defect. Fixed by authoring both days fully: the
Gospel was always unambiguous and is now always authored; the Epistle uses
the same "last lesson before the Gospel" convention this file's own Lenten
Ember Wednesday entry already established for an identical two-peer-lesson
shape, applied for consistency rather than invented to close this gap. C24
is retired, folded into a widened C23 covering all six Holy Week days.
Important: Passion Tuesday was shipping Holy Tuesday's Mass, a defect the
previous round's own footnote had found and left unrecorded. Fixed at the
source -- colitur_keys now excludes lectio's own (wrong) ini section for
this one weekday rather than translating it; a new passion_tuesday_entry
hand-authors the real Missal citation (Dan 14:27, 28-42 / John 7:1-13, both
scans). New entry C26 records the resulting divergence, 43 of 46 years,
traced (not merely counted) to three years where a competing I-class feast
impedes the day entirely.
Important: the allow-list header was stale one level up, still naming and
restating the diagnosis of an id (C21) retired in the previous round.
Rewritten in full rather than layered with another correction.
Minors: all three Lent Ember values now pinned (only Wednesday was before);
C22's citation corrected to attribute the date-anchor text and the rank
text to their own separate sources; assert_reachable's own comment no
longer overclaims what it can catch; C25's falsified reasoning replaced
with the directly observed fact (a first replacement derivation was itself
found wrong on a second reading and is recorded as rejected, not silently
discarded); hand-authored citations standardised to English book names
with a colon, matching this file's own dominant convention, with one
stated exception where a value must stay byte-identical to lectio's own
data rather than be reformatted.
dune test: 358/358. COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force: 359/359.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two Critical findings, both real: Holy Week (including the entire Sacred
Triduum) was reading Passion Week's Masses -- the original colitur_keys
widened lectio's single, conflated ini section into both weeks instead of
Passion week alone. Narrowed to Passion week only; Holy Week's own four
cleanest days (Monday, Tuesday, Thursday, Saturday) are hand-authored
directly from the Missal, verified twice against both scans (C23); Holy
Wednesday and Good Friday are genuinely multi-lesson liturgies with no
single Epistle slot and are deliberately left unanswered, not guessed (C24).
The Lenten Ember days were still dead keys: Temporal_ef computes
ef-lent-ember-{wed,fri,sat}, lectio's ini names the same data
ef-lent-1-{wednesday,friday,saturday}, and colitur_keys never translated
it -- both engines independently fell through to the same wrong ferial
answer, so even the differential stayed green (C22, a genuine lectio bug
recorded for upstream). Fixed the instance and the class: colitur_keys
gained the rename, and tools/bootstrap_lectionary.ml gained
assert_reachable, sweeping Rite_ef.Temporal_ef.temporal at generation time
so a translation table entry naming a slug colitur never computes dies
loudly instead of shipping silently, plus an informational log of every
real slug with no entry at all.
C21 ("colitur's step 3 cannot reach a correct answer for the fixed
Christmastide slugs") is retired, superseded rather than merely patched:
the Nativity-Octave days now have their own direct Missal formulary
(Tit. 3,4-7/Luc. 2,15-20, "Diebus infra octavam Nativitatis Domini"),
resolved at step 2, not step 3 at all. That surfaced a real RG 69 gap
underneath it: a Sunday landing 26-31 December should keep its own Office,
not the fixed weekday placeholder, which Temporal_ef does not currently
distinguish. C6's verdict is re-opened (open, not colitur) for the 19 of
its 138 rows where this applies directly, and a new entry C25 (57 rows)
records the same gap propagating one hop further through step 3 into Holy
Name week. Both are out of this task's own scope -- a behaviour change to
a shared, multi-round-reviewed kernel-adjacent function -- and recorded,
not fixed, per the coordinator's own instruction.
C6's own note is rewritten in full rather than layered with another
correction; C18's stale trailing count is fixed to match its own pin; the
Vigil-misapplication risk flagged as a Minor closed itself once the
Nativity-Octave fix landed, confirmed by inspection rather than assumed.
dune test: 358/358. COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force: 359/359.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Layer 3 is NOT blind to the ferial resumption rule, unusually for this
project: lectio implements the same rubric independently, so the differential
checks colitur's rule against a second implementation rather than against
silence.
It IS blind to the Commons -- lectio has no such concept -- so chain step 4
rests on layer 4 alone.
Divergence triage, 1 532 of 16 801 days differ (15 269 match exactly),
0 unexplained:
- A genuine colitur bug found and fixed: data/ef/lectionary.sexp carried
lectio's own ini section names verbatim, never translated into the slugs
Temporal_ef actually computes for the identical office. Data the bootstrap
already held (Passiontide both weeks, the Pentecost Ember days, Holy Name
Sunday) was unreachable by chain step 2, silently falling through to a
wrong step-3 answer -- invisible until citation content became comparable.
tools/bootstrap_lectionary.ml gained colitur_keys (rename/widen), a
hand-authored ef-nativity-vigil entry cross-sourced from lectio's own
sanctoral calendar and corroborated by colitur's own (overlay-suppressed)
sanctoral bootstrap of the same source, and a derived ef-holy-name entry
(RG 17(a)'s single Mass heading covers both the Sunday and 2-January
shapes). One guess (giving the fixed Nativity-Octave days Holy Name
Sunday's own citation uniformly) was tried and reverted once measured
against the fixture -- Missal-verified to be right only for the genuine
"Sunday within the Octave" case, wrong whenever the true preceding Sunday
is Christmas Day or Advent IV instead.
- 10 existing/widened Layer C entries (C1/C6/C8/C14/C15/C16/C17/C18 --
C6 and C17 narrowed with the removed population accounted for, not
silently re-absorbed) plus two new ones: C19 (the already-adjudicated
Time-after-Epiphany week-numbering offset, now visible in citation
content), C20 (lectio computes no reading at all for the seven
readingless saints Task 6 gave a Common or proper -- colitur is more
complete, not wrong).
- One entry, C21, is a genuine colitur LOGIC limitation found but not
fixed: Lectionary_ef.readings' step 3 is a single hop to the preceding
Sunday, insufficient for a run of colitur-only fixed Christmastide slugs
whose own preceding Sunday is itself another entry-less fixed slug.
Recorded verdict open (data/ef/expected-divergences-missalemeum.sexp's
own established precedent for this shape), not left silently failing --
fully diagnosed in task-8-report.md, recommended as a dedicated
follow-up task rather than a hasty fix to a shared, multi-round-reviewed
kernel-adjacent function.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Review re-verified all fifteen saints and all seven formularies against both
printings and found zero citation discrepancies, confirming the Gabriel
printing error and all three proper/Common reversals; the reordering was
adjudicated sound. Two Important findings, both about the guard rather than
the data.
IMPORTANT 1 -- the guard had no test, and a comment claimed it did.
`test_step4_never_diverts_a_temporal_office` asserted 2026-07-04 keeps its
ferial Mass and its comment claimed to "pin it behaviourally". It did not:
no shipped assignment names a temporal slug, so the guard is a NO-OP on
shipped data and that test passes with the guard removed. The reviewer
proved it by forcing `sanctoral_office = true` -- all 357 tests stayed
green. That mattered more than an ordinary missing test: the guard is the
structural claim the whole reordering argument leans on, and on a task with
no oracle the tests are the entire safety net.
Fixed by exposing `Commons.of_tables` (already present internally; it
applies exactly `load`'s validation, so a synthetic table is a well-formed
table with a WRONG assignment rather than malformed data the loader would
reject before the guard is reached -- and it is the constructor a future
diocesan overlay needs anyway), adding `day_with ~commons` beside `day`, and
writing test_step4_guard_refuses_a_common_assigned_to_a_ferial_slug: a
synthetic Commons assigning the Common of Abbots to
`ef-time-after-pentecost-5-saturday`, a really-observed ferial slug,
asserting 2026-07-04 still says its ferial Mass. Two checks, the first
making the second mean something -- it asserts the hostile assignment IS
present and resolvable, so the ferial Mass wins because the GUARD refused it
and not because the lookup missed. Mutation-verified: with the guard
disabled exactly one test fails, this one; before this round that mutation
reddened nothing. The old test is renamed
test_step4_leaves_a_temporal_office_alone_on_shipped_data and its comment
corrected to say it does not pin the guard.
IMPORTANT 2 -- the guard cited an authority that does not say what was
claimed. The comment said "[Validate] already asserts slug uniqueness per
liturgical year, so a sanctoral feast can never collide with a temporal
slug". validate.ml's check maps over `Temporal.office` slugs ONLY, compared
to each other across the days of one year; it says nothing about
cross-stream collision. An assumption was promoted to an asserted invariant
-- the exact defect class this project's citation discipline exists to
catch. Rewritten to state it as an assumption (no sanctoral slug carries the
`ef-` prefix every temporal slug does; 0 of 327 today), to quote the real
authority verbatim (validate.ml's own note that this "is the same assumption
the rest of this codebase already leans on"), to carry a CORRECTED marker
naming the wrong citation so it is not re-derived, and to record the failure
mode if it ever broke: benign and one-directional -- a colliding saint is
denied his Common and falls through to steps 2/3, i.e. to exactly the answer
the unguarded chain would have given him. No day gains a reading it should
not have.
MINOR -- the previous commit body led with "Blast radius, measured ... ZERO
differing lines", which is true but oversold: the CLI prints no citations, so
that sweep is STRUCTURALLY INCAPABLE of observing the reorder or any citation
value. It is a valid negative control for the sanctoral `Edit` overlay and
nothing else. The evidence for the reorder is mutation 1 (relegating step 4
to last reddens exactly the four step-4 pins) plus those pins' own explicit
expected values -- not the sweep. Correcting the record here.
MINOR -- test_commons_load_rejects_bad_data wrote four FIXED-name files into
the temp dir and removed none, colliding across concurrent runs. Replaced
with a local `with_temp_file` copied from test_lectionary.ml's own
(`Filename.temp_file` + `Fun.protect ~finally`); the four labels moved into
the assertion messages where they belonged. Verified zero leftovers after a
full run.
MINOR -- added the sharper argument for the reorder, which makes the
deviation obviously right rather than merely well-evidenced, and it now LEADS
the branch comment as warrant (1), with the Missal citation demoted to a
corroborating warrant (2): step 4 is STEP 1'S CONTINUATION. Step 1 already
runs the observed office's own proper ahead of steps 2 and 3; step 4 is that
same rule for the saints whose readings the Missal keeps in a Common instead
of printing on the celebration. Placing it last would have made the chain
internally inconsistent with code that already existed -- St Joseph beating a
competing temporal entry because his readings sit on his Celebration.t, and
St Vincent Ferrer losing to one because his sit one indirection away. Nothing
in the rubrics draws that distinction; it is an artefact of where colitur
stores the data. So the plan's ordering did not merely disagree with the
data, it contradicted step 1.
358 tests green (357 before), 359 with the exhaustive sweep.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ba0adba's own wrong commit body
Three Important findings, all traceable to the task-5 brief rather than
the implementation itself; all confirmed against the real data and the
real resolver before fixing, not taken on trust.
1. test_step3_uses_temporal_not_observed (2028-12-26) did not exercise
step 3 at all: 26 December is always Stephen, a real sanctoral entry
with its own citations, so that date resolves entirely at step 1.
Its justifying comment was also wrong -- 24 December's TEMPORAL slug
is ef-nativity-vigil, IDENTICAL to its observed slug (Temporal_ef.named
hard-codes the Vigil for that date ahead of any Sunday computation),
so there was never a temporal/observed split on that date to exploit.
Replaced with 2025-02-03: 2 February 2025 (Sunday) is observed as the
Purification (own citations Mal 3:1-4 / Luke 2:22-32) but its TEMPORAL
identity is ef-time-after-epiphany-sunday-4 (Rom 13:8-10 / Matt
8:23-27, a different lectionary entry); 3 February has no proper of
its own and reaches step 3, which must return the Sunday's TEMPORAL
reading, not the Purification's. Verified against
data/ef/sanctoral.sexp and data/ef/lectionary.sexp directly.
2. The termination-argument comment in lectionary_ef.ml (and its echo in
lectionary_ef.mli) claimed an unguarded Sunday would loop. It would
not: readings is not recursive -- step 3's fallback is one flat
Lectionary.find, never a re-entrant call into readings -- so an
unguarded Sunday would just repeat step 2's own already-failed lookup
once (same pure inputs, same None) and return [] normally. Rewritten
to say what is actually true: the guard exists because a Sunday has
no PRECEDING Sunday to resume, not because skipping it would be
dangerous; the chain terminates because every step consults data or a
strictly earlier date, and no step ever calls back into readings.
3. Correcting the record, per instruction, rather than amending
ba0adba: that commit's own body said Advent ferias carry 'Advent I's
own readings copied onto the following Monday-Thursday'. Both details
are wrong, verified directly against data/ef/lectionary.sexp: the
duplicated readings are ef-advent-SUNDAY-2's (Rom 15:4-13 / Matt
11:2-10), not Advent I's, and they appear on ef-advent-2-monday,
-tuesday, -thursday and -saturday -- four non-contiguous days, not a
Monday-to-Thursday span. The in-code comment and the task-5 brief's
own commit template both already said 'Advent II' correctly; only
ba0adba's commit body had the error.
dune test --force: 344 tests, all green (unchanged count -- one test's
body changed, none added or removed).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Chain step 3. Guarded on weekday <> Sun: a Sunday reaching this branch
would look up its own slug via days_since_sunday Sun = 0 and loop --
every other chain step consults data, this one consults a strictly
earlier date, so that guard is the whole chain's termination argument.
Reaches the Sunday by Date.add_days plus a fresh temporal_at call, never
by string surgery on the day's own slug -- the slug shapes are genuinely
inconsistent across seasons (ef-advent-sunday-1 vs ef-advent-1-monday,
week number on opposite sides of the season name).
Uses the preceding Sunday's TEMPORAL slug, never its observed one: the
rubric is the preceding Sunday's Mass even in a year a feast displaced
that Sunday from being observed (pinned: 2028-12-26, the Monday after a
Vigil-displaced Advent IV Sunday, still takes Advent IV's Mass).
Measured over the full 1583-9999 domain (temporal cycle only, no
sanctoral contest): of 412 distinct temporal slugs, 305 carry no
lectionary entry of their own; of the 304 that are feria (non-Sunday)
slugs, step 3 alone resolves 297 of them via their preceding Sunday.
The 7 that remain, plus the 1 uncovered Sunday slug itself
(ef-holy-name-sunday), all trace to the same two missing lectionary
entries (Holy Name Sunday and 30 December), not to eight independent
gaps or a step-3 defect -- traced date-by-date, not merely counted.
Day-level effect, 2005-2050 (full Precedence+Calendar pipeline,
matching this project's existing differential window): 16807 days,
16531 resolved (98.36%), 276 still empty; step 3 alone accounts for
4503 of the resolved days, more than either step 1 or step 2.
Warrant is the same class as step 2's, not a confirmed Missal
citation: lectio hard-codes this shape as literal duplicated data on
the four Advent ferias (Advent I's own readings copied onto the
following Monday-Thursday) and leaves the rest of that same shape
simply absent; step 3 turns the duplication into a rule.
dune test --force: 344 tests, all green (was 340).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Liturgical_day.citations has read "always empty until Plan 4" since Plan 3;
it is now filled. Rite.t gains a readings function, rite-supplied for the
same reason transfer_target is: what a day with no proper falls back to is a
rubric, not a universal. Calendar calls it and passes its own temporal
function as the callback the rite needs to reach another date.
Steps 1 and 2 only: the observed celebration's own proper, else the day's own
temporal slug. Nothing encodes "Lent has daily propers" -- the presence of an
entry is the discriminator.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Celebration.citations has existed in the type, the .mli and the sexp schema
since Plan 2 and has been emitted as () for every entry; the bootstrap now
writes the real values for the 208 entries lectio has them for.
On the celebration rather than in the lectionary table deliberately: a
diocesan overlay adding a saint then carries his readings through the
existing overlay algebra, with no second file to edit and no new directive.
Asserted both ways -- the 13 January proper is present, and no
Commemoration_only entry has readings, because in the EF a commemoration
contributes an oration, not a reading.
|
| |
|
|
|
|
|
| |
119 entries, Epistle + Gospel only. The generator refuses a section carrying
exactly one of the two: an Epistle without a Gospel is malformed and wants
investigating, not shipping. SHA-256 of the source INI is in the provenance
header, as with sanctoral.sexp.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Sexplib.Sexp.load_sexp raises bare Failure for several malformed inputs
(unterminated list/string, empty file, more than one sexp) rather than
Sexplib.Sexp.Parse_error, so those cases escaped Lectionary.load as an
uncaught exception -- breaking the .mli's own promise and the kernel's
never-raises-on-fallible-construction constraint. Mirrors the catch-all
already present in Layer.load and Overlay.load, plus a second catch-all
on the t_of_sexp branch for defence in depth.
Adds test_load_never_raises, covering all of the above plus a missing
file, using Filename.temp_file rather than a hardcoded path. Verified the
new test fails against the pre-fix load (uncaught Failure) and passes
against the fix.
|
| |
|
|
|
|
|
| |
Data only, the same shape and discipline as Layer: slug-canonical,
duplicates rejected at construction naming the offending slug, sexp
round-trips. Which slug a day falls back to is a rubric and belongs to the
rite module, so nothing here knows about ferias or Sundays.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
M21 accepted `subset diffs [Colour_f; Comm_identity_unresolved]`, so a row
with no colour diff at all could be absorbed under a colour citation. The
unresolved allowance existed only for the 22 February rows the previous
commit reverted; with those gone the predicate tightens to exact equality
on Colour_f, matching C18's shape, and stays green.
Records two things the audit's bucket summary did not carry. The effective
dataset is 329, not 328: base 327 plus three overlay Adds minus one
Suppress, so commemoration-of-st-peter and major-litanies fall outside
both buckets despite being in the stated scope, and a suppressed entry is
counted as verified. And the summary says colour was "independently
checked against RG 124" for every entry where much of it is inferred from
the saint's category rather than read -- the per-entry basis column makes
that distinction and the summary line erases it.
Also records that "zero blast radius" holds only for the observed office:
49766 commemoration-colour changes on 8 slugs are real data changes,
invisible because the CLI omits commemoration colour.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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->450
from the observed-day counts, M21 20->18, M15 17->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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(fix round 1, F1)
The prior fix (settled_at) recognised two settlement channels for a
transferred candidate at its target -- winning outright (observed) or
surviving as a commemoration -- but missed a third: reaching the target
and then being CAPPED OUT there, by admit's own RG-111-style admission
count limit or by disposition's own Omit. That candidate lands in the
target's own omitted list, genuinely settled and accurately labelled, but
settled_at did not check that list, so the origin reported it as
unresolved under the same wrong, hardcoded unconverged_reason -- the exact
original bug, one level further out.
Unreachable on shipped EF data (the Major Litanies are the only privileged
Commemoration_only candidate real data carries, and no second one can ever
share Easter+2), but reachable by construction: a second privileged
Commemoration_only entry on the Litanies' own transfer target that
outranks it in admit's Class1 selection, or -- without any synthetic data
-- forcing the Litanies' own RG 109(f) privilege to Ordinary, which makes
the transferred candidate lose that same cap against its own real target.
Fixed by adding target-omitted membership as a third disjunct in
settled_at. New regression test in test_calendar.ml, built the same way:
the real EF layer plus one synthetic privileged Commemoration_only entry
on the real 2011 transfer target, sorting ahead of the Litanies so it wins
the Class1 slot. Mutation-verified to fail specifically when the third
disjunct is removed. COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force stays
clean after the fix, confirming it changes no shipped day's output.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
correction
M5 (the pre-existing register-cited gap this task closes) had a genuine
backwards claim in its own note: it said missalemeum's single admitted
commemoration on 25 April 2027 (the Sunday-conflict year) was "the Major
Litanies". Checked directly against the raw fixture row while adjudicating
this task's own new divergence -- missalemeum's own commemorations field
there is "St. Mark"; "Pro rogationibus" (the Litanies) is the one listed
as displaced. Corrected in place, both the .sexp entry and this file's own
header note. M5 itself now covers only the ordinary case (25 April 2026):
presence agrees now that the entity is built, identity does not (colitur's
own English name vs missalemeum's Latin-ish descriptive string), the same
declared comparator limit M15/M18 already document, hit here for a
different reason.
The real, substantive divergence the correction exposes: colitur now
admits the Litanies on 2027-04-25 where missalemeum admits Mark. New entry
M20, adjudicated colitur -- RG 109(f) places the Litanies in the same
closed privileged list as (a)-(e), and RG 111(b)'s own text is
unconditional ("the II-class commemoration is dropped if a privileged one
is due", no table-order qualifier). The same mechanism already
primary-source-verified and used for other RG 109 categories elsewhere in
this codebase; honestly flagged as the first real, non-synthetic test of
this specific admit clause, consistent with this oracle's own
already-documented pattern of RG 108-111 gaps (M1, M8, M10).
M18's own count moves 395 -> 394 (2027-04-25 no longer falls into "observed-
identity-unresolved alone"; it moved into M20), traced to the specific date
and mechanism, not merely re-baselined.
data/ef/expected-divergences.sexp (the lectio allow-list) needed no
change: lectio computes no Major Litanies at all, and its own row type
carries no commemorations field -- layer 3 is entirely blind to this
change, confirmed rather than assumed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The BVM Saturday Office is itself "de B. Maria Virg."; RG 112(d) (Caput
XVI, "De Commemorationibus") excludes another commemoration whose own
oration invokes the SAME BVM's intercession. our-lady-of-mt-carmel (16
July, Commemoration_only) was wrongly admitted as an ordinary
commemoration alongside the Office on every 16-July-Saturday -- its own
collect explicitly invokes "her" (eius) patronage, and both photographic
scans print a rubric anticipating exactly this collision (an either/or
of Mass texts, not a joint commemoration).
Precedence_ef gains marian_slugs (a closed, hand-verified list of
sanctoral slugs that are themselves feasts of the BVM) and is_bvm_office
(true for subject = Bvm OR a marian_slugs member -- the disjunction is
load-bearing: the Office is identified only by subject, since its own
slug is deliberately reused from the ordinary ferial fallback; Mt Carmel
is identified only by the list, since its own subject tag is Saint, not
Bvm). disposition gains a new branch, checked before the pre-existing
Commemoration_only catch-all, since the one live witness is
Commemoration_only and that branch's own "always Commemorate" had no
exception for this shape.
Checked exhaustively against every Marian-named sanctoral entry: only
Commemoration_only-status entries can ever reach this branch live (a
Feast-status one always wins outright instead of losing). Of the two
such entries in the data, only Mt Carmel is reachable --
our-lady-of-ransom (24 September) is provably unreachable: 24 September
falling on a Saturday forces 1 September to a Thursday, which by
construction makes 24 September the September Ember Saturday, Class2,
every time, not a sampled coincidence.
Re-measured against the full pre-change binary: the original 75,853-day
blast radius is unchanged in total, splitting into 74,633 colour-only +
1,220 colour+comms (16-July Saturdays). Mutation-tested: exactly 3 new
tests redden, nothing else.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The BVM Saturday office is now genuinely correct, so both comparators'
allow-lists move -- every count derived from the harnesses' own failure
output, never transcribed or guessed.
lectio differential (data/ef/expected-divergences.sexp, C17, new,
colitur): lectio builds no equivalent office at all, so it keeps
showing the plain season colour on every otherwise-unoccupied Class4
Saturday where colitur now shows white. Season, slug and rank all still
agree (the office deliberately reuses the ordinary ferial slug), so
Colour_f alone is the complete diff set -- gated on colitur's own
rank/weekday/colour rather than a date list, the same shape M2 used, at
416 rows over 2005-2050.
missalemeum oracle (data/ef/expected-divergences-missalemeum.sexp): M2
is CLOSED, REMOVED, the same shape as this file's own M4/M6/M7/M9/M12/
M14/M17 precedents -- not re-adjudicated to a different verdict, gone
because the colour divergence it named no longer occurs on any of its
former 22 dates. What is left on all 22 is Observed_identity_unresolved
alone (colitur's BVM-Saturday candidate is temporal-origin and
deliberately carries no English name) -- exactly M18's own shape, not a
distinct citation any more. Keeping M2 as a separate id would have kept
silently absorbing these rows under a stale "colour differs" citation
whose own reason had stopped firing (subset's own diff-set test admits
a SMALLER set than the one named) -- the same "count proving cardinality
where identity was required" trap this project's review process
watches for. M18's own expected_rows moves 373 -> 395 accordingly.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Entry 27's band branch has been unreachable for the right reason since
it was written: precedence_ef.ml's own comment on it acknowledged the
row existed, but the one test exercising it built a hand-typed
candidate, never a real Temporal_ef.temporal output, and nothing built
the office itself. Closes that gap on both sides:
- The band-table row now sources its candidate from Temporal_ef.temporal
directly (of_temporal), the same review-finding-3 discipline the
Ember/vigil rows already use, so a future regression in the office's
own construction fails this row too, not only the unit-level test.
- Two new resolve-level end-to-end tests, using the real band/
disposition/admit triple (not stubs): the office winning a real
otherwise-unoccupied Saturday and admitting an ordinary commemoration
alongside it (1 August 2026, Holy Machabees -- the task brief's own
worked oracle example), and the office genuinely losing to a real
competing feast and being omitted under RG 26, with no confusion from
the one live data witness that also carries subject Bvm (12 September,
Most Holy Name of Mary) -- proving RG 26's rank-keyed omission fires
before any subject-keyed rule ever could.
- Two golden pins mirroring the same two dates, checked by hand against
`colitur day 2026` before being typed in, following this file's own
"a golden test blesses whatever it is given, verified independently"
discipline. The existing 2038-03-06 pin (RG 91 entry 24 outranking a
Class4 candidate) is corrected in passing: that date is itself a
Saturday, so the displaced candidate the pin's own omitted-list check
names is now precisely entry 27's own shape, not entry 28's bare
catch-all -- the win/lose outcome the pin proves is unchanged, only
its own more precise citation.
Mutation-tested (recorded in the task report): reverting
is_bvm_saturday to a constant false reddens the dedicated unit test, the
new end-to-end resolve test, and the 2026-08-01 golden pin, while
leaving the 2026-09-12 "loses to a real feast" pin untouched, exactly as
expected since that date's outcome never depended on the fix.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 91 entry 27, "Officium sanctae Mariae in sabbato", sits in the Table
of Precedence between entry 26 (III-class vigils) and entry 28 (IV-class
ferias). Precedence_ef.band already routed a plain IV-class Saturday
feria to entry 27's own band value, but nothing in Temporal_ef.temporal
ever constructed the office itself, so an otherwise-unoccupied Saturday
still surfaced with a bare ferial slug and its season's ordinary colour.
Established from Caput IX of the Rubricae Generales, both photographic
scans and the electronic transcription, word for word (no
scan-vs-transcription conflict: RG 78/79 are General Rubrics prose, not
the Mass-propers body text the transcription is documented elsewhere as
missing almost all of):
"78. In sabbatis, in quibus occurrit Officium de feria IV classis, fit
de sancta Maria in sabbato.
79. Officium sanctae Mariae in sabbato incipit a Matutino et explicit
post Nonam."
RG 78's own protasis IS "otherwise unoccupied IV-class Saturday" --
every Saturday whose temporal candidate would otherwise be Class4,
across every season that rank reaches (Christmastide, Septuagesima,
Time after Epiphany, Time after Pentecost, ordinary Paschaltide).
Nothing else was needed to decide "otherwise unoccupied": band's own
entry-27 branch already reads rank/weekday on the temporal candidate
unconditionally and only wins the day when nothing outranks it -- RG
78's own condition, decided by the existing occurrence machinery.
Colour is white, unconditionally, per RG 120(b) ("Adhibetur color albus
in Officio et Missa de festis: ... b) B. Mariae Virg."), not RG 119/127/
128's seasonal rules -- this office is never "de Tempore" for colour
purposes, so it overrides the season's own violet/green.
The slug is deliberately left UNCHANGED (reused from whatever the
generic <season>-<week>-<weekday> ferial fallback would already have
produced), for two independent reasons: it matches the Sacred Triduum's
own precedent (identified structurally, off rank/weekday, never off the
slug), and a bespoke uniform slug would have broken
Colitur_kernel.Validate's own slug-uniqueness-per-liturgical-year
invariant, sighted zero times before this task -- confirmed directly by
writing it that way first and watching the landmark-years test fail.
Subject is tagged Bvm (currently inert for precedence -- only Lord is
ever read by band/disposition/admit) and the name is the Latin
"Officium sanctae Mariae in sabbato" (RG 91 entry 27's own table title
and RG 79's own heading), deliberately not English, the same
zero-circularity discipline Holy Family/Holy Name/the Sacred Triduum
already established.
The I-V numbered "Missae de sancta Maria in sabbato" (both scans) are a
Mass-propers selection detail (RG 309(a): "iuxta temporum diversitatem")
governing which readings/texts are said, not which office is kept --
colitur computes no citations yet (Plan 4), so this is deliberately not
modelled here.
Two pre-existing tests needed correction, not because they were wrong
before, but because RG 78 genuinely changes their dates' own facts: a
Saturday inside the Holy Name of Jesus window (3 January) and two
Saturdays inside christmastide_feria_slug's own "-0-"/"-2-" stretches
(26 December, 10 January) are all otherwise-unoccupied Class4 Saturdays,
so they now legitimately carry the BVM office instead of staying a bare
Temporal-subject feria.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Holy Thursday, Good Friday and Holy Saturday resolved to the generic
Passiontide ferial slugs with no distinct identity of their own -- rank
and colour were already correct (RG 91 entry 2; Holy Thursday's white
per RG 128(b)/RG 122), only Celebration.names/subject were missing.
Keeps the slug (RG 91 entry 2 is identified structurally, off rank and
Easter offset, by Precedence_ef.band -- never off the slug -- so
renaming it would touch precedence for no reason and break the lectio
differential's own slug mapping for these three lectionary keys, the
same reasoning already given for Holy Family/Holy Name). Carries the
identity in Celebration.names instead, the same treatment those two
established: Latin, not English, to avoid reading the oracle this axis
is compared against.
Names sourced from both photographic scans, word for word, corroborated
by the electronic transcription's own table-of-contents-style listing at
the identical three headings (three-way agreement, nothing to
adjudicate): "Feria V in Cena Domini" (Holy Thursday), "Feria VI in
Passione et Morte Domini" (Good Friday -- not the transcription's own
informal "Feria VI Parasceve" used in passing elsewhere), "Sabbato
Sancto" (Holy Saturday).
Also tags subject = Lord, going further than Holy Family/Holy Name
strictly required (they needed it only because band's entry 14 reads
subject to outrank a colliding fixed feast; entry 2 here needs no such
thing). Safe: disposition's RG 112(a) branch only fires when both sides
of an occurrence are tagged Lord, and no Lord-subject sanctoral entry
has a fixed civil date inside Holy Week's own movable range; any Class1
sanctoral entry landing there (e.g. a transferred Annunciation) reaches
disposition's earlier, subject-blind Transfer branch first regardless.
Verified against the full 1583-9999 domain: zero
observed/commemorations/transferred_* difference traceable to the tag.
test_golden.ml's describe gains a name_la field alongside subject, for
the same reason subject was added: a names-only change is otherwise
invisible to every pin whose rank/colour/slug are already correct (this
task's own catalogued vacuity flavour #1). Six existing pins move from
subject=temporal to subject=lord (the three Easter-extreme Holy Saturday
pins, 2016's Good Friday, and the 2026 Holy Thursday/Good Friday pair);
the rest gain name_la=- by construction (no other temporal-cycle
candidate carries a name yet).
Mutation-tested: reverting temporal_ef.ml alone (keeping the tests)
reddens the new Rite_ef unit test plus five golden pins across two
independent layers.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The re-review asked for a third commemoration in the shape-(c) row, so
that "spliced immediately after its trigger" could be told apart from
"appended at the end" -- it had proved an append-at-end variant passed
the whole suite green, the pair alone being too short to distinguish
them.
Attempting it establishes something better than the test requested. On
this day-shape a third commemoration is rubrically impossible. Shape (c)
requires the trigger to lose the day while still being admitted, and a
Class2 trigger can only lose to a I-class day (RG 111(a): one privileged
commemoration) or a II-class Sunday (RG 111(b): one, "scilicet de festo
II classis"). Both caps are one. The third candidate is now offered and
correctly refused, which is the assertion worth having.
So RG 110(c)'s "ante omnes alias commemorationes" half has no reachable
witness in the EF's rubrical space, and the re-review's own finding that
shape (c) never co-occurs with a third commemoration across 8417 years
is a consequence of the rubric rather than an accident of the data. The
append-at-end variant stays indistinguishable from the splice on every
input the engine can construct. Recorded rather than papered over with a
synthetic row proving a shape no rubric permits.
Also drops Record from the "nothing compares commemoration order" note
-- Record.t has no commemorations field at all -- and names, at
privilege_of's own (a) branch, that the Holy Name's Sunday privilege
currently rests on a substring match rather than on RG 17's closing
paragraph, which is its real warrant.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 110(c), word for word: "quoties vero oratio unius Apostoli addenda
est ad modum commemorationis, huic orationi additur altera immediate,
ante omnes alias commemorationes." "Huic orationi" (dative, "to this
oration") refers to the trigger's own oration; "additur altera" means
the companion is added to it, i.e. follows it. "Ante omnes alias
commemorationes" governs the pair's position relative to other,
unrelated commemorations, not the pair's own internal order. The
previous build prepended the companion uniformly in both RG 110
shapes, citing this same clause for both -- correct for (a)/(b) (the
day's own oration, not a list member, has nothing to order against),
backwards for (c), where the trigger is itself a list member and the
companion belongs after it. Fixed in rg110_additions: shape (a)/(b)
still prepends; shape (c) now splices the companion in immediately
after its own trigger. Re-pinned the unit test that had asserted the
wrong order, and corrected both rows' comments to cite the clause that
actually governs each shape.
No layer in this codebase compares commemoration order: the lectio
differential never compares commemorations, the oracle sorts both
sides into a multiset, and the golden tests' own describe function
sorts its commemorations field too. Recorded as a new, permanent blind
spot in CLAUDE.md and the register, not merely fixed around -- the
admit_cases unit table is the only place order is asserted at all.
Re-measured the full blast radius against the same pre-change binary:
same 14,627 differing days, same four shapes and counts, confirming
the fix changed only the content of the 593 shape-(c) rows and nothing
else. Mutation-tested: reverting the splice back to a uniform prepend
reddens exactly the shape-(c) unit test; a new golden pin for a real
shape-(c) day (2004-02-22) stays green under the same mutation, living
proof that golden pins cannot see this axis, not merely a claim.
Separately, M19's own predicate checked a date and a diff shape but
not which candidate -- proved insufficient by fabricating a second,
bogus companion on 30 June and confirming the whole suite stayed
green. Fixed by requiring the admitted commemoration to be exactly
commemoration-of-st-peter, mirroring C16's own identity guard. Added a
golden pin for 30 June, the only assertion of that entry's identity
outside the allow-list.
Also: corrected a false claim in the task report that the electronic
transcription carries no corroboration of the Holy Name fallback --
its own table of contents does, at a line not checked on the first
pass. Added two further citations, both re-verified against the scan:
RG 17's own closing paragraph, settling the Sunday shape's Sunday-
exclusion at the rubric level rather than only in the propers; RG
124(c), which assigns red to 30 June by paragraph number rather than
by the generic apostle/martyr default. Noted the fragility of deriving
the Sunday shape's RG 109(a) privilege from a slug-substring match
rather than from a citation. Cosmetic: a stray blank line and an
indentation inconsistency.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 110 (Caput XIV): "In Officio et Missa S. Petri semper fit
commemoratio S. Pauli, et vicissim... pro unica habeantur" -- in the
Office and Mass of either Peter or Paul, a commemoration of the other
is always made, uncapped by RG 111's own admission count. Both
photographic scans, full text including sub-clause (c) (a separate
trigger this register previously had not transcribed: the same rule
also fires when one Apostle's oration is admitted merely as an
ordinary/privileged commemoration, not only when it is the day's own
office).
Three real pairs in the 1962 calendar, all confirmed on both scans:
25 January (conversion-of-st-paul + peter), 22 February
(chair-of-st-peter + paul), 30 June
(in-commemoratione-sancti-pauli-apostoli + a new
commemoration-of-st-peter). The first two already existed as ordinary
sanctoral candidates but were wired into RG 111's ordinary, capped
admission contest instead of this rule's own uncapped one -- the
defect this closes. 30 June had no companion at all: a genuine gap
in lectio's own source data (confirmed directly against
tridentine-calendar.ini) and in missalemeum's own oracle output for
both fixture years, not only a colitur bootstrap miss, so colitur is
now uniquely correct on this date among the three engines compared.
Added via data/ef/adjustments.sexp's own Add directive, the
architecture's existing extension point for exactly this shape of
gap, since data/ef/sanctoral.sexp is generated and lectio must not be
touched.
Precedence_ef.admit gained rg110_additions/rg110_companion_slug,
layered on after admit's own four ordinarily-capped branches decide
their normal result: checks both the observed candidate and every
already-admitted candidate against the three-pair lookup and prepends
any companion found, uncapped and additional, never competing for
RG 111's own slot.
Measured full blast radius (1583-9999, pre-change binary from git
archive at 59fbda8 vs the fixed binary, 3,074,246 days each side,
14,627 differing days, all four predicted shapes, zero unclassified):
3,619 Holy Name fallback days (previous commit), 3,533 days Paul was
wrongly excluded from Chair of St Peter's own day by a competing
privileged feria, 593 days Chair of St Peter itself was admitted only
as an ordinary commemoration with Paul entirely absent, and 6,882 days
the new 30 June companion is added. The 3,533+593 figure supersedes an
earlier, narrower 852-day estimate that measured only the delta
between two older code commits, not the rule's full scope.
The lectio differential needed no change: it does not compare
commemorations at all, and this fix never touches season, slug, rank,
or colour. The missalemeum oracle allow-list needed three changes:
M12 removed (22 February 2027 no longer diverges in commemoration
count), M15's date list gained 2027-02-22 (now reaching identity
comparison for the first time, where it lands on that entry's own
pre-existing, unrelated limit -- one of the two commemorations is
temporal-origin and unnamed), and a new M19 for the 30 June gap.
Mutation-tested, both halves separately: disabling the admit-level
addition reddens the two new unit tests, the oracle's own M12-shaped
checks, and an existing golden pin (updated to expect the Paul
companion); removing only the 30 June data entry reddens solely the
oracle's new M19 count, confirming the code and data halves are
independently load-bearing.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 17(a): "festum Ss.mi Nominis Iesu, celebrandum dominica quae occurrit
a die 2 ad 5 ianuarii (secus die 2 ianuarii)" -- both photographic scans,
confirmed on the calendarium's own January table and the Mass propers'
own heading. Two defects closed together, since they interact through
RG 91 entry 14/RG 16(a):
1. The Sunday shape (2-5 January) now tags subject = Lord, matching
RG 91 entry 14 ("Festa Domini II classis") -- previously subject =
Temporal, the same defect shape Holy Family had before it.
2. The fallback (RG 17(a)'s own "secus die 2 ianuarii", the calendarium's
"vel, ea deficiente, die 2 ianuarii") is now built: 2 January carries
the feast whenever no Sunday falls 2-5 January that year. Before this
fix colitur emitted no Holy Name office at all in such a year -- a
real II-class feast simply missing, on 3,619 of 8,417 years in the
domain (43%; 20 of the 46 years 2005-2050, independently re-derived
against `date -d`).
Both shapes band identically at RG 91 entry 14's MOVABLE half
(Precedence_ef.entry_14_movable_band) -- one feast, not two differently
classified ones, per the Mass propers' own single heading covering both
dates. No live collision exists in the current sanctoral data (nothing
fixed-date falls 2-5 January besides a Commemoration_only entry on 5
Jan), so the RG 16(a)/RG 112(a) interaction is proved with synthetic
precedence-level fixtures mirroring Holy Family's own precedent, not a
live-data regression. One asymmetry the synthetic tests found and kept
honest rather than forced: a losing Holy-Name-Sunday is privileged
(RG 109(a), "of a Sunday") and survives RG 111(a)'s cap; a losing
Holy-Name-fallback is not (2 January is not a Sunday, and no other
RG 109(a)-(f) category applies to it), so it gets no commemoration at
all if ever outranked -- both individually correct readings of RG 109/111's
closed lists.
Golden pins follow the brief's own vacuity warning: the Sunday shape
already emitted the right slug/rank/colour before this fix (an ordinary
Sunday and Holy Name coincide on those fields), so its pin asserts
subject explicitly rather than pinning the whole line uncritically; the
fallback pin (2029-01-02) is the one with teeth against the larger
defect, reddening on slug/rank/subject together if reverted.
Mutation-tested: each half of the fix reverted separately reddens
exactly its own tests (Sunday subject: the dedicated unit test, the
golden pin's subject field, one precedence end-to-end test; fallback:
the fallback unit/anchor/golden tests, the new C16 differential count,
and both shapes of the precedence end-to-end tests) and nothing else.
Adds data/ef/expected-divergences.sexp's C16 (lectio has no fallback for
this window at all) -- the lectio differential's own count, independently
re-derived against `date -d` for the fixture's 2005-2050 span, not
transcribed from the domain-wide figure. The missalemeum oracle window
(2026-2027) exercises only the Sunday shape and needed no new entry:
subject is not one of its compared fields, and both years' rows already
corroborate the Sunday-shape ranking (missalemeum's own 2026-01-04 and
2027-01-03 rows: rank 2, white, title "Holy Name of Jesus").
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
spot precisely
The full breakdown, precisely: of 730 days, 331 are resolved (330
matching, 1 mismatched -- M13, Joseph vs the Seven Sorrows), 399
unresolved -- 373 in M18's own bucket, 26 absorbed inside M1/M2/M3/
M16's own widened subsets where the axis fires alongside their
pre-existing citation. M18's own note previously stated only its own
373 without this fuller context.
Also names the blind spot the axis exists to close in exact terms,
not just "the observed day's identity": a TEMPORAL-origin observed
day silently replaced by a DIFFERENT temporal-origin observed day of
the SAME rank and colour -- exactly Holy Family's own shape, and the
reason every prior layer stayed green through the whole gap. States
explicitly what the count pin does and does not prove: it guards
against the 373/399 population moving silently in either direction,
but cannot say which specific day moved or why.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
test_holy_family_anchor_present_and_erosion_is_caught built its
"eroded" list by filtering the exact pair it then asserted was
absent -- removing an element and checking it is gone proves
List.filter works, not that any detector caught anything. Borrowed
the name of test_anchors_erosion_is_caught, which uses a genuine
one: missing_from_anchors, called with an "expected" set sourced
independently of T.anchors (named_slugs_for_year, via T.named).
Reworked to match that shape: the expected slug is now sourced from
T.sunday_slug (season/weekday logic, a different function entirely
from T.anchors's own hand-typed string), and both the presence and
erosion checks reuse the real missing_from_anchors detector instead
of a bespoke, self-referential one.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG16(a)/RG112(a) key on
Two of the three original Holy Family pins (2026-01-11, ordinary
year; 2024-01-07, earliest possible date) were byte-identical before
and after temporal_ef.ml's own fix. Reverting the feature failed only
the 2030-01-13 collision pin -- describe omitted subject, the ONE
field the change actually touches on an ordinary (non-collision)
year, so those two pins asserted an ordinary Sunday's identity and
called it Holy Family. Vacuity flavour #1 (an assertion already true
before the code under test ran), not #8 (promoted from actual
output) -- the other nine fields' values were independently sourced
and remain so.
subject added to describe's own formatted line. Every existing golden
pin's expected string updated to match -- each value independently
sourced (grep data/ef/sanctoral.sexp for the sanctoral-origin pins;
Temporal for every ef-* temporal slug) before running the suite to
verify, not copied from actual output and rationalised afterward. All
matched on the first attempt.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
On 7,197 of the 8,417 days Holy Family occurs (every year that
isn't the 13-January collision), every emitted byte was identical to
the pre-change binary -- subject appeared in no output path the CLI
or any test read. Celebration.make already takes ?names, defaulting
to empty, and Temporal_ef.build never passed it.
build now takes an optional ?names, set only on Holy Family's own
branch: a LATIN name, not English. The oracle's own observed-identity
axis (test_oracle.ml) reads only `en`, so this is deliberately
invisible to it -- an English name here would mean reading
missalemeum's own title text, the oracle this exact axis is compared
against, to decide colitur's "ground truth" name: the "expected value
promoted from actual output" vacuity flavour this project's review
process watches for. Latin has no such circularity: the calendarium's
own January table and the Mass propers' own heading, both
photographic scans, word for word, "Sanctae Familiae Iesu, Mariae,
Ioseph" -- the same genitive-title convention test_names.ml's own
worked example already uses for Easter ("Dominica Resurrectionis").
Every other temporal-cycle candidate, including the neighbouring
Sundays, still carries no name of any kind -- a targeted addition for
the one day this task built, not a claim that the general gap
(register's own open item on Holy Name of Jesus, RG 17(a)) is closed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
cite RG95's real primary authority
F2: the disposition comment for RG112(a) claimed the electronic
transcription "carries NEITHER this paragraph's own worked example
NOR its own more specific Mass-proper rubric... exactly the
transcription's documented defect" -- wrong on both counts, checked
directly rather than taken on trust.
RG 112 has no worked example in any of the three source documents
(the transcription included) -- there was nothing to drop. The Holy
Family Mass propers' own 13-January rubric is absent from the
transcription not because it silently drops content it otherwise
has (the project's own documented defect, dropped calendarium
commemoration lines) but because that specific document (a 2006 web
capture) contains almost no Mass-propers text of any day: 5
Introit-line occurrences across 26,322 lines, against 61 and 402 in
the two photographic scans; its own "Proprium de Tempore" page is a
table of contents linking to PDFs the capture never pulled in. A
coverage gap in a partial web capture, not an instance of the
narrower, different defect the methodology note actually describes.
The ruling is unaffected -- the propers' quotation is real, on two
independent photographic scans, and settles 13 January on its own --
only the attribution is struck, here and in test_precedence_ef.ml
(the register and the task report are corrected separately).
F7: RG 95's own second paragraph -- present in all three documents,
including the transcription -- is a more direct, occurrence-level
authority for the exact collision than RG 112(a): "if two feasts of
the same Divine Person... occur together, the one higher in the
table is kept, the other omitted." Added as the primary citation on
disposition's RG112(a) branch, with RG 112(a) and the propers' note
kept as corroboration. Also corrects RG 112(b)'s own framing: it is
bidirectional ("et vicissim"), and only the Lord-feast-wins direction
(RG 16(a)) is implemented -- the Sunday-wins direction has no witness
anywhere in this codebase's data and was wrongly described as already
covered.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
entry_14_movable_band = -14 was justified only by "cannot collide
with a real table position (1..28) or unclassified" -- a collision
argument, not an ordering one. band's own value is compared by plain
<, so a negative number beats every I-class entry (1-13), not merely
the fixed Baptism it was built to beat. Not live against the shipped
universal sanctoral data (no I-class universal feast falls 7-13
January, which is why the original 1583-9999 sweep showed only the
intended shape), but entries 12/13 admit PROPER and INDULT I-class
feasts too, and those arrive via adjustments.sexp-style overlays --
this architecture's own advertised extension path. A diocesan
patronal feast landing in Holy Family's window would have made the
inversion live immediately: the I-class feast displaced and
transferred to the next day, reproduced and confirmed before this
fix, reverted after.
Fixed by rescaling every band branch to the real RG 91 entry number
times ten (unclassified untouched at max_int) instead of the bare
1..28, reserving genuine headroom immediately before each entry for
a movable sub-rank -- not an arbitrary rescale: RG 91's own text
records a "primum mobilia, deinde fixa" split at three rows, not
only entry 14 (entry 12's own ninth sub-item, entry 14, and entry
20), so this leaves room for the other two without a second rescale
if either ever gets a live witness. entry_14_movable_band now
derives from entry_14_fixed_band - 1, tied together so they cannot
drift apart.
Added a synthetic I-class end-to-end test reproducing the exact
counter-example that found this: a universal I-class candidate
inside Holy Family's own 7-13 January window is now observed and
does not transfer, with Holy Family itself falling to RG109(a)'s
ordinary privileged-Sunday-commemoration path, the same treatment
any genuine feast outranking an ordinary Sunday gets.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
An ordinary year (2026-01-11, no fixed-date competitor), the latest
possible date and the one 13-January collision (2030-01-13, the
fixed Baptism of the Lord excluded entirely by RG91 e14 + RG112(a)),
and the earliest possible date (2024-01-07, Epiphany a Saturday) --
proving RG 17(b)'s own 7-13 January window at both ends, not only
its middle. Every field independently traced against the primary
text before typing it in, per this file's own header rule: season
stays christmastide (RG 72-73, unaffected by which Sunday of it this
is), week stays unset (Christmastide has no numbered weeks at all),
slug is unchanged from the plain Sunday key this date always carried
(temporal_ef.ml's own comment on why RG 17(b) needs no new
lectionary key), rank II class, colour white. Each weekday
independently cross-checked against "date -d <iso> +%A" (GNU
coreutils).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
layer_m_reason's own five entries whose diff shape was checked by
EXACT list equality (M1, M2, M3, M13, M16) lost their match once the
observed-identity axis widened every row's diff set two commits ago.
Each is widened the same way commemoration-identity was already
widened for M13 once before: the axis now ALSO fires alongside their
existing citation, same root cause, same id -- M1/M3 (temporal-origin
observed day, no name), M2 (same, plus five Paschaltide dates that
used to match cleanly and now surface for the first time), M13
(Joseph, sanctoral, now a genuine title MISMATCH, not merely
unresolved), M16 (the temporal Passiontide feria observed there).
M18 covers the remainder: 373 of 730 days whose observed celebration
is temporal-origin and so carries no English name at all -- the
overwhelming majority of the window, including Holy Family's own two
dates in it (2026-01-11, 2027-01-10), counted here rather than shown
as a false Matched. Gated on the diff SHAPE alone (this file's own
convention for a population this size, the same reasoning M2's own
title-substring predicate already uses instead of a date list),
verdict unresolvable -- the same fourth verdict M15 already
established for the identical limit on the commemoration axis.
Building an English name onto the temporal cycle is Plan 4's own
scope, register §6.
Teeth, per the brief: temporarily corrupted hilary's own English
name in data/ef/sanctoral.sexp (14 January 2026, an OBSERVED sanctoral
day, rank and colour left untouched) and reran. Reddened immediately:
2026-01-14: observed-identity-mismatch differ -- colitur=(rank=3
colour=w ...) oracle=(rank=3 colours=[w] title="St. Hilary" ...)
rank and colour agree on both sides -- exactly the shape the
pre-strengthening comparator would have slept through completely.
Reverted (git diff on the data file is empty) before this commit.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Before this task's Holy Family fix, colitur's generic Sunday
fallback lost outright to the fixed Commemoration of the Baptism of
the Lord on 13 January whenever it fell on a Sunday, producing the
SAME slug lectio's own tridentine-calendar.ini shows there --
squarely inside C1's own 6-13 January blanket (only Season differed).
Now that Holy Family (RG 17(b)) correctly outranks the fixed Baptism
and excludes it as a commemoration (RG 91 entry 14, RG 112(a)),
colitur's own slug on those seven dates (2008, 2013, 2019, 2030,
2036, 2041, 2047) changes to ef-time-after-epiphany-sunday-1 -- a
genuine identity divergence against lectio, which has no Holy Family
at all. C1's own predicate does not absorb it (jan_6_13_slug has no
entry for that slug), so it surfaced as unexplained, exactly the
check the task brief asked for: split it out into its own cited
entry rather than widening C1's predicate to swallow it silently.
C1's own expected_rows moves 368 -> 361 (back to its pre-rebootstrap
value, for a third and different reason than either of the first two
moves recorded in its own note); the new C15 covers the 7 rows,
gated on the literal date list AND colitur's own slug, the same
identity guard C1/C6/C8/C14 already apply.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two related fixes, both needed for Holy Family to actually observe
correctly on the seven years it coincides with the fixed
Commemoration of the Baptism of the Lord (13 January): 2008, 2013,
2019, 2030, 2036, 2041, 2047.
band's entry 14 ("Festa Domini II classis") gated on sanctoral
origin only, so a movable Class2 Lord feast had no row in the table
at all. RG 91 entry 14's own text says otherwise: "primum mobilia,
deinde fixa" -- movable first, then fixed. entry_14_movable_band
gives Holy Family (the one movable candidate this codebase builds
with subject Lord) a value strictly better than the fixed half's own
literal 14, negative so it can never collide with a real table
position -- without it, the two would tie at 14 and fall to
Precedence.resolve's own alphabetical tie-break, which picks the
WRONG side ("commemoration-of-the-baptism-of-the-lord" sorts before
"ef-time-after-epiphany-sunday-1").
disposition gets a new branch for RG 112(a) (Caput XVI, "De
Commemorationibus"): the Office, Mass or commemoration of a mystery
of one Divine Person excludes a commemoration of another mystery of
the SAME Divine Person. Winner and loser both subject Lord -> Omit,
not Commemorate -- without it, Holy Family observing correctly still
left the Baptism admitted as an ordinary Class2 commemoration under
RG111(b), which the primary text does not allow.
Confirmed by a MORE SPECIFIC primary source than RG 112(a) alone: the
Holy Family Mass propers' own note, found on both photographic scans,
word for word, immediately after the Postcommunio -- "Si festum S.
Familiae occurrerit die 13 ianuarii, Missa dicitur de festo S.
Familiae, sine commemoratione Baptismatis D.N.I.C., et sine
commemoratione dominicae." The electronic transcription carries
neither this rubric nor RG 112(a)'s own worked example -- another
instance of its documented defect, not merely absent from one check.
Still expected red: the lectio differential (2005-2050) now shows a
new, real divergence on those seven 13-January-Sunday dates -- lectio
has no Holy Family at all, so it still shows the fixed Baptism
observed there, unlike colitur now. The oracle's own M-series entries
also still need widening for the observed-identity axis added two
commits ago. Both are the next commits.
|