<feed xmlns='http://www.w3.org/2005/Atom'>
<title>lectio.git/internal/calendar, branch v0.46.0</title>
<subtitle>offline Catholic daily readings and liturgical calendar in Go, with CLI, TUI and web clients</subtitle>
<id>https://git.labunix.xyz/lectio.git/atom?h=v0.46.0</id>
<link rel='self' href='https://git.labunix.xyz/lectio.git/atom?h=v0.46.0'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/'/>
<updated>2026-08-12T12:51:33Z</updated>
<entry>
<title>oracle_ef_test: three structural coverage gaps in the strengthened test</title>
<updated>2026-08-12T12:51:33Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T12:51:33Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=96b14d17e5210b93f1c126fe165fd81ec1e839af'/>
<id>urn:sha1:96b14d17e5210b93f1c126fe165fd81ec1e839af</id>
<content type='text'>
Cheap fixes flagged in review, all confirmed against the committed
snapshot before being applied:

1. An unmapped season phrase skipped the RANK AND COLOUR checks too,
   not just the season comparison -- `continue` in the wrong place.
   Confirmed live: neither Holy Thursday ("maundy"/"holy week" do
   not match the title "Holy Thursday" itself) nor any of the six
   September Ember days (no "ember" case exists at all; the Advent
   and Lent Ember days only ever passed by an incidental substring
   match on "advent"/"lent") had any oracle coverage at all --
   reverting the Holy Thursday colour fix left this test green.
   Season skip and rank/colour checks are now independent.

2. Colour membership alone cannot catch a Rose regression: violet is
   a member of every rose/violet pair by construction (Gaudete/
   Laetare), so "got violet, want one of [rose violet]" passed even
   with RG 131's Rose support removed entirely. On the day the pair
   actually names (oracle rank 1, the Sunday itself, not a weekday
   reusing its propers), a colour set containing rose now demands
   rose specifically.

3. `has("sexagesima")` never matched missalemeum's own ligatured
   "Sexagesimæ" -- confirmed in the committed snapshot: the ligatured
   form appears 10 times, the unligatured form only 4, and every
   ligatured instance mapped to season "" (skipped from ALL coverage,
   not merely a season miss, given finding 1 above). Normalised once,
   generally (æ -&gt; ae), not as a single hardcoded word, so any other
   ligature this generator's own data may carry is covered too.

Net effect on TestOracleEF: 730 checked (up from 691), 29 skipped
(down from 39) -- the 10 reclaimed by fix 3. Still green: 0
unallow-listed rank or colour mismatches over the full snapshot.
</content>
</entry>
<entry>
<title>calendar: record the RG 95 chained-transfer gap in the source</title>
<updated>2026-08-12T12:50:58Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T12:50:58Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=09a14446d5b0d4150a6de118a7d04ab99e54c21e'/>
<id>urn:sha1:09a14446d5b0d4150a6de118a7d04ab99e54c21e</id>
<content type='text'>
transferIfImpededEF resolves one candidate's own transfer walk in
isolation and has no way to notice a SECOND, separately-transferred
I-class candidate landing on the same destination day -- St Joseph
(19 March) and the Annunciation (25 March) can both walk to the
Monday after Low Sunday in the same year (2008, 2035, 2046, e.g.
2035-04-02: annunciation-of-the-blessed-virgin-mary +joseph-spouse-
of-the-bl-virgin-mary). RG 95 grants the right of translation
"solummodo festis I classis" to I-class feasts only, so both
candidates genuinely have it, and the collision they land in
together is an ordinary RG 97/98 occurrence question this function
does not resolve: pickEF's plain alphabetical slug tie-break settles
it instead of re-walking the loser. RG 98 itself supplies the
determinism rule this collision needs and does not have: "in
paritate autem Officium prius impeditum praecedit" -- at equal table
position, the office impeded FIRST takes precedence, which is
chronological (Joseph, impeded on the 19th, before the Annunciation's
own walk begins on the 25th) and may favour Joseph over the current
alphabetical fallback.

No functional change -- this collision is left unfixed, defensible
against scope (it needs resolving occurrence between two ALREADY-
TRANSFERRED candidates, not a single one, a bigger shape than this
function currently has). Leaving it unrecorded was not defensible:
nothing in internal/calendar/ named RG 95, 97, 98, or chained
transfers anywhere before this comment.
</content>
</entry>
<entry>
<title>gen-sanctoral-ef, caldata: fix round 2 -- review found five real problems</title>
<updated>2026-08-12T12:50:34Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T12:50:34Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=e122fa4368e156b9c90c128a8daad9545b22ed11'/>
<id>urn:sha1:e122fa4368e156b9c90c128a8daad9545b22ed11</id>
<content type='text'>
External review of the seven-defect fix (round 1) confirmed all seven
correctly and structurally fixed, then found five further problems in
what shipped alongside, two of them critical. All five verified
independently before being fixed, not applied on the review's say-so
alone -- see each item below for the primary-source check performed.

CRITICAL 1: the regeneration destroyed all 322 Polish display names.
main() preserved name.la across a regeneration (missalemeum has no
Latin titles) but had no equivalent for name.pl, and never emitted
one -- name.pl count went 322 -&gt; 0 (confirmed: `git show
2386a45:internal/caldata/tridentine-calendar.ini | grep -c
'^name.pl'` = 322; the pre-round-2 file = 0). naming.CelebrationName's
own name[lang] -&gt; name.en fallback then silently substituted English
for every Polish EF display, reaching mobile.Day(date, "ef", version,
"pl") -- a shipped dlectio entry point -- with no error anywhere in
the chain, and nothing in this repo's test suite asserting any
name.* field at all. Fixed at the root, not by re-adding name.pl
specifically: `entry.la` (one hardcoded language) is replaced by
`entry.otherNames map[string]string`, populated from every
"name.&lt;lang&gt;" field already present except name.en (English always
comes fresh from missalemeum) and re-emitted verbatim, sorted for
deterministic output -- a third or fourth language added later
survives a regeneration without this function changing again.

CRITICAL 2: St Romanus was deleted, and St Eusebius (14 August)
excluded, on a primary-source claim the primary source itself
contradicts. The exclusion cited the calendarium's 9 August row as
reading only "Vigilia, III classis.", no "Com." line -- checked
against ONE of the three local Missal scans,
"1962-06-23,...LT.pdf", an ELECTRONIC TRANSCRIPTION. The other two,
PHOTOGRAPHIC scans of the actual 1962 Missale Romanum, both carry it:
"missale-romanum-1962.pdf" calendarium, 9 August: "XVI d V 9
Vigilia, III classis, Commemoratio S. Romani Mart.", with the
saint's own proper text elsewhere in the same scan ("Et fit
commemoratio S. Romani Mar-") and its own back-of-book index
("Romani Mart., 9 augusti ... 621"). The transcription silently
drops vigil commemorations generally (also missing there, present in
both photographic scans: 7 August Donatus, 25 December Anastasia).
14 August's "St. Eusebius" is the identical shape (calendarium: "XI
b XIX 14 Vigilia, II classis, Commemoratio S. Eusebii Conf.") and
genuinely a DIFFERENT person from 16 December's "St. Eusebius, Ep.
et Mart." (calendarium: "V XVII S. Eusebii Ep. et Mart., III
classis.") -- a Confessor and a Bishop-and-Martyr, not the same
saint duplicated. knownSpuriousComm (both entries) is removed
outright; slugOverride gains "08-14/eusebius" -&gt; "eusebius-confessor"
so the two no longer collide by slug. Going forward: the
photographic scans are the primary source; the electronic
transcription is a convenience index only; where they disagree, the
scan wins -- recorded in the generator's own comments, not just here.

IMPORTANT 3+4: Thomas Becket (29 Dec) and Silvester (31 Dec) were
silently promoted to class-4 by a hidden coupling. RG 68(d)/(e): "die
29 decembris, fit commemoratio S. Thomae Episcopi et Mart.; die 31
decembris, fit commemoratio S. Silvestri I Papae et Conf." -- both a
bare "Commemoratio" with NO class of their own; the DAY they fall on
(within the Nativity Octave) is II class, confirmed in the same
calendarium row. refYearExplainsAbsence calls calendar.Compute and
trusts a commemoration's own id-rank when the temporal day looks
class-1/2-strong; after this task's own earlier fix promoted 26-31
December from class-4 to class-2 (RG 67/68), that trust flipped for
these two from "not explained" to "explained" purely as a side
effect of an unrelated temporal_ef.go change -- the generator's data
inference reads the engine's own computed ranks, so a temporal_ef.go
rank change can silently rewrite generated data. Fixed narrowly (6-31
December excluded from ever trusting the id-rank, citing RG 68(d)/(e)
directly) and the coupling itself documented in
refYearExplainsAbsence's own doc comment as a standing hazard for the
next temporal_ef.go rank change, not just this one instance.
Separately, the SAME function's doc comment overstated its own
guarantee ("ANY class-1..4 saint would lose there") -- false for its
Lent/Passiontide limb, where a III-class privileged feria does not
beat a I- or II-class feast (RG 109(e) is privilege over an
equal-or-lower class only) -- and the "commemoration id names the
saint's TRUE rank" claim at the call site was falsified by its own
worked example (St Blaise's id claims rank 4, and he is still
correctly ruled RankCommemoration). Both rewritten to describe this
as the rank-blind sampling heuristic it actually is, not a rubric
evaluator.

IMPORTANT 5: the Purification's own citation, strengthened. Three
fixes to classOf's doc comment, no data change (the tag stays
"lord", per round 1's own decision): the colitur cross-reference is
removed (colitur bootstraps from lectio and was reading the same
oracle a second time, not independent corroboration, and citing a
sibling project's in-flight branch is not itself an argument); the
rule that actually makes the occurrence pattern diagnostic is now
named -- RG 91 entry 14 ("Festa Domini II classis") above entry 15
("Dominicae II classis") above entry 16 ("Festa II classis... quae
non [sunt Domini]"), each verified directly against the scan, not
paraphrased; RG 120(b) is recorded as genuine primary-text
counter-evidence ("Adhibetur color albus... b) B. Mariae Virg.,
etiam in benedictione et processione candelarum die 2 februarii" --
2 February filed under the white-colour rule's OWN "B. Mariae Virg."
heading, separate from 120(a)'s "Domini" heading), and RG 112(b)
("Officium, Missa aut commemoratio de dominica excludit
commemorationem... de festo vel mysterio Domini, et vicissim") is
cited as independently backing the empty commemoration list. A new
committed fixture test replaces reliance on the report alone, since
the deciding years (2 February on a Sunday) fall outside this repo's
committed 2026-2027 oracle snapshot: TestPurificationBeatsFebruarySunday
(internal/calendar/precedence_ef_repro_test.go), five independently
fetched years. One of the years this reasoning is sometimes quoted
against, 2036, is corrected in passing: 2 February 2036 is in fact a
Saturday, not a Sunday (`date -d 2036-02-02 +%A`) -- checked here
rather than repeated, 2042 used instead.

Witnesses (internal/caldata/caldata_test.go):
TestTridentineNamesPreservedAcrossRegeneration,
TestTridentineRomanusAndEusebiusPresent (replaces
TestTridentineNoSpuriousRomanus, whose own name asserted the
now-corrected wrong claim). Pre-fix failures (captured against the
committed pre-round-2 state, commit 50e3970):
  name.pl coverage = 0 entries, want &gt;= 315
  assumption-of-the-blessed-virgin-mary: name.pl = "", want the preserved Polish name
  romanus missing: the calendarium's photographic scans both carry "Commemoratio S. Romani Mart." on 9 August
  missing "eusebius-confessor" (08-14)

internal/caldata/tridentine-calendar.ini regenerated from the ORIGINAL
branch-point data (`git show 2386a45:...`), not from this session's
own already-damaged intermediate file -- regenerating from an
already-corrupted source would have preserved nothing, since the
preservation mechanism can only preserve what is actually on disk
when it runs. Verified directly (not merely re-tested): all 322
name.en/name.pl values byte-identical to the branch point; 15 rank
fields and 2 class fields differ (the round-1 Lenten-rank and
class-tag fixes, unchanged by this round); 5 new slugs added
(agnes-secundo, boniface-martyr, eusebius-confessor, evaristus,
theodore); 0 slugs removed.
</content>
</entry>
<entry>
<title>calendar, precedence_ef: two more RG 91 gaps exposed by defect 4</title>
<updated>2026-08-12T11:46:01Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T11:46:01Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=b4d44c88fe3c92c5fb06b43fe94be0049059ef6e'/>
<id>urn:sha1:b4d44c88fe3c92c5fb06b43fe94be0049059ef6e</id>
<content type='text'>
Found during the mandated 2005-2050 before/after verification (not
one of the seven, but caused by defect 4's own fix, so fixed in the
same pass rather than left as a self-introduced regression). Neither
is a hypothetical: both are live in the fixed calendar and both were
individually confirmed via cmd/lectio-ef-dump before being written up
as tests.

1. RG 91 entry 4 (Immaculate Conception, Assumption BVM) sits ABOVE
   entry 6 (Sundays of Advent/Lent/Passiontide) -- unlike an ORDINARY
   I-class feast (entry 11, e.g. St Joseph), the Immaculate Conception
   (8 December) is not impeded by an Advent Sunday at all. Before
   defect 4, Advent Sundays were wrongly II class, so this was
   accidentally right (I beats II outright, no tie reached); once
   Sundays became I class the tie-break mattered for the first time,
   and precedenceEF had no branch for it -- the Sunday wrongly won.

2. RG 91 entry 5 (Vigil &amp; Octave day of the Nativity) sits above entry
   6 the same way, and its own gap was worse than a wrong winner: the
   Vigil of Christmas (24 December) falling on Advent IV, once
   defect 4 made that a genuine I-class tie, sent the Vigil into
   transferIfImpededEF's forward walk -- which has no way to re-place
   a transfer crossing the Dec 31/Jan 1 boundary (celebrationDate
   re-resolves a fixed date using the YEAR OF THE DAY BEING QUERIED,
   so a walk landing in the following January can never match the
   query that produced it). The Vigil did not move to the wrong day;
   it vanished for the whole year, for every year 24 December is a
   Sunday (2006, 2017, 2023, 2028, 2034, 2045).

Both fixed the same way as the existing II-class-feast-of-the-Lord
bonus in precedenceEF (a one-line precedence adjustment keyed on
slug), generalised into a single beatsClass1Sunday helper covering
both RG 91 entries.

A separate, unrelated bug surfaced by the SAME verification pass and
fixed alongside it: transferIfImpededEF's destination check reused
precedenceEF's tie-break BAND to decide "is this day I or II class",
but band encodes a different question (which of two EQUAL-class
candidates wins a tie) -- an ordinary, non-Sunday II-class temporal
candidate YIELDS under defect 2's own fix (band 5), even though it is
genuinely II class. A day within the Octave of the Nativity (26-31
Dec, RG 67) is exactly such a day, so band&lt;=3 alone let a transfer
wrongly land inside it (a real reproduction: "vigil-of-christmas"
would have landed on 29 December 2006 instead of vanishing outright,
caught while tracing the entry-5 bug above). Replaced with a direct
class test (isHighClass), which is both correct and simpler -- it no
longer needs the Sunday flag at all for this particular check.

Witnesses (precedence_ef_repro_test.go): TestImmaculateConceptionBeatsAdventSunday,
TestVigilOfChristmasSurvivesAdventSunday. Fail before this commit with:
  2013-12-08 observed = "ef-advent-sunday-2" want immaculate-conception-of-the-blessed-virgin-mary (RG 91 entry 4 beats entry 6)
  2006-12-24 observed = "ef-advent-sunday-4" want vigil-of-christmas (RG 91 entry 5 beats entry 6; must not vanish)
(full set: 2013/2019/2024 for the first, 2006/2017/2023/2028 for the second)
</content>
</entry>
<entry>
<title>test(ef): un-gate the oracle test now the seven defects are fixed</title>
<updated>2026-08-12T11:06:47Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T11:06:47Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=4722236b26d3439ed56893cb2863121bb705c7cf'/>
<id>urn:sha1:4722236b26d3439ed56893cb2863121bb705c7cf</id>
<content type='text'>
Remove the LECTIO_EF_ORACLE_STRICT gate added when the strengthened
rank/colour assertions first landed. All seven defects are fixed as
of the previous four commits; TestOracleEF now passes unconditionally
as part of the normal go test ./... run, with its small, cited
allow-list (four entries, none of them one of the seven) doing the
only remaining filtering.
</content>
</entry>
<entry>
<title>precedence_ef: a II-class privileged feria yields to a feast (defect 2)</title>
<updated>2026-08-12T11:06:18Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T11:06:18Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=61a2d658fea1c9a1640cb54bb203a8441bbb17a9'/>
<id>urn:sha1:61a2d658fea1c9a1640cb54bb203a8441bbb17a9</id>
<content type='text'>
precedenceEF's equal-class tie-break only distinguished "ordinary
III/IV-class feria yields" from "everything else wins" -- Sundays,
named feasts, Lent/Passiontide ferias, AND II-class privileged ferias
(the Ember days, the late-Advent 17-23 Dec ferias) were all bucketed
into the same "wins its tie" branch. RG 91 disagrees at class 2:
entry 15 (Sundays) sits ABOVE entry 16 (II-class feasts of the
universal Church), so a Sunday wins -- but entry 16 sits ABOVE entry
18 (II-class ferias, including the Ember days), so those FERIAS
yield instead, the opposite direction from a Sunday. St Matthew (21
September, II class) was losing to the September Ember Wednesday
every time the two coincided; St Thomas (21 December, II class) was
losing to an ordinary late-Advent feria the same way once the
previous commit correctly promoted those ferias to II class.

The fix distinguishes a II-class Sunday from a II-class feria using a
Sunday flag that already existed on `candidate` (used by the OF path)
but was never wired up for EF: temporal_ef.go's efCel always set
Sunday: false, even on an actual Sunday. A new efSunday helper (efCel
plus the flag) replaces the three efCel calls inside temporalEF's
Sunday branch, and computeEF now propagates td.Sunday into the day's
temporal candidate.

precedence_ef_test.go's own pre-existing witness ("at equal class, the
temporal office wins") encoded exactly the bug: a bare class-2
temporal candidate with no Sunday/season information, standing in for
"the temporal office" in general. It is rewritten into two explicit
cases (Sunday wins its tie; a privileged feria yields) plus the
existing Lent/Passiontide-vs-ordinary III/IV-class case restated
explicitly rather than left implicit.

Witness (precedence_ef_repro_test.go): TestMatthewBeatsSeptemberEmberWednesday.
Fails before this commit with:
  2016-09-21 observed = "ef-september-ember-wed" want matthew (RG 91
    entry 16 beats entry 18)
  2022-09-21 observed = "ef-september-ember-wed" want matthew (RG 91
    entry 16 beats entry 18)

With this commit, all seven named defects are fixed:
LECTIO_EF_ORACLE_STRICT=1 go test ./internal/calendar/... -run TestOracleEF
passes (0 unallow-listed rank/colour mismatches over 730 days). The
gate stays in place for this commit; a following commit removes it.
</content>
</entry>
<entry>
<title>calendar: RG 96 transfers must skip II-class days too (defect 1)</title>
<updated>2026-08-12T11:05:34Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T11:05:34Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=00a32e549493b0fb51ae23e8a5e73aa54a5205b1'/>
<id>urn:sha1:00a32e549493b0fb51ae23e8a5e73aa54a5205b1</id>
<content type='text'>
transferIfImpededEF's forward walk only skipped days whose temporal
office was I class. RG 96 requires skipping to "the next following
day that is not I or II class" -- II class also blocks. 2011: the
Sacred Heart (Friday after the Corpus Christi octave) falls on 1 July
and impedes the Precious Blood, also fixed on 1 July. The walk landed
the Precious Blood on 2 July, displacing the Visitation (II class,
fixed) outright, and never reached 3 July (an ordinary II-class
Sunday) at all.

Two changes were needed together, not one:

1. The walk's continuation threshold widens from "temporal band &lt;= 2"
   to "&lt;= 3", which is what actually captures every II-class temporal
   day (an ordinary Sunday, or a II-class named feast) as well as
   every I-class one -- band 3 is precedenceEF's own value for any
   non-Sunday-privileged II-class temporal candidate, unchanged by
   this commit.

2. A FIXED sanctoral II-class feast (the Visitation) has no temporal
   band at all -- the walk needs to also check whether some OTHER
   fixed celebration, class 1 or 2, already resolves onto the
   candidate day. computeEF now builds this check once (occupiedByRank,
   parameterised by which ranks count) and passes it in.

Widening (1) alone is wrong on its own: a class-1 feast is NEVER
actually impeded by a mere II-class day (I class always outranks II
class outright, no tie exists) -- naively applying the wide "&lt;=3"
threshold to decide whether the ORIGINAL date is impeded, not just
where to land afterwards, wrongly bumped unimpeded feasts landing on
an ordinary Sunday (caught while testing this: All Saints, 1 Nov 2026,
a Sunday that year, was wrongly pushed to 3 Nov). transferIfImpededEF
now uses two different thresholds for two different questions -- class
1 only to decide IF a candidate is impeded at all, class 1 OR 2 to
decide where an already-impeded one may land -- see its own doc
comment for the full reasoning.

Witness (precedence_ef_repro_test.go): TestTransferSkipsBothIAndIIClass.
Fails before this commit with:
  2011-07-02 observed = "precious-blood-of-our-lord-jesus-christ" want
    visitation-of-the-blessed-virgin-mary (RG 96: the Precious Blood
    must skip past it, not displace it)
  2011-07-04 observed = "ef-time-after-pentecost-3-monday" want
    precious-blood-of-our-lord-jesus-christ (RG 96: first day that is
    neither I nor II class)
</content>
</entry>
<entry>
<title>temporal_ef: Sunday ranks, Rose Sundays, Holy Thursday white</title>
<updated>2026-08-12T11:04:53Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T11:04:53Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=f40eb498c612aeda2ff7f3d5b898e4d1ddcec352'/>
<id>urn:sha1:f40eb498c612aeda2ff7f3d5b898e4d1ddcec352</id>
<content type='text'>
Four fixes to internal/calendar/temporal_ef.go, all found by the
strengthened oracle test (previous commit):

1. Sunday ranks (defect 4). The generic Sunday branch assigned
   class-2 to every Sunday except Advent I. RG 11-12 / RG 91 entry 6:
   every Sunday of Advent and every Sunday of Lent is I class (as are
   Passiontide's own two Sundays and Low Sunday, already correct via
   their named-feast cases). Fixes St Joseph wrongly taking a Sunday
   of Lent (defect 3, precedence_ef_repro_test.go's
   TestJosephYieldsToSundayOfLent) as a direct consequence: once Lent
   Sundays are I class, Joseph (also I class) no longer wins the tie
   outright and correctly transfers to the 20th via the existing RG
   96 walk -- no separate code change was needed for defect 3.

2. Rose (defect 5). efColour had no Rose case at all; Gaudete (Advent
   III) and Laetare (Lent IV) now get Rose on that Sunday specifically
   (RG 131: rose vestments may be used "in Officio et Missa diei
   dominici tantum", for that Sunday's Office and Mass only), not the
   surrounding Sundays.

3. Holy Thursday's colour (defect 6). RG 128(b) names the Missa in
   Cena Domini as a whole-Mass exception to Passiontide's violet; RG
   122 states the same fact affirmatively, in the White section
   itself. Good Friday and Holy Saturday, either side, are unchanged
   (still violet -- their own black/no-colour treatment is a separate,
   unmodelled gap, noted in precedence_ef.go's own doc comments).

4. Beyond the seven, found by the same strengthened test and fixed for
   the same RG 91 entry 18 reason defect 2 (next commit) relies on:
   the Ember days of Lent had no case in efEmberSlug at all (only
   September and Advent did), so they fell through to the ordinary
   III-class Lenten-feria rank instead of the II class RG 91 entry 18
   requires. The late-Advent ferias (17-23 Dec, RG 91 entry 18) and
   the days within the Octave of the Nativity (26-31 Dec, RG 67-68)
   had no elevation at all, defaulting to III/IV class. All three are
   one-line, unambiguous, primary-cited additions to the same rank
   logic already being touched here -- left unfixed, the strengthened
   oracle test could only reach green by allow-listing them as if they
   were defensible divergences, which they are not.

Witnesses (temporal_ef_test.go): TestTemporalEFSundayRanks,
TestTemporalEFRoseSundays, TestTemporalEFHolyThursdayColour,
TestTemporalEFEmberDayRanks. All fail before this commit; see the
report for the exact pre-fix failure messages.
</content>
</entry>
<entry>
<title>test(ef): strengthen the oracle test to assert rank and colour</title>
<updated>2026-08-12T11:03:57Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T11:03:57Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=ca3403893bfbebb325fe3ab6a98081640574bf2a'/>
<id>urn:sha1:ca3403893bfbebb325fe3ab6a98081640574bf2a</id>
<content type='text'>
internal/calendar/oracle_ef_test.go asserted Season only. lectio's own
EF oracle test comment said as much ("rank/colour are reported
informationally"), which is exactly why several precedence/colour
defects in precedence_ef.go and temporal_ef.go shipped without ever
failing a test: the suite was green while the observed office's own
rank and liturgical colour could be wrong.

Rebuild the oracle from the committed missalemeum snapshot
(sources/snapshot.tar.gz, missalemeum/en/YYYY-MM-DD.json, 2026-01-01
.. 2027-12-31, 730 days) instead of a live 2025-2026 fetch, via a
rewritten scripts/build-oracle-ef.sh -- offline, reproducible, and
correctly separating info.rank/info.colors from info.id (whose
embedded rank is the rank of the propers REUSED that day, not the
day's own rank -- e.g. 2026-01-02 is a class-4 feria carrying id
"sancti:01-01:1:w" because it reuses the Circumcision's propers).
info.colors is an array (14 of 730 days carry two values -- Gaudete/
Laetare "pv", Palm Sunday "rv", Good Friday "bv", Holy Saturday
"vw"), so the new Colour assertion is membership, not equality.

The strengthened assertions immediately expose several real defects
(rank mismatches on every Advent/Lent Sunday, the Ember days, the
late-Advent and Christmas-octave ferias, and more) -- that is the
point, this is the regression net subsequent commits fix against.
Since the repo's convention is go test ./... green at every commit,
TestOracleEF is gated behind LECTIO_EF_ORACLE_STRICT=1 for now rather
than landed red; a later commit removes the gate once the fixes are
in. Season alone stays green throughout (unchanged, always was).

A small, cited allow-list (efAllowList) is included from this commit:
genuine, defensible divergences unrelated to the fixes ahead of it --
RG 91 entry 27's un-built BVM Saturday Office, the pre-existing 6-13
January Christmastide/time-after-Epiphany season-boundary divergence,
missalemeum's own RG 33 gap on a Sunday 9 August, and one collision
(St Joseph vs the Friday of Passion Week, 2027) left explicitly
unresolved even by the sibling project's much deeper primary-source
pass. None of the four is one of the seven defects this branch fixes.
</content>
</entry>
<entry>
<title>calendar/readings: report Sunday as its own display rank, not solemnity</title>
<updated>2026-08-05T20:24:53Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-05T20:24:53Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=4855ef2a667b7ea71092e0582db5aff1838a0d63'/>
<id>urn:sha1:4855ef2a667b7ea71092e0582db5aff1838a0d63</id>
<content type='text'>
The Ordinary Form's Table of Liturgical Days treats Sunday as its own
category, never a solemnity. temporal.go's sundayDay() already marks these
days distinctly from named solemnities (Class stays unset, unlike solemn()'s
ClassLord); internal/readings/offline.go now reads that existing signal to
relabel the REPORTED rank to "sunday" for ordinary and privileged-season
Sundays alike, leaving Celebration.Rank, ofRankOrder and all precedence
untouched. Named solemnities landing on a Sunday (Easter, Pentecost, ...)
and feasts of the Lord (Holy Family) keep reporting their own rank. The 1962
form is untouched.

Added calendar.RankSunday (display-only, deliberately excluded from
ofRankOrder), the i18n Sunday/niedziela words, and a test pinning the exact
dates from the original bug report.
</content>
</entry>
</feed>
