| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
temporal_of.ml's temporal only ever reached holy_family's own correct
26-31 December / 30 December fallback logic through sunday_slug, which
returns None immediately for a non-Sunday date. In a year 25 December
is itself a Sunday (26-31 December then holding no Sunday of its own),
the feast vanished entirely and fell through to an ordinary Christmas
ferial slug -- confirmed on 2022, 2033, 2039, 2044, 2050 (and roughly
1583..9999 domain-wide, one year in seven).
temporal's dispatch now consults holy_family directly, independent of
weekday, between the sunday_slug and christmas_feria_slug branches,
carrying the identical identity the Sunday case already builds
(subject Lord, holy_family_names, rank Festum). holy_family and
anchors were already correct and needed no change.
Added a direct example-based test for the fallback across five
affected years plus a control for the unaffected Sunday case, and a
domain-wide property (Holy Family is observed in every liturgical
year 1583-9999) folded into both the 200-sample QCheck run and the
exhaustive sweep -- the property that would have caught this directly.
Un-pinned the now-fixed behaviour everywhere it was recorded as
known-wrong: test_rite_of.ml's own 1583 pin (rewritten to assert the
fix), test_validate_of.ml's own independent exhaustive-sweep counter
and landmark-year filter (found via make check, not the initial
survey), and data/of/expected-divergences-litcal.sexp's L2/L3
allow-list entries against the litcal oracle (closed and removed, with
a dedicated regression test replacing the allow-list's own silence).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
W1: when 19 March (St Joseph) falls on Palm Sunday, colitur sent him
forward to Easter+9 instead of anticipating the solemnity backward to
18 March, the one rule in the whole Normae transfer machinery that
names an earlier date. Live in 16 of 1583-2100 (1595, 1606, 1617,
1690, 1758, 1769, 1780, 1815, 1826, 1837, 1967, 1978, 1989, 2062,
2073, 2084).
Blocked on a kernel contract: Rite.t.transfer_target required its
result be strictly later than the impeded date, an obligation argued
purely from the EF's RG 96. Traced against Calendar's actual placement
pass rather than assumed unsafe: the round loop re-resolves the whole
year fresh every round, and its two safety nets (~start/~stop; the
round-count guard) both test the target's own value with no comparison
against origin, so a bounded backward jump converges the same way a
bounded forward one does. The one requirement that stays load-bearing
is target <> origin: Precedence.resolve never deduplicates by slug, so
a candidate returning its own argument unchanged would collide with
itself in the same round's contest. Relaxed the obligation accordingly
(rite.mli) and added the fourth transfer_target branch in
Precedence_of, ahead of the existing three (Precedence_of.transfer_target,
Rule 0). calendar.ml needed no logic change, only two comments that
asserted "every genuine transfer moves forward" as a blanket fact.
Unpinned the two tests that asserted the old wrong (forward) behaviour
and replaced them with assertions of the correct one, plus a new
direct unit test of the backward branch across two independent years.
EF output is untouched: data/ef/ and lib/rites/rite_ef/ carry no diff,
and colitur day/readings for 2026, 1583 and 9999 are byte-identical
against a build of the prior commit. OF's own 2005-2050 window carries
none of the 16 affected years and shows zero unexpected diffs; the
full 1583-9999 domain still reaches a fixed point under the exhaustive
sweep.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I7 (final-review.md, 2026-08-25-colitur-of-phases-3-5): OF Sundays and
solemnities shipped without the Second reading, and the lectionary
data header called the First reading an "Epistle" -- EF vocabulary.
The sole blocker was Validate's own kernel-hardcoded assertion that a
well-formed day's sorted citation parts are exactly [First; Gospel];
Citation.part already carried Second.
Rite.t gains citation_shapes : Citation.part list list, the fourth
EF-shaped kernel misfit (after Preface.t, Mass_formulary.source,
transfer_target's strictly-later contract) and the first fixed rather
than only documented. EF supplies its one shape unchanged; OF supplies
two, [First; Gospel] on a feria/feast/memorial and [First; Second;
Gospel] on a Sunday or solemnity (OLM 1981 Praenotanda n. 66.1 vs
n. 69.1, n. 84(b)/(c), page-image verified against olm-1981.pdf).
Validate's "citations" check now matches against the rite's own
declared shapes rather than a single literal pattern, preserving all
three invariants it always enforced: zero or one complete shape, never
partial; no part outside what the rite declares; no part repeated.
bootstrap_lectionary_of.ml's cite now extracts a Second reading from
Sunday-cycle ini sections only, correctly excluding the one stray
`second` field lectio's snapshot carries on a weekday-cycle section (a
content-verified scraping artifact). The hand-authored Christmas Day
entry gains its own Second reading from the same OLM passage already
cited for its First/Gospel. Regenerated data/of/lectionary.sexp: 771
entries unchanged, citation fields 1542 -> 1725 (+183, all Second
readings), SHA-256 re-pinned, header wording fixed and a new coverage
bullet added. Responsorial Psalm is deliberately still not emitted --
OLM 1981 Praenotanda n. 71 itself lists it apart from the readings
proper as a chant with its own refrain, and the finding driving this
change names only the missing Second reading.
EF output verified byte-identical to the branch start (empty
lib/rites/rite_ef + data/ef diff since v1.0.0, plus a direct binary
comparison of `day`/`readings` for 2026, 1583 and 9999 against a
worktree build of the pre-change commit).
Tests: three new fixtures in test_validate.ml prove the generalisation
holds both directions (a multi-shape rite accepts either of its
declared shapes; a rite that never declared a shape still rejects it).
test_citation_coverage_of.ml's pinned residual grows 41 -> 49, all new
entries the same already-understood chapter-crossing shape.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The "KNOWN UNIMPLEMENTED FOURTH RULE" note (Normae n. 56(f)) still said
"No sanctoral data exists yet (Phase 3), so nothing is WRONG today" and
located the trigger at "25 March co-occurring with Palm Sunday". Both
are now false, and the date was already wrong when written: St Joseph
is 19 March, not 25 March -- 25 March is the Annunciation, a separate
solemnity handled elsewhere in this same module.
Phase 3 shipped data/of/calendar-2002.sexp on this branch, so the
defect is now live in 16 of the 1583-2100 years (19 March on Palm
Sunday); rewrite the note to say so and point at where it is pinned
(test_rite_of.ml's known-wrong-forward-transfer test, allow-list
entries L8/L9).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Temporal_of.named correctly guards the Nativity Vigil: when 24 December
falls on a Sunday it is the Fourth Sunday of Advent (Tabula I.2 outranks
I.3), not the Vigil, and named returns None so temporal's dispatch falls
through to the ordinary Sunday slug. anchors, however, still listed
("of-nativity-vigil", 24 December) unconditionally -- a regression from
the earlier R8 fix, which added the guard to named but never updated
anchors to match. In 2028 and 2034, anchors claimed the Vigil where
temporal actually returns "of-advent-sunday-4".
anchors exists precisely as an independent restatement whose stated
purpose is to catch an accidental single-site drift rather than leaving
it invisible -- it caught exactly this drift, just later than it should
have, only once Validate.run was wired for the OF rite for the first
time (nothing before that compared anchors against named/temporal, so
the two were free to disagree unnoticed).
Fixed by restating named's own guard exactly: the Vigil entry is omitted
on a Sunday year rather than replaced, since the Fourth Sunday of Advent
is an ordinary generic week-numbered Sunday, not one of the named days
anchors exists to restate.
Audited every other anchors entry the same way, across the full
1584-9997 domain (test_temporal_of.ml's own exhaustive sweep, run under
COLITUR_EXHAUSTIVE_SWEEP=1): no further drift found. The sweep does
surface one already-known, already-pinned mismatch -- the "of-holy-family"
entry, in any year 26-31 December holds no Sunday (Normae n.35(a)'s own
30-December fallback) -- but it is a different shape, not a second
instance of this bug: there anchors computes the right date and it is
temporal that fails to reach it, which test_rite_of.ml already found,
pinned and deferred as out of scope. Corrected that file's own stale
comment, which still described the now-fixed Vigil disagreement as an
open gap.
New tests in test_temporal_of.ml cover both a Sunday-24-December year
(2028, 2034) and a non-Sunday one, checking every anchors entry against
temporal directly, plus a positive assertion that the Vigil entry is
correctly present or absent depending on the year.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Christmas-season dates
The bootstrap excluded 19 lectio bases as "date-keyed duplicates", but
17 of them were not duplicates at all: the 8 O-Antiphon days
(17-24 December) and 8 further Christmas-season dates (29-31 December,
2-5 and 7 January) each carry unique per-date content found nowhere else
among the emitted entries, verified against lectio's own ini directly.
17 December is Gen 49:2,8-10 / Matthew 1:1-17, but colitur was falling
through to that year's unrelated weekday-keyed "advent-3-mon" content
instead.
OLM n. 69.3 explains why: those ferias are fixed by civil date, unlike
every other Advent/Christmastide/Paschaltide feria, which is merely
non-alternating within a weekday slot. Temporal_of's own ferial slugs
for these dates are weekday-keyed, so looking one of those up served
whichever OTHER date happened to share that year's weekday alignment --
a citation that silently drifted year to year on ~16 real civil dates
(6 January stays excluded: Temporal_of fixes Epiphany there
unconditionally, so that date can never reach the ferial path at all;
two more, easter-6-thu and advent-4-sat, stay excluded for their own,
different structural reasons).
Fixed with a date-keyed lookup route (Lectionary_of.date_keyed_slug),
tried before the weekday-keyed one in readings' own step 3.
Temporal_of's slugs are unchanged -- only which lectionary key resolves
a day's citations. tools/bootstrap_lectionary_of.ml now maps the 17
bases to synthetic date-keyed slugs instead of excluding them, and its
own reachability sweep calls date_keyed_slug directly so the two can
never drift apart. Re-emitted data/of/lectionary.sexp (754 -> 770
entries) and corrected its provenance header, which previously
described these dates as excluded duplicates.
Also states, for the first time, a Minor finding from the same review:
190 of 222 shipped sanctoral slugs have no dedicated lectionary entry
and correctly fall through to the ferial per OLM norms -- expected
behaviour, not a gap, but never said in the coverage report before.
New tests pin 17 December (Gen 49:2,8-10 / Matthew 1:1-17) and 2 January
(1 John 2:22-28 / John 1:19-28) in two years with different weekday
alignments, proving neither reading drifts, plus direct boundary
coverage of date_keyed_slug itself (both windows, the 6 January
exclusion, and the Sunday guard).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Task 5 of Phases 3-5 (the payoff task): bundles Tasks 1-4's separately
built pieces (Temporal_of, Precedence_of, Rubrics_of, Lectionary_of)
into a (Vocab_of.season, Vocab_of.rank) Colitur_kernel.Rite.t, and
wires colitur day/readings --rite of <year> into the CLI. Default
stays ef; every pre-existing invocation is byte-identical (asserted
directly in test/cli.t and against a real v1.0.0 build for three
years, plus git diff --stat v1.0.0..HEAD over lib/rites/rite_ef/,
lib/kernel/, data/ef/ is empty).
No kernel change was needed, confirming the spec's central claim.
season_runs needed real thought rather than the brief's own suggested
Vocab_of.seasons: Temporal_of.season's own 'first run'/'second run'
comments confirm Ordinary Time is genuinely interrupted by Lent and
Easter over one liturgical year, so the expected run-length-compressed
sequence names it twice, six runs over five seasons -- exactly the
case Rite.t.season_runs's own doc comment already names as its
illustration for why this field is rite-supplied rather than derived.
easter/fixed_key are as specified, each carrying its own citation
(Gregorian computus; the 2002 Missal's one bissextilis occurrence is a
leap-year table entry, not a kalends-doubling rule, so fixed_key is
identity).
Follows rite_ef.ml's template and its lectionary-parameter lesson
exactly: lectionary is caller-supplied, not closed over.
test/test_rite_of.ml resolves the real assembled rite (calendar-2002
.sexp + all 13 amendment overlays + lectionary.sexp) through Calendar
and Validate.run, the same discipline test_validate.ml/test_rite_ef.ml
already apply to EF. This is the first time rite_of has been checked
this way, and it surfaced two new, real, cited gaps outside this
task's own scope to fix: Temporal_of never reaches Normae n.35(a)'s
30-December Holy Family fallback in a year with no Sunday in 26-31
December (first hit 1583, the domain floor), and Temporal_of.anchors
disagrees with temporal on 24 December when that date is itself a
Sunday (Advent IV outranks the Vigil, first hit 2006). Both pinned as
known-wrong, not fixed, the same treatment the brief's own pre-known
St Joseph/Palm Sunday gap (Normae n.56(f)) gets, pinned on 2062. A
third gap was found in data/of/lectionary.sexp's own coverage (audited
against one civil year only, so the other weekday-cycle letter is
unaudited and at least one pairing is asymmetric on shipped data) --
that file is excluded from this task, so the wide 2005-2050 sweep
checks structural invariants only and leaves the citation-chain checks
to the small, individually-audited landmark-year set.
make check (COLITUR_EXHAUSTIVE_SWEEP=1): exit 0, 867 tests, ~316s.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Task 4 of Phases 3-5: the last Rite.t field OF still needed, `readings`.
The cycle rules are CODE, cited to OLM (Ordo Lectionum Missae) 1981
Praenotanda -- verified against the real page image
(docs/research/of/olm-1981.pdf pp.32-33/"XXXII-XXXIII"), not the
document's own unreliable OCR text layer, per the design spec's own
caveat. n. 66 (with its footnote 102's worked example, 1980=C/1981=A/
1982=B/1983=C) gives the three-year Sunday cycle; n. 69 point 4 gives
the two-year weekday cycle, Year I in odd label years, Year II in
even. Both derive the "label year" the same way: one more than the
civil year Advent I opened in, per n. 66's footnote 102 itself
("nempe a prima hebdomada Adventus, quae cadit in anno civili
praecedente") -- so the cycle turns at Advent I, not 1 January, exactly
where the task brief said to get it right. The design spec's own
citation for the weekday rule, "Praenotanda n. 649", does not survive
a direct check against the primary source (search finds "649" only in
unrelated index/page-number entries); corrected here to n. 69, the
paragraph the rule's own Latin text actually sits under, confirmed by
the page image's own printed margin number.
The data is bootstrapped from lectio's of-lectionary.ini (988 keys,
niedziela.pl, harvest 2020-2025) by tools/bootstrap_lectionary_of.ml
-- OCaml, not the brief's own suggested .py: tools/bootstrap_lectionary
.ml already established this exact shape for EF, including a real
safety net ([assert_reachable], sweeping Rite_of.Temporal_of.temporal
AND the real merged sanctoral layer directly) that a second-language
reimplementation would either duplicate or lose. Handles two real
data anomalies found while building it: one malformed ini line (a
Polish Septuagint-numbering annotation for Sirach 3, "Syr 3,2-6.12-14"
against OLM/CEI/USA's shared Nova Vulgata, matching the design spec's
own sec5 finding); and two Sunday-cycle-labelled bases (Annunciation,
Immaculate Conception) where a scraping-year artifact left one of
three cycle letters carrying a different day's Mass entirely --
resolved by a general, mechanical 2-of-3 majority rule, not a
per-saint hand edit, and logged.
Coverage measured in both directions, per the brief's own Step 1:
- 1 of 365 days in civil year 2026 (25 December, the Christmas DAY
Mass) has no Temporal_of-slug match anywhere in lectio's 988 keys --
only the Vigil is present. Named in the data file's own header.
- 0 of 438 distinct lectio bases map to no colitur slug, after 19 are
deliberately excluded (late-Advent/Christmas-season DATE-keyed
duplicates lectio also carries in a WEEKDAY-keyed form colitur's own
slugs actually match -- Lectionary.t has no date-keyed lookup at
all, so the date-keyed family is transcription-inert, not silently
dropped: named explicitly, not a residual).
Lectionary_of.readings is three steps (no Commons indirection, unlike
EF -- out of this task's scope): the observed celebration's own
embedded citations; else, for a real sanctoral winner, its own slug
looked up directly (flat, then both cycle letters); else the day's
own temporal slug, same lookup. No preceding-Sunday fallback: OF's own
two-year cycle assigns every Ordinary Time weekday its own reading by
design, and no OF norm was found instructing otherwise.
Tests (test/test_lectionary_of.ml, 12 cases): a cycle-arithmetic table
straddling Advent 1980/1981/1982/2025 inside single civil years,
reproducing OLM n.66's own worked example directly; SHA-256 pins on
both the emitted file and lectio's own source (embedded in the
provenance header); a pinned, NAMED 2026 coverage result (364 resolve,
exactly {25 December} does not -- never a bare count); two resolution-
chain spot checks (a plain ferial, and a saint's day beating the
ferial it would otherwise fall on); and a real subprocess test that a
missing lectio source file fails the generator loudly, non-zero exit,
no output written -- the exact bug Task 1's own generator shipped and
needed a review round to fix.
dune test: exit 0, 856 tests. make check (COLITUR_EXHAUSTIVE_SWEEP=1,
full 1583-9999 sweep): exit 0, 862 tests, ~342s, both run unpiped in
the foreground. git diff --stat v1.0.0..HEAD -- lib/rites/rite_ef/
lib/kernel/ data/ef/ still empty.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fix round 1 for Task 3, addressing review findings.
Rename the exported creed function from `credo` to `creed` across the
.ml, .mli and test call sites, so the OF rite bundle can write
`creed = Rubrics_of.creed` with no gratuitous mismatch against
Rite.t's own field name, matching Rite_ef.Rubrics_ef.creed's own
naming. IGMR n. 67's own heading is "Professio fidei" and its body
says "Symbolum", never "Credo" -- documented as a comment on the
now-correctly-named function rather than kept as the exported name.
Local test helpers (credo_on_temporal, check_credo, test_credo_*) and
Alcotest description strings keep the Latin shorthand, since only the
call sites against RO.creed needed to change.
Corrected two comment inaccuracies:
- The Annunciation (25 March) is NOT always inside Lent, unlike St
Joseph (19 March): 25 March sits after Easter's own earliest
possible date (22 March), so in an early-Easter year (2008, Easter
23 March) it falls inside the Easter Octave instead, or is
transferred under Normae n. 60/5. No functional effect (gloria/creed
read observed/temporal as actually resolved), but the stated reason
was wrong.
- The Requiem-silence argument's counts: three All Souls Mass
formularies (not two), and roughly 147 Gloria+Credo markers combined
elsewhere in the Missal (not "over 150", which conflated Gloria
alone with the combined figure) -- recounted directly against a
fresh pdftotext -layout extraction rather than estimated.
Added: an independent corroborating citation for the Holy Thursday /
Easter Vigil Gloria exception, Vigil n. 31 -- the Easter Vigil's own
praenotanda ("VIGILIA PASCHALIS IN NOCTE SANCTA"), a THIRD
independently-numbered rubric set inside the same Missal PDF,
confirming the Vigil's own Gloria directly rather than resting solely
on the Holy Thursday rubric's forward-looking "usque ad" clause.
dune test: exit 0, 845 tests. make check (COLITUR_EXHAUSTIVE_SWEEP=1,
full 1583-9999 sweep): exit 0, 851 tests, 330.3s, both run unpiped in
the foreground. git diff --stat v1.0.0..HEAD -- lib/rites/rite_ef/
lib/kernel/ data/ef/ still empty.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Task 3 of OF Phases 3-5: the celebrant-rubrics module for the OF rite,
supplying three of Rite.t's four remaining fields.
creed/gloria implement IGMR n. 53 (Gloria) and n. 67-68 (Symbolum),
both quoted in full in the module header. temporal is read, not
observed, for both Sunday clauses: Temporal_of.temporal tags every
Sunday of Advent/Lent/Easter Sollemnitas (the privileged-season
convention), so an observed.rank test alone would wrongly grant Gloria
on an Advent or Lent Sunday, which n. 53's own "extra tempus Adventus
et Quadragesimae" explicitly withholds. Credo is deliberately narrower
than Gloria: n. 68 has no "et festis" clause, so an ordinary Festum
does not get the Creed, unlike EF's RG 475(b)/(c). Two Missale-proper
exceptions (Holy Thursday evening Mass, the Easter Vigil Mass) are
cited from the Missal's own "Dicitur Gloria in excelsis" rubric, not
the IGMR, which is silent on both. The Requiem question is likewise
IGMR-silent (nn. 379-385 say nothing about Gloria/Credo); flagged as
an inference from the Missal's own consistent marker pattern, applied
only to the one Requiem-shaped slug the shipped OF data can construct
(all-souls), the same closed-population discipline Rubrics_ef's own
Colour.Black proxy uses.
preface returns None unconditionally, a measured verdict rather than
a stub. The module header transcribes the 2002 Missal's own "INDEX
PRAEFATIONUM" in full: nine of Preface.t's 15 EF-cited constructors
name an OF occasion with multiple distinct texts (Nativity x3, Lent
x4-9, Easter x5, Ascension x2, Holy_spirit x2, Bvm x5, Apostles x2,
Common split across two independent 7/8-member families, Requiem x5)
-- structurally lossy to collapse into one constructor. The other six
(Epiphany, Trinity, Sacred_heart, Christ_the_king, St_joseph,
Holy_cross) match cardinality with a single OF text apiece, and were
checked and rejected anyway: Preface.t's own constructors are RG-cited
by construction, and IGMR n. 364's own "quibus Missale Romanum
ditatur" (prefaces the Missal is ENRICHED with) is direct textual
evidence the 2002 collection is not a bare carry-over -- corroborated
directly for Sacred Heart, whose OF text was read and found to be a
different composition from its RG 491 namesake. Reusing any of the
six on cardinality and theme alone would be the exact "sounds similar"
trap the task brief warns against.
test/test_rubrics_of.ml: 26 table-driven cases. Every temporal-origin
row builds observed via Temporal_of.temporal on a real date; every
sanctoral-origin row (a solemnity in Lent, an ordinary Festum, a
weekday obligatory memorial, All Souls) pairs a real Temporal_of.temporal
result with an observed record copied verbatim from
data/of/calendar-2002.sexp, since no full OF Rite.t/Calendar pipeline
exists yet to derive one. Includes same-date Gloria/Credo pairs that
prove the two rules genuinely diverge (a Sunday of Advent, an ordinary
Festum) rather than one silently mirroring the other.
dune test: exit 0, 845 tests. make check (COLITUR_EXHAUSTIVE_SWEEP=1,
full 1583-9999 sweep): exit 0, 851 tests, 303.6s, both run unpiped in
the foreground. git diff --stat v1.0.0..HEAD -- lib/rites/rite_ef/
lib/kernel/ data/ef/ is empty.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Four fixes from fix round 2 review:
classify_subject's "maria"/"b.m.v" substring test over-matched 12 saints
who merely carry "Maria" in their own name (Maximilian Mary Kolbe, John
Mary Vianney, Mary Magdalene among them) as Bvm. Replaced with an
explicit BVM_DATES table of the 13 genuinely Marian entries. Bvm 25 -> 13.
The provenance header claimed lectio is "never a source", which omitted
that slugs and English names both come from it. Corrected to state
exactly what does (slugs, en names) and does not (every substantive
field) come from lectio. A missing lectio file used to degrade silently
to a different SHA-256 with no en names and no warning; it now fails
loudly. lectio's own SHA-256 is now pinned alongside the Missal PDF's.
Four more entries carried a second pdftotext artifact distinct from the
letter-spacing already handled -- a combining diacritic rendered as a
stray spacing character (Kim Taegŏn/Chŏng Ha-sang, Đũng Lạc, Makhlūf,
Kęty). Hand-repaired the same way Peter Damian was, each corroborated by
the identical corruption recurring in the Missal's own index.
precedence_of.ml's PHASE 3 HAZARD comment about All Souls (2 November)
was asserting a gap that no longer exists now that OF sanctoral data
ships. Added test_all_souls_beats_an_ordinary_sunday, which resolves the
shipped All Souls entry against a real per-annum Sunday (2025-11-02)
through the actual Precedence.resolve pipeline, and updated the comment
to record the resolution instead of demanding it.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Temporal_of.named claimed 24 December unconditionally as
of-nativity-vigil (Sollemnitas), and temporal's dispatch matched named
before sunday_slug. On a Sunday 24 December, the Fourth Sunday of
Advent -- Tabula I.2, Normae n. 5's own privileged Sundays of Advent,
Lent and Easter -- was silently replaced by the Vigil.
named now returns None for 24 December when that date is itself a
Sunday, so temporal's dispatch falls through to sunday_slug and the
day resolves as of-advent-sunday-4. The Vigil Mass is an evening Mass
of the following solemnity, not an office belonging to 24 December's
own civil day -- the same civil-day-granularity reasoning already
applied to Holy Thursday (Precedence_of.band's entry-1 comment) and to
expected-divergences-litcal.sexp's L1 entry. Every non-Sunday
24 December is unaffected.
Audited every other named entry for the same latent shape (see
.superpowers/sdd/of-r8-advent-iv-report.md): none of them has it,
either because the date can never fall on a Sunday, or because the
date IS the definition of that Sunday (Palm Sunday, Easter, Pentecost,
Trinity, Christ the King), or because the competing movable-Sunday
windows are constructed to exclude that date.
Added test_nativity_vigil_yields_to_advent_sunday, covering
2028-12-24 and 2034-12-24 (both inside the litcal fixture window) and
the 2026-12-24 non-Sunday control. Re-ran the litcal layer: no
allow-list counts moved, since it compares only season and
Ordinary-Time week, and both readings of 24 December are "advent"
either way. Updated test_precedence_of.ml's "entry 3, not 9" comment,
which had carried this as a known, unfixed defect, to describe the
fix; its own pinned assertion (a hand-built Thursday candidate) needed
no change.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fix wave from the final whole-branch review of OF Phase 2 (0 Critical,
5 Important, 8 Minor). Applies the five items ruled in-scope and records
two more, per the controller's R7/R8/R9 rulings.
Fixes:
- temporal_of.ml: season-boundary header cited "Normae n. 71-77", a range
that does not exist (the Normae end at n. 61) and collides with real IGMR
nn. 71-77 (Preparation of the Gifts) in the same PDF -- EF leakage from
RG 71-77. Corrected to Normae Titulus II, nn. 17-47, with a note against
reintroducing the wrong range.
- precedence_of.ml entry 3: added the Tabula's second clause (Commemoratio
omnium fidelium defunctorum / All Souls) to the comment, and recorded the
Phase 3 hazard -- Vocab_of.rank has no constructor for it yet, and every
natural tagging choice gets 2 November's precedence wrong in a different
way. No code change; nothing can construct the entity yet.
- precedence_of.ml transfer_target's search: added a domain_max_date guard
(following Rite_ef.Precedence_ef's existing shape and reasoning) so the
walk can no longer probe Computus past 9999-12-31, and it now returns the
last date visited on bound exhaustion instead of failwith-ing. .mli
updated to drop the @raise Failure clause.
- precedence_of.ml is_privileged_sunday: added its own inline Tabula I.2
citation, matching its sibling helpers.
- precedence_of.ml entry 10: trimmed the reused "universal or temporal-origin"
comment -- Temporal_of never constructs a Memoria_obligatoria candidate, so
the temporal-origin half was vacuous there.
Recorded without fixing (both comment-only, per explicit scope ruling):
- test_precedence_of.ml: corrected the entry-3 Nativity Vigil test's
characterisation. The pinned band-30 assertion (2026-12-24, a Thursday) is
correct, but is not the value on a 24-December Sunday (e.g. 2028, 2034),
where is_privileged_sunday instead bands the same candidate 20. Named the
underlying Phase 1 defect this exposes -- named() claims 24 December
unconditionally and is matched before sunday_slug, so the Fourth Sunday of
Advent gets no office at all in those years, invisible to the litcal layer
-- as known and carried to the next task.
- precedence_of.mli transfer_target: documented Normae n. 56(f) (St Joseph
on Palm Sunday anticipates backward to 18 March) as a known, cited,
unimplemented fourth transfer rule, and named the underlying kernel
constraint (Rite.t.transfer_target's strictly-later obligation, justified
only by the EF's RG 96) as the reason a real fix needs a kernel change.
dune test: 799 tests, exit 0. make check (exhaustive sweep): 805 tests,
exit 0, 224.7s. No kernel/rite_ef/data changes (git diff empty).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Three rules, in priority order: the Annunciation in Holy Week goes to
Easter+8; any other solemnity on a Sunday of Advent, Lent or Easter goes to
the following Monday (n. 5, which n. 60 defers to explicitly), except on Palm
Sunday or Easter Sunday; otherwise the nearest later day free of Tabula
entries 1-8.
The n. 5 Monday rule is easy to miss -- n. 60 names it only by cross
reference, and reading n. 60 alone yields a single search rule where the
sources give three.
Shaped to match Rite.t.transfer_target so a later phase wires it unchanged,
with its own step bound: Calendar's round guard bounds rounds, not one call's
internal search.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The prior comment claimed of-nativity-vigil is 'not a distinct celebration' -
wrong: Temporal_of.named (temporal_of.ml:230) constructs it as its own
Sollemnitas-rank candidate on 24 December, a genuine contestant in
band/Precedence.resolve.
The real reason None is safe is structural, not that. The Nativity is
Tabula entry 2 (band 20); only entry 1, the Paschal Triduum (band 10),
bands lower. The Triduum's Easter-2..Easter window is confined to 20
March-25 April because Gregorian Easter never falls outside [22 March, 25
April] over the whole 1583-9999 domain (measured exhaustively in
test_computus.ml, not assumed), so it can never reach 25 December. The
Nativity therefore always keeps its own day and its vigil can never be
orphaned by a transfer or reduction.
Behaviour is unchanged: vigil_feast still returns None unconditionally.
RG 33 (EF-only) and Normae nn. 11/13 remain the reason the hook exists at
all and returns None for every other candidate.
|
| |
|
|
|
|
|
|
|
|
| |
admit returns the empty list because disposition never returns Commemorate;
vigil_feast returns None because the OF has no vigil office that its feast's
movement could orphan -- 'of-nativity-vigil' is a Mass formulary of the
solemnity, not a separate celebration.
Both are argued from the sources rather than stubbed, and Precedence_of.rules
now assembles the four functions the kernel resolver consumes.
|
| |
|
|
|
|
|
|
|
|
| |
An impeded solemnity transfers; every other loser is omitted for that year
('Reliquae celebrationes eo anno omittuntur').
Commemorate is never returned, and that is the rule rather than a gap: the OF
has no commemoration of a losing celebration in the EF's sense, and an
optional memorial is an election rather than a commemoration. A property over
every rank pairing asserts it, so a later edit cannot quietly introduce one.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Entries 10-13. Entry 12 is one undivided row -- the Tabula draws no
universal/proper split for optional memorials, unlike entries 3/4, 7/8 and
10/11 -- so it deliberately does not read the layer.
Entry 13's four clauses need no date arithmetic of their own: every
privileged feria is entries 2 and 9, tested earlier in the chain, so what
reaches the final branch is exactly the residue those clauses name.
Entry 10 uses [not (is_proper layer)], not the brief's original
[is_universal layer]: is_universal was deleted as dead code in Task 2,
because every temporal-origin candidate carries layer = "temporal", never
universal_layer, so a positive is_universal test can never match one --
the same correction entries 3, 5 and 7 already apply.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Entries 5-9. Entries 5 and 7 differ only by subject -- 'Festa Domini'
against 'Festa beatae Mariae Virginis et Sanctorum' -- so they key on
Celebration.t.subject, the same field RG 91 entry 14 uses on the EF
side, never on the slug.
Entry 9's three clauses (late-Advent ferias from 17 December, the
Nativity octave, Lenten ferias) are what separates a privileged feria
from the ordinary one at entry 13.
CORRECTION to the task brief, applied here rather than after: entries
3, 5 and 7 test 'not (is_proper layer)', not 'is_universal layer'.
Every temporal-origin candidate Temporal_of.temporal constructs
carries layer = "temporal" unconditionally, never universal_layer, so
a positive universal-layer test silently excluded every temporal-cycle
solemnity and Lord-subject feast from these entries -- Corpus Christi
came out unclassified outright, and Trinity/Christ the King/Holy
Family/the Baptism of the Lord landed one entry too low. is_universal
is now dead and removed; entry 3's branch (written in Task 1) is
amended along with the new entries 5 and 7. Only entries 4 and 8 still
test is_proper directly, matching the Tabula's own proper-calendar
rows.
Also fixes a pre-existing typo in the brief's own 'entry 6: a Sunday
per annum' test row: rank was Sollemnitas, which -- being tested at
entry 3, earlier in the chain -- made the row fail regardless of the
is_universal/is_proper question, since no real Sunday per annum is
ever Sollemnitas. Changed to Festum, matching the adjacent 'Sunday of
Christmas time' row and real Temporal_of output.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The Tabula dierum liturgicorum's entries 1-4, one band branch each, scaled
x10 as Precedence_ef's own table is. The Triduum is identified structurally
by Easter offset because Temporal_of emits Good Friday and Holy Saturday as
ordinary Lent week-6 ferias, leaving no slug to key on.
Holy Thursday sits at entry 2, not entry 1: the Tabula's own entry 2 runs
'a feria II ad feriam V inclusive' and the Triduum opens with an evening
Mass inside that civil day. Same granularity decision the litcal layer's L1
records on the season axis.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The first code for a second rite. lib/rites/rite_of/vocab_of implements
the OF's five-way rank vocabulary (Sollemnitas/Festum/Memoria_obligatoria/
Memoria_ad_libitum/Feria) and five-season vocabulary (Advent/Christmas/
Lent/Easter/Ordinary_time), each constructor cited against the 2002
Missale Romanum's Normae universales and the Tabula dierum liturgicorum.
temporal_of implements season boundaries, week numbering — including
Ordinary Time's own two-block resumption, derived from the Missale's own
"HEBDOMADA I/XXXIV 'per annum'" headings and empirically verified across
the whole 1583-9999 domain — named temporal days, and Sunday/ferial
slugs. Both satisfy Colitur_kernel.Temporal.RITE with no kernel change.
No Rite.t is assembled and no CLI wiring is added (Phase 2's own scope);
lib/rites/rite_ef and data/ef are untouched, verified byte-identical
against the v1.0.0 tag across a domain-spanning sample.
test/test_temporal_of.ml adds unit tests for every boundary and named day
plus seven QCheck properties (seasons contiguous, Ordinary Time weeks in
1..34, Advent always four Sundays, slug uniqueness, weekday agreement,
determinism, consecutive liturgical years partition civil time), with a
committed exhaustive sweep mirroring test_validate.ml's own convention.
Full account, including the Ordinary Time derivation's evidence and a
list of EF concepts that do not carry over, in
.superpowers/sdd/of-phase1-report.md (untracked, gitignored).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 497 ("in Missis festivis et votivis Apostolorum et Evangelistarum")
carries no natalicium restriction, unlike RG 475(e)'s Creed clause --
preface_apostle_slugs already includes one non-natalicium sibling (In
Commemoratione S. Pauli, 30 June) on this exact reasoning.
conversion-of-st-paul (25 January) was left off pending a witness: the
FIUV Ordo's own single window has 25 January impeded by a Sunday.
Now witnessed four times, two independent publishers, four civil
years: the Latin Mass Society Ordo's 2023-2024 and 2024-2025 editions
both read "Pr of the Apostles" on their own unimpeded 25 January
(2024, 2025); extraordinaryform.org's 2024-2025Ordo.pdf and
2026-2027Ordo.pdf independently agree on their own unimpeded years
(2025, 2027, spot-checked, not wired in as a fixture). Every source's
2026 edition agrees 25 January is impeded that year and produces no
data point at all. No source disagreed with the textual reading.
Surveyed every other Apostle/Evangelist-named slug in
data/ef/sanctoral.sexp before concluding the list needed exactly this
one addition: the Dedication of the Basilicas of Sts Peter & Paul (18
November) is confirmed NOT an RG 497 trigger (all three LMS editions
read "Pr of the Dedication of a Church", not "Apostles" -- it is about
the buildings, not the Apostles in person); the Vigil of Sts Peter &
Paul (28 June) is confirmed "Common Pr", corroborating the pre-existing
"no vigil ever reaches this branch" comment.
Blast radius, measured exhaustively (1583-9999, new permanent sweep in
test_rubrics_ef.ml): 7217 domain years have 25 January unimpeded and
observed; all 7217 now read Apostles, zero exceptions.
Claude-Session: https://claude.ai/code/session_017ZBxCCRM2ojnBupp3SBxV9
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Item 2 of Phase 3 (celebrant-rubrics-phase1), the bulk of this phase
and the last EF Mass rubric this project scoped: which preface is
said, deferring to seasonal/proper-title rules for the fourteen named
prefaces, then RG 498's Common residual.
RG 482 gives the resolution chain: the Mass's own proper preface,
failing that the seasonal one, failing that Common. Read literally,
RG 484-497 look like fourteen separate rules, but each numbered
rubric's own propria/de-Tempore pair produces the SAME preface
identity either way, so the whole chain collapses into one priority-
ordered decision: title/mystery triggers (Holy Cross, Sacred Heart,
Christ the King, Trinity, St Joseph, BVM, the Nativity octave, the
Apostles, Epiphany), each independent of season, then six seasonal
windows (Nativity, Epiphany, Lent, Holy Cross/Passiontide, Easter,
Ascension, Holy Spirit, Trinity-for-ordinary-Sundays), then Common.
The "one genuinely unproven piece" the design spec worried about --
per-feast proper prefaces extracted from the Missal's propers at scale
-- turned out not to be a large-scale extraction problem at all: every
one of the fourteen propers is a closed, small, subject/slug-keyed
trigger (mirroring Precedence_ef.band's own RG 91 table), not
thousands of individual saints' pages. The one genuine open question
(RG 488, the Chrism Mass) is N/A: this engine resolves one Mass per
civil day and has no separate Chrism-Mass dimension.
Preface is a new kernel type (lib/kernel/preface.ml[i]), not an
EF-specific one, the same placement as Colour/Subject/Mass_formulary:
Liturgical_day.t is parameterised only over season/rank, so any field
it carries generically must live in the kernel even though only EF
constructs a value of it today. Wired exactly as creed/gloria were
(Rite.t.preface, Calendar.ml, Rite_ef.context), but Preface.t option,
not a bare bool: unlike creed/gloria, a preface is said only at a
Mass, and Good Friday (1955-restored Holy Week) resolves an observed
celebration but has no Mass at all -- None is the honest answer there,
and also the neutral value an unimplemented rite returns.
Two priority-order findings only the oracle settled, not derivable
from the Latin text in isolation, both cross-checked against 358
individually classified entries in the FIUV Ordo's own praef column
(test/fixtures/fiuv-ordo-2025-2026.sexp, already captured, wired up
here as a new comparison axis): RG 484(b)'s own "except Masses with a
proper of the divine mysteries or Persons" is narrower than every
other window's implicit exception (an Apostle inside the Nativity
octave is overridden to Nativity; outside it, keeps his own preface
even inside another window); and RG 495's "et votivis" half is live
for the one office this engine models without a votive-Mass dimension
(the Saturday Office of the BVM), which also proved a vigil is not a
"festum" for this purpose (the Assumption's own vigil takes Common,
not BVM, correcting an initial reuse of Precedence_ef.marian_slugs
that had no reason to make that distinction for its own, different
rubric). A third, RG16(a)-shaped fix landed the same way: RG 494(b)'s
own Trinity grant must read the day's TEMPORAL season, not the
celebration that actually won it, or a Class1 feast with no preference
of its own (All Saints) wrongly falls to Common on a Sunday it merely
commemorates.
colitur rubrics gains a sixth TAB-separated column. Domain-wide
1583-9999 exhaustive sweep confirms every Christmastide day resolves
Nativity/Epiphany/Bvm, every Paschaltide day one of its own three
windows or a season-independent title, every Lent day Lent or a
title, and Passiontide legitimately produces Easter exactly once a
year (the Vigil Mass) -- 8416 of the domain's 8417 years, the one
short year being the domain's own upper boundary (the liturgical year
opening in 9999 cannot construct dates in year 10000, a pre-existing
edge this sweep re-confirms rather than a new one).
day/readings verified byte-identical to the branch's own state before
this phase (commit 9c96e0a) across a 455-year sample spanning the
whole domain -- not literally to the v0.10.1 tag, which 22 earlier
commits on this same branch (Phase 1/2, the bissextile shift, the
Rogation colour fix) had already moved past before this phase began.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Temporal_ef.temporal's Rogation Monday/Tuesday branch hardcoded
Colour.Violet with no citation (data/ef/expected-divergences-lms.sexp's
L6, surfaced by the LMS Ordo). RG 119 assigns white to the de-Tempore
Office and Mass from the Paschal Vigil Mass to the Pentecost Vigil Mass
exclusive; Easter+36/+37 sit inside that window. RG 128's own exhaustive
four-case violet list never names Rogation days, and its vigil clause
(d) is doubly inapplicable: these are not vigils, and they are inside
Paschaltide, not outside it. RG 88 explains the violet actually seen in
print sources: "de Litaniis minoribus nihil fit in Officio, sed tantum
in Missa" -- the violet belongs to the Rogation Mass/procession, a
distinct votive text this engine does not model, not to the day's own
Office. Witnessed directly: LMS Ordo 2023-2024, 2024-05-06, "FERIA IV Cl
W" with "Gl", the Office and Mass printed separately from the optional
violet votive Mass of the Rogations.
Cascade verified, not assumed: RG 432(b) omits the Gloria on every
violet Mass, so the wrong colour was also silencing the Gloria on these
two weekdays even though RG 237(e) (Breviary, ordinary Paschaltide
ferias say Te Deum) already made it true underneath. White removes the
432(b) block, and the Gloria now follows Te Deum via 431(a), matching
the Ordo's own "Gl" -- confirmed with dedicated golden pins in both
test_golden.ml (colour) and test_rubrics_ef.ml (the Gloria flip),
2028-05-22/23 (neither day impeded that year).
Closed L6 in data/ef/expected-divergences-lms.sexp. Reopened C8 in
data/ef/expected-divergences.sexp (26 of 16801 rows, 2005-2050): lectio
independently computes these two days violet too, so the two engines
used to agree by sharing the same uncited assumption; colitur's colour
is now correct and lectio's is not, so the comparator disagrees again,
for the opposite reason. While reopening C8, found and corrected a
genuine misattribution in its own prior closure note, which claimed
lectio's violet was "RG 128(d)" -- 128(d) governs vigils outside
Paschaltide and has nothing to do with Rogation days. Checked
docs/research/rules-register.md for the same claim: not present there,
but a related conflation was found and corrected at its O'Connell
section 4(d) note, which had used a Rogation MASS/procession citation to
"confirm" the day's own OFFICE colour.
Blast radius measured in-process across the full 1583-9999 domain
(throwaway probe, not committed): 4722 days total (2368 Rogation
Mondays + 2354 Rogation Tuesdays actually observed outright, i.e. not
impeded by a stronger sanctoral feast that year), all Violet->White,
all with the Gloria flipping false->true alongside, zero anomalies.
Mutation-tested: reverting the branch to Colour.Violet reddens 16 tests
across Rubrics_ef, the lectio differential, the LMS Ordo suite and both
golden pin files; restored and reconfirmed green (680 tests).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Phase 2 of celebrant-rubrics-phase1: colitur rubrics gains a fifth
column, whether the Gloria is said. Follows the Creed's own seam
exactly -- Rite.t.gloria, Liturgical_day.t.gloria, wired through
calendar.ml the same way.
RG 431(a)/432(a) defer the Gloria to the Breviary's own Te Deum rule
(nn. 237-238), so te_deum is implemented as its own named predicate,
cited clause by clause, not collapsed into a colour heuristic. 431(c)
(Holy Thursday, the Easter Vigil Mass) and 432(b)/(d) (violet; a
Requiem) are independent overrides checked ahead of the Te Deum-derived
answer. Every clause this engine has no dimension to model
(votive Mass classes, the wider n.302 "Missa festiva" categories) is
stated as N/A with its own reasoning, not silently dropped.
Validated against the FIUV universal Ordo (Gloria and Te Deum) and all
three LMS editions (Gloria). A first pass over-trusted a clean-looking
15-for-15 FIUV contradiction of 237(b)'s own Septuagesima exception and
replaced it with a blanket "every Sunday" rule; the evidence was itself
corrupted -- the FIUV extractor recognised only one of the source's two
Te Deum negations ("non dicitur", not "sine"), so every "sine Te Deum"
Sunday read wrongly true. Fixed in tools/extract_fiuv_ordo.ml, fixture
re-extracted, and the literal 237(b) reading restored once the
corrected data confirmed it. A second bug surfaced alongside it (Palm/
Passion Sunday wrongly reading true via Temporal_ef.named's own table
membership, then Christ the King wrongly reading false from an
over-broad fix) is closed with an explicit two-slug exclusion.
Domain-wide 1583-9999: every violet or Rose day is gloria=false except
the Easter Vigil (RG 431(c) lex specialis), every Requiem is
gloria=false, both measured exhaustively, zero exceptions. Mutation-
proved: disabling 431(c) reddens 8 tests including all four oracle
comparisons; disabling 238(c)'s feria-I-classis exclusion reddens
exactly the dedicated Ash Wednesday unit test, a genuine blind spot in
both oracle layers, reported rather than hidden.
Two open, cited findings, neither fixed here (out of this task's
"follow creed's exact seam" scope): a privileged Lenten/Passiontide
feria carrying one commemoration reads Gloria=true in the LMS Ordo but
Te-Deum=true/Gloria=false in FIUV -- the two oracles disagree with each
other, not merely with colitur (data/ef/expected-divergences-lms.sexp
L5, expected-divergences-fiuv.sexp F3); and a pre-existing, uncited
Colour.Violet bug on Rogation Monday/Tuesday in Temporal_ef.temporal,
surfaced by this comparison but root-caused as a separate defect (L6).
day/readings verified byte-identical against a build from the branch
tip before this task (v0.10.1's own tag predates an already-landed
bissextile fix that legitimately changed both, so it is not the right
baseline).
671 tests green (dune test); 678 with the exhaustive sweep
(COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force, ~104s).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Missale Romanum's calendarium footnote for February (LT.txt:5011-5014,
scan-corroborated scan2.txt:3050-3058): in a leap year the sixth kalends of
March (24 February) is doubled rather than a 29th day appended, so St
Matthias moves 24->25 February and St Gabriel of Our Lady of Sorrows
27->28, with 24 February itself carrying no fixed office that year.
data/ef/expected-divergences-lms.sexp entry L3 tracked this as an open gap.
Implemented as the rubric's own general mechanism (every fixed entry from
24 through 28 February shifts one civil day later in a leap year), not as
"move these two named saints": the two readings are indistinguishable on
shipped data (nothing else is fixed in that window) and diverge only for a
future --overlay entry in the same range, which the mechanism reading
covers correctly and a two-saints special case would not. This project has
already been bitten once (RG 16(a)) by a rule implemented against shipped
data's coincidental shape rather than the rubric itself.
Kernel stays rite-agnostic: Rite.t gains a fixed_key field (Date.t -> (int
* int) option), the same seam easter already establishes, read only by
Layer.on_date's FIXED half -- the movable half (Easter_offset/Nth_weekday)
is untouched. Default is the identity mapping, an optional argument on
on_date, so every existing caller and every rite that supplies nothing is
byte-identical to before this field existed. Date.is_leap is exposed in
date.mli (already existed in date.ml) so the rite reads the kernel's own
single-sourced leap-year definition. The EF implementation lives in
Rite_ef.Temporal_ef.bissextile_fixed_key, fully cited, wired into
Rite_ef.context.
Blast radius, measured over the full 1583-9999 domain (Calendar.year run
twice per civil year, real fixed_key vs identity, every day diffed): all
2,041 leap years in the domain show a visible change for each saint;
6,983 individual liturgical days change total, zero unclassified, across
four shapes (Matthias vacates 24 Feb in 1,803 years / occupies 25 Feb in
1,811; Gabriel vacates 27 Feb in 1,699 / occupies 28 Feb in 1,670).
L3's own prior estimate (1,650 years, observed-outright only) is confirmed
close on the same definition (1,677 measured); the broader observed-or-
commemorated count is higher, not lower, showing the narrow estimate
undercounted visible impact rather than overcounting it.
The lectio differential (2005-2050 fixture) gains a new cited entry, C40
in data/ef/expected-divergences.sexp: lectio implements no such shift, so
every leap year in its window now diverges on the two shifted days (21
rows, not the naive 44 -- the comparator never compares commemorations, so
a side where the shifted saint has zero comparator-visible footprint on
both engines produces no row). The LMS Ordo's 2023-2024 fixture -- the
window L3 was originally found in -- now matches on the Creed comparison;
its formulary-override bucket count is corrected 182->181 (24 February
leaves the counted Proper population, becoming Own_slug-sourced). The
missalemeum oracle fixtures (2026-2027, 2038, 2035) cover no leap year and
are unaffected.
L3 is closed: converted from an active allow-list record to a prose
closure paragraph (L1's own precedent), citation preserved verbatim, fix
and measured blast radius recorded. The id-list assertion narrows to [L4]
alone, and the now-dead "2024-02-24" -> "L3" date mapping is removed.
Six golden values pinned across four new test cases: Matthias in a leap
year (both the vacated and occupied sides) and a common-year control;
Gabriel likewise, deliberately choosing a leap year where he is admitted
only as an ordinary commemoration rather than winning outright, a
different shape from Matthias's.
Mutation-tested: forcing fixed_key back to identity reddens exactly five
test cases -- the differential's Layer C count-pin (C40 drops to 0 actual
vs 21 expected), the LMS Ordo's Creed and formulary-bucket checks, and
both new golden pins -- confirming the tests actually exercise the fix.
Reverted; dune test, the exhaustive sweep, and make check are all green.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The .mli promised said is "the slug whose Mass is said". For Votive
(RG 78/309(a), the Saturday votive Mass of Our Lady) it was set to the
day's own ferial slug -- whose Mass is exactly the one NOT said. A
consumer joining rubrics to readings on that slug would silently get
the wrong Mass: 2026-01-03 reports ef-christmas-1-saturday, which has
zero entries in data/ef/lectionary.sexp, because the citations
actually come from bvm_saturday_citations, a season-keyed function
with no slug of its own anywhere in the shipped data.
Chose the type-honest fix over the interim documentation one: said is
now Slug.t option, None exactly for Votive, because there is
genuinely no slug in the shipped data this field could report for
that one source. Adding real ids for the five seasonal BVM Masses
(the reviewer's first option) is out of scope -- a data restructuring
this round explicitly does not carry. Threading the office slug
through a second field was considered and rejected as redundant: the
day's own office is already available on the same Liturgical_day.t
via observed.slug, which every caller already has in scope regardless
of via, so said does not need to duplicate it.
colitur rubrics stays byte-identical: rubrics_line already has
d.observed in scope and falls back to its slug when said is None,
printing the exact value it always printed for a Votive row (verified
directly, diffed against pre-fix output across four years). colitur
day/readings are unaffected (neither reads Mass_formulary at all).
colitur emit --format sexp's pretty-printed line count for 2027 moved
9011 -> 9025: every day's formulary record widened by said's own
extra option wrapping, and to_string_hum wraps by column width.
Cosmetic only, diffed line by line to confirm every change is this
shape or a consequent wrap shift; recorded in test/cli.t alongside the
476(f) note it now sits next to.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
colitur said the Creed IS said on All Souls' Day and every other
Requiem-shaped day: RG 475(b)'s "in festis I classis" branch fired on
rank alone, with nothing checking RG 476(f), "Non dicitur symbolum ...
f) in Missis defunctorum". Allow-listed as L1 in
expected-divergences-lms.sexp on the argument that [creed] has no
notion of a Requiem Mass in its inputs and could not express the rule
without a signature change.
That argument does not hold. Colour.Black is used by exactly two
celebrations in the whole engine, verified by grepping every
occurrence in lib/ and data/: commemoration-of-all-souls
(data/ef/sanctoral.sexp) and Good Friday (temporal_ef.ml, already
false via the earlier RG 23(b) feria exclusion and has no Mass at all
in the 1955-restored Holy Week). So on every day this engine can
construct, colour = Black if and only if the Mass is a Requiem -- a
citable implication (RG 117 assigns black to Masses of the dead) on
this data, not a heuristic.
Rite_ef.Rubrics_ef.creed now reads observed.colour as RG 476(f)'s own
guard, positioned ahead of 475(b)'s rank branch. A new test,
test_colour_black_population_is_exactly_two, sweeps both the shipped
data and Temporal_ef's own code across a century and fails loudly the
day a third Colour.Black celebration is ever introduced, so the proxy
cannot silently rot.
L1 is closed in expected-divergences-lms.sexp, citation preserved.
Blast radius, measured (full 1583-9999 sweep, grouped by observed
slug): 8 416 days change from true to false, every one
commemoration-of-all-souls (missing from exactly 1 of the 8 417 domain
years, a boundary-year transfer effect at 1583/9999). A further 8 416
Colour.Black days are Good Friday, unaffected (already false before
this fix). colitur day/readings stay byte-identical to v0.10.1
(checked directly against a v0.10.1 worktree build, 9 domain-spanning
years); colitur rubrics changes on exactly the 8 416 days above.
colitur emit --format sexp's pretty-printed line count for 2027 moved
9010 -> 9011 as a side effect: Sexplib.Sexp.to_string_hum wraps by
column width, and All Souls' Day 2027's record grew one wrapped line
because "false" is one character longer than "true". Cosmetic only --
no field's data changed -- and pinned in test/cli.t with the
measurement recorded.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
rubrics_ef.ml's Creed check excluded feriae from 475(b)/(c)/(e) via an
explicit test for feria I classis (Ash Wednesday, Holy Week) and vigils
only. RG 24/25's feriae II and III classis (Advent 17-23 December, the
Advent/Lent/September Ember sets, the numbered Lenten/Passiontide
ferias) were excluded by no check at all, correct today only because of
an unstated Temporal_ef property (no ferial-origin office it builds
carries subject Lord/Bvm or an apostle-list slug). A comment read as if
this were established "by construction of the two exclusions
immediately above", which overclaimed: those two exclusions cover feria
I classis only.
Corrected the comments to name RG 24/25 explicitly, state what is and
is not checked, and cite where the real guarantee comes from. Added a
test that sweeps Temporal_ef.temporal across a century (1583-1682),
asserting the invariant directly against every ferial-origin day found,
with its own coverage counters confirming the span actually reaches
Advent 17-23, all three non-Whitsun Ember sets, and Lenten/Passiontide
ferias. The first run of the test found a real gap in its own
population filter (RG 17(a)'s 2 January Holy Name fallback, a genuine
feast sitting outside Temporal_ef.named for an architectural reason),
fixed by naming that date explicitly rather than narrowing the span.
Proved the test has teeth by mutation: forcing the ferial builder's
default subject to Lord reddened it (and 24 other tests, expected
collateral from an intentionally broad mutation) before being reverted.
No production logic changed -- only comments in rubrics_ef.ml. day,
readings and rubrics output confirmed byte-identical against the
pre-fix binary for four spot years across the domain. Also corrects a
stale test-case count in a prior task report (18 in the array, not the
19 recorded there); the array now genuinely holds 19.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Whether the Creed is said at Mass. New Rubrics_ef.creed, reached through
a new Rite.t.creed field and a new Liturgical_day.t.creed bool (false,
not an option, for a rite that has not implemented the rule); colitur
rubrics gains a fourth TAB-separated column.
475(a) reads the TEMPORAL cycle's own weekday, not the observed day: a
Sunday impeded by a Feast of the Lord (RG 16a) still says the Creed.
475(d)'s three octaves (Nativity, Easter, Pentecost) are pure date/
Easter-offset windows, checked first, since a saint's feast winning the
day inside one of them still says the Creed ("etiam in festis
occurrentibus") -- St Stephen, 26 December, is the live witness.
RG 23 classifies Ash Wednesday and every feria of Holy Week (including
the Sacred Triduum) as feriae, not festa, however high their rank, so
475(b)/(c)'s "in festis" never reaches them; this single check subsumes
476(a)'s own naming of the Chrism/Lord's-Supper Mass and the Easter
Vigil. RG 28-34 vigils are a third liturgical-day category, also
excluded from "in festis" regardless of rank -- reuses the already-
exported Precedence_ef.is_vigil rather than a new list.
475(e)'s Apostle/Evangelist natalicia list (creed_apostle_slugs) was
derived by grepping data/ef/sanctoral.sexp directly and checking each
candidate's own date against whether it is that saint's dies natalis --
not copied from any list supplied with the task. The Conversion of St
Paul and the 30 June Commemoration of St Paul are excluded (neither is
a natalicium); the Chair of St Peter and St Barnabas are included only
because the clause names them explicitly, which is exactly why it has
to: neither is a natalicium either.
475(c)'s BVM half reuses Precedence_ef.marian_slugs (newly exported)
rather than the subject field alone: checked against the shipped data,
almost every Marian sanctoral entry ships subject=Saint, not Bvm.
man/colitur.1's rubrics section is updated to match the new column;
test/cli.t repinned via dune promote for the same reason. Verified
day/readings output byte-identical to v0.10.1 across the whole
1583-9999 domain (both binaries' concatenated day+readings output,
6,148,492 lines each, zero diff). Domain-wide: 882,996 days say the
Creed, 2,191,250 do not; every one of the domain's 439,178 Sundays says
it, zero exceptions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fix round 1's own comment claimed the Latin Mass Society Ordo witnesses the
Votive tag directly, reading its "V Mass of BVM" as an abbreviation for
"votive". That was wrong: the Ordo's I-V are roman numerals naming WHICH
of the Missal's five seasonal "Missae de sancta Maria in sabbato" (RG
309(a)'s own "iuxta temporum diversitatem") is said on a given Saturday,
not a marker of the Mass's kind. All five numerals occur through the Ordo
(I x1, II x4, III x3, IV x3, V x8); the false reading came from "V Mass of
BVM" also being a substring of "IV Mass of BVM".
Votive itself is unaffected and stays correct on RG 431(e) alone, quoted
verbatim in its place: "e) in Missis votivis IV classis de Angelis,
quocumque die, et de B. Maria Virg. quae in sabbato celebrantur" -- votive
Masses of the IV class, of the BVM, celebrated on Saturday. The retraction
is recorded, not softened, in lectionary_ef.ml/.mli and the test pin's own
comment, together with what the Ordo's numeral actually means so the
mistake is not repeated, and the consequence it leaves behind: because the
numeral names WHICH seasonal Mass is said, a future comparison against the
Ordo (Task 6) can validate bvm_saturday_citations' own season-keyed
selection, not merely that some BVM Mass was chosen.
Comments and docs only -- no behaviour change. Both suites re-run green and
colitur day re-confirmed byte-identical.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Mass_formulary.source was missing a case for a Mass said IN PLACE of the
day's own office's Mass while that office is itself kept unchanged -- RG
309(a) and RG 431(e) both classify the RG 78 Saturday Mass of Our Lady this
way, in the Missal's own words, as a "Missa votiva IV classis... de B.
Maria Virg.", not as the day's own office's Mass. The Latin Mass Society
Ordo (docs/research/ordo/lms-ordo-2024-2025.pdf) witnesses it directly,
printing that day as "V Mass of BVM".
The BVM-Saturday branch in Lectionary_ef.readings was tagged Own_slug for
lack of a better constructor when Task 2 landed, flagged there as a
judgement call rather than a specified answer. That call was wrong: left
as Own_slug, a future comparison against the LMS Ordo (a later task in this
plan) would read every BVM Saturday as a manufactured divergence between
colitur's "own" Mass and the Ordo's votive one. Retagged to Votive; said
is unchanged (still the day's own, reused ferial, temporal slug) since the
office itself is unaffected, only the Mass said for it.
Added the new constructor's source_to_string case ("votive") and its own
test row, and pinned the branch itself in test_lectionary_ef.ml's formulary
cases at 1 August 2026, verified directly against the resolver rather than
assumed.
Both this session's own drifted pins that the earlier commit inherited from
the task brief are unaffected by this change, and both are re-confirmed
independently correct in this round: dune test and the exhaustive sweep are
green, and colitur day stays byte-identical against the pre-fix-round
binary.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Rite.readings now returns (Mass_formulary.t option * Citation.t list)
instead of a bare citation list, and Liturgical_day.t carries the result
as a new formulary field. Validate holds a rite that resolves a formulary
at all to resolving one on every day, the same discipline it already
applies to citations; the EF lectionary chain resolves Some on every day
of every year 1583-9999, confirmed by a direct sweep over 2005-2050 as
well as through Validate itself.
Plan Tasks 2 and 3 are merged into this one commit on the coordinator's
own instruction: Rite.readings' signature and the field that consumes it
are one atomic edit, and the intermediate state does not compile on its
own.
Each of the four lectionary steps now builds its own Mass_formulary.t at
the point it decides, not by re-deriving it afterwards from the citations
it returns: step 1 tags Proper with the observed slug, step 2 tags
Own_slug with the day's own temporal slug, step 3 tags Preceding_sunday
with the resumed Sunday's temporal slug, and step 4 tags Common with the
Common's own id -- Commons.find now returns that id alongside its
citations rather than discarding it, since it is only ever in scope at
the point the assignment is looked up.
The RG 309(a) Saturday votive Mass of Our Lady, which answers between
steps 4 and 2 rather than as one of the four numbered steps, is tagged
Own_slug too: Mass_formulary.source has no dedicated constructor for it,
and its own guard only ever fires when the observed celebration already
is the day's own (reused ferial) temporal slug, which is exactly what
Own_slug documents. Recorded as a judgement call in the task report, not
a specified answer.
test/cli.t's `emit --format sexp` line count is repinned (8472 to 8881):
that command serializes Liturgical_day.t whole, so the new field grows
its output. `colitur day` itself is untouched -- verified byte-identical
against the pre-change binary across 1583, 1900, 2026, 2038 and 9999.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 33 omits a II/III-class vigil in three cases: it falls on a Sunday, it
falls on a I-class feast, "vel si festum cui praemittitur in alium diem
transferri aut ad commemorationem reduci contingat". Only the first two
were built; the third was recorded in precedence_ef.ml as unimplemented on
the grounds that no witness existed in the shipped data. That reasoning was
wrong, and the rule fires on 1 744 days across 1583-9999.
Both halves of the clause reduce to one observable question -- is the feast
the OBSERVED office on the following day (RG 34 puts it there) -- so the
kernel asks it once per candidate, after place_transfers has settled the
year. No fixed point is needed: a vigil is a candidate only on its own day,
never on its feast's, so suppressing it cannot change what the next day
observes. Precedence.rules gains vigil_feast, which returns the slug of the
feast a vigil precedes; the kernel cannot infer that itself, because only
two of the five vigil/feast pairs share a slug stem.
Blast radius, measured pre-change binary vs HEAD over the whole domain and
classified: 1 744 days, three shapes, zero unexplained. 1 199 are the feast
reduced to a commemoration (10 August on a Sunday, St Lawrence); 478 and 67
are the feast transferred under RG 96 after the Sacred Heart or Corpus
Christi takes its day. The Assumption's and the Ascension's vigils never
qualify -- their I-class feasts always keep their own day.
Independently witnessed, which is unusual here. The published Ordo -- the
only witness outside the Divinum Officium -> missalemeum -> lectio lineage
-- omits St Lawrence's vigil on 2025-08-09, agreeing with colitur against
both engines. That date had been read earlier as an Ordo gap; the Ordo was
right, and correcting the misreading is what surfaced this clause. On
2027-08-09 the feast does keep its day and the Ordo omits a vigil colitur
correctly keeps, which is a genuine Ordo gap.
Allow-lists: C39 (lectio, 10 rows) and a 2038 oracle class citing the
register, the 2026-2027 window having no instance. The golden pin asserting
St Lawrence's vigil is violet moved 2025 -> 2027; its own comment had
reasoned about the vigil's weekday and missed that RG 33 also looks at the
feast's. Two new pins cover both shapes of the clause.
The vigil/feast table is built with Slug.of_string_exn: mutation testing
showed that of_string plus Result.to_option turns a typo into None, which
this hook's contract reads as "not a vigil", switching the rule off in
silence. Two tests assert the table against the shipped data in both
directions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
"113. Commemoratio de Tempore fit primo loco. In admittendis et ordinandis
aliis commemorationibus, servetur ordo tabellae praecedentiae." Only the
second sentence was implemented, adopted on ef-rg16a as the admission and
ordering criterion. The first -- the commemoration OF THE SEASON is made in
the first place -- was not, so ordering ran through band alone for every
commemoration including the seasonal one.
Reconciled with RG 110(c), which adds the inseparable Peter/Paul pair "ante
omnes alias commemorationes". Both rubrics are primary-source certain: the
photographic scans' OCR is illegible at RG 110(c), but docs/research/LT.txt,
the electronic transcription, carries the Rubricae Generales complete, and
O'Connell's footnote 39 turns out to render that clause exactly rather than
gloss it. They share a technical term. RG 113's own sentence fixes the sense
of "aliae commemorationes" as the ones other than the de Tempore one it has
just placed primo loco, and RG 110(c) sits three paragraphs earlier in the
same code. Read consistently, the pair heads the OTHERS, not the whole list:
season, then the pair, then the table order. So this runs after
rg110_additions, and List.partition's stability keeps the pair adjacent while
the seasonal commemoration steps in front of it.
Blast radius, two full 1583-9999 sweeps diffed: 3 533 days, every one
ORDER-ONLY -- the commemoration set is identical on both sides of every
changed day, checked as sorted multisets, zero days where anything else
moved. All are 22 February with chair-of-st-peter observed. Exactly the
population measured before the rule was written.
The order-sensitive test row is in test_precedence_ef.ml's admit_cases, which
is still the only place in the suite that asserts commemoration order at all.
It needed a mixed-origin candidate: every other candidate in that table is
origin = Temporal by default, so the rule is an identity on them.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 128(b)'s own exception list, transcribed in the rules register and
primary-source-verified since Task 16, excepts "Actione liturgica feria VI
in Passione et Morte Domini usque ad Communionem exclusive" from the violet
that otherwise runs from Septuagesima to the Easter Vigil. RG 132 assigns
black there. The register recorded this as an acknowledged gap rather than a
disputed reading -- the code comment beside the Holy Thursday exception says
so in as many words -- and it is closed here.
Found by two witnesses outside the Divinum Officium lineage that colitur,
lectio and missalemeum all share: O'Connell, The Celebration of Mass, 4th ed.
(1964), revised throughout to the Codex Rubricarum (1960) and the 1962
Missal, and a published 1962 Ordo. Both say black. So does missalemeum's own
colour set, which orders the day "bv".
The rubric is per-action ("usque ad Communionem exclusive") and the model
emits one colour per day; black is the day's principal one, the same
acknowledged limit RG 126's Palm Sunday blessing already carries.
Blast radius: one day per year, colour only, across the whole 1583-9999
domain. Two golden pins re-pinned. Good Friday's 46 differential rows leave
C23 for a new C36 gated on the exact triple [First_f; Gospel_f; Colour_f],
so C23's own exact-pair gate still means what its note says for its
remaining four days: 184 + 46 = 230, no residue, both counts from the
comparator rather than hand-counted.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
M11 was the one entry in the missalemeum allow-list adjudicated against
colitur, and it was right to be. The calendarium directs "Com. octavae
Nativitatis" under each of 26, 27 and 28 December (LT.txt:5454-5459) and
RG 109(c) makes a commemoration of the days within the Octave privileged.
colitur emitted none.
The cause was a reasoning error stated in Temporal_ef's own comment:
"26-28 Dec are Stephen, John and the Innocents, hence sanctoral". Their
office is sanctoral -- those II-class feasts win the day -- but they
remain days WITHIN the Octave (RG 67, "Dies infra octavam sunt II
classis"), and colitur built them as generic Class4 ferias. With no
octave-day candidate there was nothing for the feast to be commemorated
over. Building days 2-4 exactly as days 5-7 always were makes the
commemoration fall out of the existing machinery rather than needing a
special case: the feast wins on rank, the octave day loses, RG 109(c)
privileges it, RG 111(c)'s single slot goes to it.
A second, independent defect surfaced while fixing it. The octave-day
branch covered 29-31 December unconditionally, so a Sunday falling there
got a feria identity -- where RG 69 says a Sunday occurring 26-31
December SEMPER keeps its own office and commemorates the feast.
Confirmed against the oracle rather than argued: missalemeum shows
"Sunday in the Octave of Christmas" on 2035-12-30, a Sunday, where
colitur showed a feria. Both named and anchors now exclude Sundays;
anchors had asserted the octave slugs unconditionally and was wrong the
same way.
Blast radius, full sweep against the pre-change binary: 25251 days, every
one 26-31 December, exactly two shapes, zero unclassified -- 21653
carrying an octave-day slug and 3598 that are all Sundays, the RG 69
correction.
Allow-lists: M11 closed and removed. C6 narrowed 138 to 119, nineteen of
its days having changed temporal identity rather than verdict. M15
widened 18 to 22 -- both streams now commemorate the octave, but the
candidate is temporal-origin and carries no English name to match against
missalemeum's own, this entry's documented limit on four more dates.
Stated rather than glossed: this trades a substantive divergence, colitur
omitting a commemoration the Missal directs, for a comparator limit, the
commemoration existing but not being name-matchable. That is a real
improvement, but what the oracle now proves is that both streams
commemorate something on those days; the identity rests on the rubric and
the calendarium.
Register: section 6.17.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two open questions closed, both by looking rather than reasoning.
M13 listed three possibilities for 19 March 2027 and stayed open because
none was confirmed. The live one was (b): a rubric at St Joseph's own
Proprium Sanctorum entry overriding the general table, "the same shape as
the Annunciation's own Attamen clause", its text simply not yet found. It
was looked for directly. Joseph's entry runs from its heading straight
into the Introit with no rubric of any kind -- and the analogue does not
exist where the note placed it either: the Annunciation's entry does the
same. That exception lives in RG 96, a general rubric about transferring
an impeded I-class feast, not in its propers, so there is no precedent
for a propers-level override at all.
With (b) eliminated and (c) still unsupported, (a) stands: RG 91 ranks a
I-class feast above a III-class Passiontide feria, Joseph is not impeded
so RG 96 never engages, and colitur observes him. Recorded with its
limit, because this is elimination and not proof: the specific hypothesis
named is false, which is weaker than showing no rubric anywhere says
otherwise.
Separately, the note that Mass I of the BVM Saturday needed an
Advent-Saturday oracle year to corroborate it is answered: there is no
such year and cannot be. Advent has no IV-class ferias -- Class2 from 17
December, Class3 before -- and RG 78 requires a IV-class feria. Zero
IV-class Advent Saturdays across 2000-2100. Its single witness is not a
gap in the research but the only evidence obtainable. The branch is kept:
the Missal does print the Mass for Advent, RG 309's subject being Masses
that may be celebrated as votive, and an overlay producing such a day
would otherwise fall through silently.
Register: sections 6.13 addendum and 6.14.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 78's office has been built since ef-bvm-saturday: an otherwise
unoccupied IV-class Saturday is de sancta Maria in sabbato, white, IV
class. The Mass stayed the feria's, so the day observed Our Lady and then
read Colossians on the parable of the weeds. That is M26 shape 1.
RG 309(a) is the rule -- the Masses the Missal assigns "iuxta temporum
diversitatem" -- and it prints five, each under its own season heading.
All ten citations are transcribed from the scans with line numbers in the
source. Masses II-V were confirmed twice, against the scan and against a
live missalemeum capture of 2038 which names them and agrees on both
readings. Mass I rests on the scan alone: no oracle year to hand has an
Advent Saturday carrying this office. One witness where the others have
two, and the code says so rather than blurring it.
The mapping looked like the hard part and dissolved. The Missal's ranges
are cut by civil dates and movable feasts, not by this rite's seasons --
II ends mid-season at the Purification, III spans four seasons. But
measured against what a IV-class Saturday can actually be, it reduces to
a seasonal mapping plus one date test at 2/3 February, with no Easter
arithmetic at all: III's end to IV's start leaves the Triduum unassigned,
unreachable because Holy Saturday is I class; IV's end to V's start
leaves Pentecost week unassigned, also unreachable because that week's
Saturday is an Ember Saturday. Time after Pentecost then begins exactly
at Trinity, exactly where Mass V begins. Both gaps verified by sweep --
zero IV-class Saturdays in either across 2000-2059 -- not inferred.
The office is identified structurally, never off the slug, which it
deliberately shares with the ordinary feria: subject Bvm, IV class,
Saturday.
Blast radius: 87611 reading rows over the full domain, every one a
Saturday.
Allow-lists: M26 27 to 6, shape 1 gone, leaving only the Christ-the-King
residue argued in colitur's favour last commit. The 2038 suite's
BVM-SATURDAY-MASS class is removed rather than zeroed -- an id with no
rows must not be declared. M18 355 to 376. C17 widened 397 to 445,
taking its own Saturdays back from C1, C19 and C25, since one cause
should not be filed under two ids; C31 89 to 103; C25 closed at 0 rows,
its Holy-Name-week Saturdays now answered before step 3 is reached.
Three unit tests pinned the old behaviour and are corrected rather than
re-pinned: two asserted the day "keeps its ferial Mass", which was the
honest thing to assert while this was unimplemented. The third still
tests what it always did -- that step 4 refuses a temporal office -- and
only what answers instead has changed.
Register: section 6.13.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Date_spec carried one variant, Fixed(month, day), and its own header said
Sunday- and Easter-relative forms would arrive with the OF sanctoral. They
arrive early because two things needed them at once: a user-supplied
overlay carrying a local movable feast had no way to express "the first
Sunday of October", and Rogation Wednesday's commemoration has been
recorded as architecturally blocked since 2026-08-13.
That blockage turns out to have been a premise, not a fact. The register
concluded the Rogation "is not Commemoration_only sanctoral data by
nature... it needs a genuinely THIRD kind of thing this architecture has
no name for" -- but the reasoning rested on there being "no civil (month,
day) pair to anchor a Fixed entry to". That is a statement about
Date_spec's expressiveness. With Easter_offset the entity is ordinary
sanctoral data, the identical shape Add major-litanies already ships,
differing only in how the date is written. No third channel was needed.
The register is corrected rather than left contradicting the code.
Two variants: Easter_offset of int, and Nth_weekday of {month; nth;
weekday} with negative nth counting from the end. Fixed's sexp
representation is untouched, so all 327 sanctoral entries and the whole
overlay parse unchanged. Both are re-validated in t_of_sexp through their
smart constructors, extending the idiom Fixed already used -- the failure
that guards against is invisible, a spec deserialising into something
that silently never resolves and a celebration vanishing with no
diagnostic.
Easter is supplied by the rite, not computed in the kernel. Computus
ships Gregorian and Julian both, and picking one here would hard-code a
Roman assumption into rite-agnostic code and be silently wrong for a
Julian-reckoning rite. Rite.t gains an easter field; Rite_ef supplies the
Gregorian one.
Layer keeps a split index. Fixed entries stay in the year-independent
(month, day) table, which preserves the fast path and the "30 November
counted twice in a 371-day span" behaviour validate.mli documents for St
Andrew. Movable entries have no year-independent key by construction --
the same spec lands on a different (month, day) each year -- so they
resolve per civil year into a rata-die table. index_by_date is removed
rather than kept as an alias: two ways to index a layer, one of which
silently ignores movable entries, is the trap this change exists to
avoid.
Two domain-edge defects, both found by the suite rather than reasoning. A
liturgical year is Advent-anchored, so resolving civil year y names y +/-
1, and at the edges those are 1582 and 10000, which Computus correctly
refuses by raising. The ceiling surfaced through the domain-ceiling test,
the floor through `colitur day 1583` failing outright. Fixed once, in
Layer.index, the single point that calls the rite's easter -- a clamp
repeated per caller would have been two places to get wrong a third time.
Rogation Wednesday: RG 87 assigns the Litaniae minores to the Monday,
Tuesday AND Wednesday before Ascension (scan1:691); colitur built the
first two from the start and never the third. RG 88 keeps it out of the
Office, so the Ascension Vigil remains observed. RG 89 routes it through
the Major Litanies' rules, but RG 109's closed list names only maiores,
so by RG 107 it is an ORDINARY commemoration -- confirmed in the output,
not assumed. Name from the Missal's own "feria IV" (scan1:20495-20497),
violet to match the Monday and Tuesday offices.
Blast radius, full 1583-9999 sweep against the pre-change binary: 2257
days, every one the same shape, zero unclassified, line counts equal both
sides. The complement is the informative half -- in the other 6160 years
the Rogation does not appear at all, because RG 111 admits one
commemoration on a II-class day and an impeded feast takes it under RG
113, a Commemoration_only candidate having no row in RG 91's table. Both
shapes are pinned.
Allow-lists unmoved: layer 3 compares no commemorations and is blind by
construction, and layer 4's 2026-2027 window has a competing feast on
both Wednesdays, so the Rogation is capped out in exactly the years the
oracle can see. C8 is unchanged, asserted by its own count pin.
Not built: Sunday-relative specs, which nothing needs yet, and the
--overlay plumbing that would let a user actually supply a local movable
feast. Nth_weekday therefore ships with synthetic and property coverage
only; inventing a shipped entry to exercise it would be fabricating
calendar data.
Register: section 6.10.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Five follow-ups from the fix-round re-review, none touching a computed
result.
M20's note had said "moderate-high, not certain" with a specific revisit
trigger attached. The fix round raised the label to "near-certain" and
deleted the trigger in the same edit. Upgrading a confidence while
removing the condition that would lower it again is the one move this
record must not make, so the trigger is restored alongside the higher
label: no primary text anywhere names the Major Litanies in a
Mass-orations-count worked example, only the general II-class-Sunday
rule twice over. RG 434(b) closes the Office-shaped doubt and nothing
further.
"WORD-IDENTICAL" overstated the relation between RG 111(b) and n.
434(b). Only the trailing "quae tamen omittitur si commemoratio
privilegiata facienda sit" is verbatim in both; the openings differ,
n. 434(b) recasting the rule into the orations register. The claim was
self-refuting -- both texts are quoted adjacent to it -- and the
argument never depended on it. Now "identical in its operative clause".
And n. 434 is not "a different part of the same document": the running
heads put RG 111 under Rubricae generales and n. 434 under Rubricae
generales Missalis Romani, two distinct corpora bound in one volume,
which is the entire force of the corroboration. The code comment had
understated its own point.
Also corrects the register's LT line range for n. 434(b) (3574-3576, not
3564-3570; the (b) clause is not in the cited range), and records in
calendar.ml the diagnostic that channel (3) trades away: a rite whose
transfer_target names a date its own disposition omits used to raise a
loud, mislabelled Validate failure and is now silent at the origin. The
kernel cannot distinguish that from a deliberate omission without rite
knowledge it must not have, so accepting it is right -- but the signal
is gone, and that should be written down rather than discovered later.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
attribution, RG434(b)
F2: the task report's "colour/subject/names on the Litanies entry are
currently inert" was false for names -- test_oracle.ml's identity axis
reads Names.find on every commemoration, and the invented English name is
exactly why 2026-04-25 registers as a Comm_identity_mismatch, the reason
M5 had to be re-gated. Corrected precisely, field by field, in the report.
F3: Easter 2027 is 28 March, not 18 April, as previously stated in the
report's own "layer 4 is blind to the transfer" reasoning. The conclusion
survives (28 March is not 25 April); the date is corrected.
F4: "the exhaustive property sweep caught this immediately" was a wrong
attribution, in the report, the register, and calendar.ml's own comment.
The committed exhaustive sweep walks 1583-9998 in order and aborts at the
first failure; the years actually reported (5700, 4747) were draws from
prop_invariants, the default dune test run's 200-year random sample.
Corrected in all three places.
F5: the Litanies' privileged commemoration is due in the MASS specifically
(RG 108 + RG 81), never a separate Office answer -- colitur emits one
resolved day, and the M20 adjudication rests on that being the Mass
reading. Stated explicitly now in M20's own note, the register, and
precedence_ef.ml's own RG111(b) comment.
Also added to M20 and the register: Rubricae Generales Missalis Romani
n. 434(b) ("VIII - De diversis Missae partibus", "D) De orationibus", "I
- De orationibus in genere"), verified word for word against all three
documents -- word-identical to RG 111(b) but explicitly scoped to the
Mass ("post orationem Missae"), answering the objection that RG 111
(Caput XVI, which RG 106 says governs both Office and Mass) might be read
as Office-shaped. Moves the M20 adjudication from "moderate-high, not
certain" to near-certain.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RG 80 (Caput X, "De Litaniis maioribus et minoribus", A): the Major
Litanies are assigned to 25 April, transferred to the following Tuesday
(always Easter+2) when that date is Easter Sunday or Easter Monday. RG 81,
same division: nothing is done in the Office, only in the Mass. RG 109(f)
(Caput XVI): a privileged commemoration.
Entity: Commemoration_only, Fixed(4,25), via data/ef/adjustments.sexp's
`Add major-litanies` -- RG 81 denies it Office standing entirely, which is
exactly what Commemoration_only already means to Precedence.resolve (held
out of the observed contest by construction). Rank Class4 deliberately,
not Class1, to keep the new RG109(f) privilege branch live rather than
shadowed by privilege_of's existing "of a I-class day" branch. Colour
Violet by consistency with the sibling Minor Litanies; subject Saint, the
same "no special exclusion" default this codebase's other
Commemoration_only entries use. Names not primary-sourced, flagged as such
in the data file's own comment.
Transfer: reuses the existing RG 96 placement machinery
(Precedence.disposition's Transfer constructor + Calendar's
place_transfers/resolve_with_injected) rather than a new candidate
channel -- RG 80's own transfer is structurally the same operation RG 96
already performs for an impeded I-class feast. disposition gains a branch,
checked before the Commemoration_only catch-all: the Litanies losing to
winner slug "ef-easter-sunday" or "ef-easter-1-monday" is Transfer, not
Commemorate. transfer_target gains a branch, checked before the general
RG 96 search is even computed, returning Easter+2 directly with no search
at all -- necessary, not merely simpler, since Easter+2 is itself I-class
and a search from there would walk past the exact day RG 80 names (a
commemoration needs no unoccupied day the way a displaced feast does).
Privilege: privilege_of's previously-dead RG 109(f) branch now recognises
the Litanies' own slug. No other code change -- admit's existing
Class1/Class2-Sunday branches already implement "a privileged
commemoration categorically takes the slot" correctly, from an earlier
task.
Full blast-radius measurement, adjudication of the resulting missalemeum
divergence, and the mutation proofs are in the task's own report,
.superpowers/sdd/2026-08-12-colitur-rg16a/major-litanies-report.md.
|