<feed xmlns='http://www.w3.org/2005/Atom'>
<title>lectio.git/internal/calendar/calendar.go, 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:50:58Z</updated>
<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>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>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>fix(EF): fill reading gaps (major feasts, feria-repeat-through-feast, sundays)</title>
<updated>2026-07-28T12:46:17Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-07-28T12:46:17Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=cf45e9f7f3146bca6039b63e2be02463b02f8043'/>
<id>urn:sha1:cf45e9f7f3146bca6039b63e2be02463b02f8043</id>
<content type='text'>
EF readings had ~1.8% of days with no readings (major feasts falling back to
the wrong Sunday, feria-repeats broken when the preceding Sunday was a feast).
Now 0 gaps over 9496 days (2025-2050); reading correctness spot-checks match
missalemeum except the resumed-Epiphany-Sunday edge (next commit).

- calendar.TemporalSlug: the green-season weekday-repeats-the-Sunday rule uses
  the Sunday's TEMPORAL slug, so a Monday still finds its Sunday Mass when that
  Sunday was displaced by a feast (e.g. the Purification on Feb 2).
- Add the missing EF temporal Masses (from missalemeum): the Nativity Day Mass
  (Heb 1:1-12 / John 1:1-14), Epiphany (Isa 60:1-6 / Matt 2:1-12), the Octave
  Day of Christmas (Titus 2:11-15 / Luke 2:21), the 6th Sunday after Epiphany
  (1 Thess 1:2-10 / Matt 13:31-35), and the last Sunday after Pentecost
  (Col 1:9-14 / Matt 24:15-35).
</content>
</entry>
<entry>
<title>fix(calendar): OF precedence/transfer + readings resolution; EF Pentecost octave</title>
<updated>2026-07-28T12:35:24Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-07-28T12:35:24Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=a80e61963756a28a3963a0442a8ccc1572518373'/>
<id>urn:sha1:a80e61963756a28a3963a0442a8ccc1572518373</id>
<content type='text'>
Fixes found by validating the offline engine per-day vs the LiturgicalCalendar
API (OF) and missalemeum (EF) across 2005-2050. OF calendar is now 0 real
errors in the forward window (season/cycle already perfect).

OF precedence/transfer (calendar):
- Ash Wednesday and Holy Week Mon-Wed are band-2 privileged, so a coinciding
  feast (Chair of St Peter on Ash Wednesday) is suppressed, not observed.
- Solemnities transfer out of Holy Week / the Easter octave: the Annunciation
  defers to the Monday after the 2nd Sunday of Easter; St Joseph is anticipated
  to the Saturday before Palm Sunday; the Nativity of St John the Baptist moves
  to Jun 23 when a Lord's solemnity (Sacred Heart / Corpus Christi) falls Jun 24.
- Within a precedence band, a solemnity of the Lord/BVM outranks a saint's
  (dignity tiebreak) rather than losing an alphabetical slug tie.
- Perpetua &amp; Felicity corrected optional -&gt; obligatory memorial.

OF readings resolution (bible.OFRef + lectionary data):
- Verse-accurate Hebrew-&gt;Vulgate psalm mapping incl. the split psalms
  (9/10, 114/115, 116, 147); "+" verse joins and abbreviated ranges ("127-28")
  normalized; single-chapter books (2/3 John, Jude) get chapter 1.
- Cleaned harvest artifacts from of-lectionary.ini (descriptive-suffix gospels,
  "or Year A" alternates, "*"/"[Vulg.]"/bracket markers, slash abbreviations);
  Joel/Malachi/Zechariah/Esther book-versification citations fixed to Vulgate.
- Split a merged Ps 15:10/11 row in vul.tsv. Result: 0 unresolvable OF readings
  over 2557 rendered days (cycles A/B/C, varied Easters).

EF: the Octave of Pentecost (Whit Monday-Saturday) is red, not white.
</content>
</entry>
<entry>
<title>feat(of): proper readings for the movable Marian memorials</title>
<updated>2026-07-28T08:47:48Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-07-28T08:47:48Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=98fe454868ffff3f52396e095b5cd5f1251f1fd2'/>
<id>urn:sha1:98fe454868ffff3f52396e095b5cd5f1251f1fd2</id>
<content type='text'>
Mary, Mother of the Church and the Immaculate Heart of Mary are computed in the
engine (no fixed-date INI entry), so they fell back to the ferial. Attach their
proper Masses inline: Mary MotC = Gen 3:9-15,20 / Ps 87 / John 19:25-34;
Immaculate Heart = Isa 61:9-11 / 1 Sam 2 canticle / Luke 2:41-51. Verified they
render when observed (Immaculate Heart 2029-06-09). Extends TestOFMovableMemorials.
</content>
</entry>
<entry>
<title>feat: complete OF+EF calendar coverage (movable feasts, vigils, ember days, transfers)</title>
<updated>2026-07-28T06:49:57Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-07-28T06:49:57Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=70b805018f0ae0d8424c3c7de8f1169476385a35'/>
<id>urn:sha1:70b805018f0ae0d8424c3c7de8f1169476385a35</id>
<content type='text'>
Ordinary Form:
- Add the movable Marian memorials that have no fixed date: Mary, Mother of the
  Church (Monday after Pentecost) and the Immaculate Heart (Saturday after the
  Sacred Heart), computed in computeOF.
- General Norms 60: two coinciding obligatory memorials both become optional and
  the ferial is observed -- except Mary, Mother of the Church, which keeps
  precedence per its 2018 decree.

Extraordinary Form:
- Capture fixed-date vigils in the sanctoral harvest (Christmas, the Nativity of
  St John the Baptist, Sts Peter &amp; Paul, St Lawrence, the Assumption, All Saints,
  the Immaculate Conception) -- previously filtered out.
- temporalEF: the movable vigils of the Ascension (I class eve) and Pentecost
  (Whitsun Eve), and the September/Advent Ember days (II class violet ferias).
- transferIfImpededEF: the Annunciation transfers past Holy Week/the Easter
  octave to the Monday after Low Sunday; All Souls moves to Nov 3 when Nov 2 is a
  Sunday.
- genlect harvests proper Masses for the new Ember/vigil days.

Adds TestEFCoverage + TestOFMovableMemorials. Bumps to 0.39.0.

Verified per-day: OF 0 real errors vs calapi (2026-2028, 100% correct-observed);
EF 0 real errors vs missalemeum (2025-2027), residual = deep-tail vigil-occurrence
and St Joseph Passiontide-transfer edges (~1-2 days/yr, documented).
</content>
</entry>
<entry>
<title>feat(calendar): Compute branches on Form (computeEF via temporalEF/precedenceEF)</title>
<updated>2026-07-27T12:00:01Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-07-27T12:00:01Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=58b748340059a02e696f6a7168f81114ac0f99e9'/>
<id>urn:sha1:58b748340059a02e696f6a7168f81114ac0f99e9</id>
<content type='text'>
</content>
</entry>
<entry>
<title>refactor(calendar): Rank int enum -&gt; unified string token (OF unchanged, oracle 0 mismatches)</title>
<updated>2026-07-27T11:54:19Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-07-27T11:54:19Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=5d96dd46ae8ed6b4f4cae6a0dd771a33cdc3a317'/>
<id>urn:sha1:5d96dd46ae8ed6b4f4cae6a0dd771a33cdc3a317</id>
<content type='text'>
Adds EF rank constants (class-1..4, commemoration); ofRankOrder() for the two
ordered comparisons; buildCelebration defaults missing rank to ferial.
</content>
</entry>
<entry>
<title>fix(ini,calendar): full-line-only comments (preserve ';' in citations); drop superseded ferial from Others</title>
<updated>2026-07-27T10:58:31Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-07-27T10:58:31Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=27911b8f2574563ddd5d0de75f708503067069c9'/>
<id>urn:sha1:27911b8f2574563ddd5d0de75f708503067069c9</id>
<content type='text'>
</content>
</entry>
</feed>
