<feed xmlns='http://www.w3.org/2005/Atom'>
<title>colitur.git/test/test_precedence_of.ml, branch v1.2.1</title>
<subtitle>deterministic OCaml engine to compute and validate liturgical calendars for multiple rites, template-driven output to year 9999</subtitle>
<id>https://git.labunix.xyz/colitur.git/atom?h=v1.2.1</id>
<link rel='self' href='https://git.labunix.xyz/colitur.git/atom?h=v1.2.1'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/'/>
<updated>2026-08-26T22:38:40Z</updated>
<entry>
<title>fix(of): correct the Annunciation's transfer_target slug, dead Rule 1</title>
<updated>2026-08-26T22:38:40Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-26T22:38:40Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=e26d7da141f7985fadc53d8399a69dbaa1153c94'/>
<id>urn:sha1:e26d7da141f7985fadc53d8399a69dbaa1153c94</id>
<content type='text'>
precedence_of.ml's transfer_target Rule 1 (Normae n. 60's fixed Easter+8
destination for the Annunciation falling in Holy Week) keyed off
"of-annunciation", a placeholder that never matched the real shipped
entry's own slug ("annunciation-of-the-lord",
data/of/calendar-2002.sexp). Rule 1 was therefore dead code: it could
only ever fire against test_precedence_of.ml's own synthetic candidate,
which happened to carry the identical placeholder.

Output was nonetheless correct on shipped data (latent, not live): Rule
3's general forward search structurally converges on the same Easter+8
target, because the Easter Octave occupies exactly Easter+1..+7 at band
20 and the 3-9 April window carries only memorials on the universal
calendar. The exposure is an overlay placing a proper solemnity (band
40) or proper feast (band 80) anywhere in 3-9 April, where Rule 3 would
diverge from Rule 1's fixed destination and Rule 1 would silently fail
to override it.

Fixed the slug, and updated the existing Rule-1 tests' own synthetic
candidate to the real slug so they keep exercising Rule 1 rather than
Rule 3's coincidental agreement. Added a test that tells the two rules
apart rather than only checking the output they happen to agree on: it
rigs the occupant callback to occupy Easter+8 with a synthetic
Tabula-entry-3 candidate, confirms (via a control case using a
different solemnity) that the rig genuinely forces Rule 3's search past
that date, then shows the real shipped Annunciation still lands on
Easter+8 despite the block -- only explicable by Rule 1 firing, not by
Rule 3 happening to agree.
</content>
</entry>
<entry>
<title>fix(of): break the movable-BVM-memorial tie per a CDWDS Notification</title>
<updated>2026-08-26T22:37:45Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-26T22:37:45Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=6e62e499aed1c5a31a18bcf5e9eaa7f2b0c4ff2e'/>
<id>urn:sha1:6e62e499aed1c5a31a18bcf5e9eaa7f2b0c4ff2e</id>
<content type='text'>
Mary, Mother of the Church (Easter+50) and the Immaculate Heart of Mary
(Easter+69) are both movable obligatory memorials that can land on a
FIXED obligatory memorial's own date -- e.g. 2011-06-13 and 2015-06-13,
both against Anthony of Padua. Both candidates banded identically at
Tabula III.10 (100, both universal Memoria_obligatoria), a tie band
could not break, so Precedence.resolve's kernel-level alphabetical
Slug.compare tie-break silently picked instead -- 892 days for Mater
Ecclesiae and 1109 for the Immaculate Heart across 1583-9999, all one
shape (measured against the pre-fix alphabetical order directly, zero
unexplained).

Searched the corpus rather than inventing a rule. colitur's two
previously-checked primary sources really are silent: the 2018 decree
(AAS 110, 437-438) never addresses universal-calendar coincidence, and
Normae n. 14's third clause resolves only two AD-LIBITUM memorials
colliding. A third source resolves it: the CDWDS's own "Notification on
the Memorial of the Blessed Virgin Mary, Mother of the Church" (24 March
2018 -- same dicastery and signatories as the decree; published only on
vatican.va, confirmed absent from the AAS 2018 combined index) states
that when this memorial "coincides with another Memorial of a Saint or
Blessed... the Memorial of the Blessed Virgin Mary is to prevail," and
extends the identical reasoning to the Immaculate Heart of Mary by name.
This is a rubric, not colitur's own reasoned choice.

Implemented as a sub-rank of 95, strictly between Tabula entries 9 and
10 -- the same "fits between neighbours" technique this module already
uses elsewhere -- scoped to the two named slugs rather than
[subject = Bvm], since the Notification's own reasoning is specifically
about a memorial's link to a movable solemnity of the Lord, not a
blanket Marian precedence.

Golden pin updated: test_rite_of.ml's 2011-06-13 tie now pins Mary,
Mother of the Church as observed (was Anthony of Padua, labelled "known
arbitrary"), with the header rewritten to state the outcome now rests on
the Notification, not a coin-flip. The litcal oracle allow-list gains
L10: litcal's own grade vocabulary has no representation for a 95
sub-rank (everything Memoria_obligatoria reads "Memorial"), a
representational gap in litcal, not a computational disagreement -- the
identity axis is untouched and needed no new entry.
</content>
</entry>
<entry>
<title>fix(of): anticipate St Joseph onto 18 March per Normae n. 56(f)</title>
<updated>2026-08-26T21:40:17Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-26T21:40:17Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=2f6d25aff88b4c76c61e36889f1c017b3cc8faee'/>
<id>urn:sha1:2f6d25aff88b4c76c61e36889f1c017b3cc8faee</id>
<content type='text'>
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 &lt;&gt; 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.
</content>
</entry>
<entry>
<title>fix(of): correct subject over-match, provenance truth, and stale hazard comment</title>
<updated>2026-08-25T21:51:36Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T21:51:36Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=0994587b3694bb87d9a8ee32d60babf25c784acf'/>
<id>urn:sha1:0994587b3694bb87d9a8ee32d60babf25c784acf</id>
<content type='text'>
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 -&gt; 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.
</content>
</entry>
<entry>
<title>fix(of): Nativity Vigil no longer suppresses a Sunday of Advent</title>
<updated>2026-08-25T20:38:31Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T20:38:31Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=a2fba71d8cccc765c4a987df99fa780f5467514d'/>
<id>urn:sha1:a2fba71d8cccc765c4a987df99fa780f5467514d</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(of): correct season citation, note All Souls gap, guard transfer search</title>
<updated>2026-08-25T18:51:23Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T18:51:12Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=0a85280b0588629a05149e07934759f83f7bd83e'/>
<id>urn:sha1:0a85280b0588629a05149e07934759f83f7bd83e</id>
<content type='text'>
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).
</content>
</entry>
<entry>
<title>feat(of): transfer_target per Normae nn. 5 and 60</title>
<updated>2026-08-25T18:24:29Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T18:24:21Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=e611e90b0b5433ddc9afdcf26cbf98a5c3a7be28'/>
<id>urn:sha1:e611e90b0b5433ddc9afdcf26cbf98a5c3a7be28</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(of): admit and vigil_feast, both argued degenerate</title>
<updated>2026-08-25T17:52:46Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T17:52:46Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=29f1cc7e67e75d3f35747e5f6edd4e7ba430f97e'/>
<id>urn:sha1:29f1cc7e67e75d3f35747e5f6edd4e7ba430f97e</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(of): disposition per Normae n. 60</title>
<updated>2026-08-25T17:47:52Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T17:47:52Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=ebbf88dae0110e9cb00935861fae1857107260cc'/>
<id>urn:sha1:ebbf88dae0110e9cb00935861fae1857107260cc</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>test(of): prove the Tabula is total over 1583-9999</title>
<updated>2026-08-25T17:40:52Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T17:40:52Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/colitur.git/commit/?id=fc88c6de225592d8700fe1eb40d870ec8863b57d'/>
<id>urn:sha1:fc88c6de225592d8700fe1eb40d870ec8863b57d</id>
<content type='text'>
A hand-transcribed 13-entry table is only trustworthy if nothing the engine
constructs falls through it. Sampled property plus an exhaustive sweep behind
COLITUR_EXHAUSTIVE_SWEEP, matching the claim Precedence_ef.band already
carries for RG 91's 28 entries.

Mutation-proved rather than assumed: deleting the entry-13 branch reddens it
on a named date.
</content>
</entry>
</feed>
