<feed xmlns='http://www.w3.org/2005/Atom'>
<title>lectio.git, branch v0.46.1</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.1</id>
<link rel='self' href='https://git.labunix.xyz/lectio.git/atom?h=v0.46.1'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/'/>
<updated>2026-08-17T08:42:22Z</updated>
<entry>
<title>release: v0.46.1</title>
<updated>2026-08-17T08:42:22Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T08:42:22Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=b8099147a8e02d4b1eedb505db4f349ca5db91fb'/>
<id>urn:sha1:b8099147a8e02d4b1eedb505db4f349ca5db91fb</id>
<content type='text'>
</content>
</entry>
<entry>
<title>changelog: 0.46.1</title>
<updated>2026-08-17T08:42:02Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T08:42:02Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=4b6a0c1d534505cfbfe6a569893ec795d175129d'/>
<id>urn:sha1:4b6a0c1d534505cfbfe6a569893ec795d175129d</id>
<content type='text'>
</content>
</entry>
<entry>
<title>caldata: the Lenten Ember days were serving Lent I Sunday's Mass</title>
<updated>2026-08-17T08:05:55Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-17T08:05:55Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=dde760c31c6e8cffa84446b0804ab6d6372ccb30'/>
<id>urn:sha1:dde760c31c6e8cffa84446b0804ab6d6372ccb30</id>
<content type='text'>
Three lectionary sections were keyed ef-lent-1-{wednesday,friday,saturday}
while temporal_ef.go's efEmberSlug computes ef-lent-ember-{wed,fri,sat}. The
lookup in caldata.Readings takes the observed slug and has no alias table, so
it missed the entries entirely and fell through to the preceding-Sunday
fallback. Every Lenten Ember day since the data was added has served Lent I
Sunday's Mass -- three days a year, in a season that prints a proper Mass daily.

The values were already right; only the keys were wrong, and they were stale
rather than mistaken: they predate Lent being added to efEmberSlug, and
scripts/genlect.go keys off day.Observed.Slug, so re-running it would already
write the correct names. Advent and September were never affected -- both
already use the -ember- form.

Renamed, and verified the whole file: every one of the 119 section names is now
a slug the calendar actually computes, checked by sweeping 2005-2050. Those
three were the only dead keys.

Added TestEFLectionaryKeysAreReachableSlugs to make the class detectable rather
than just this instance. Mutation-tested: reverting the three keys fails it,
naming all three.

Found by differencing against colitur, the sibling OCaml engine, while giving
it a lectionary of its own. Worth recording how nearly it escaped: colitur
inherited the same wrong keys from this file during its bootstrap, so both
engines produced the same wrong Mass and the differential between them was
silent. It only surfaced when colitur's data was checked against the Missal
itself. Two implementations agreeing is not evidence when one was seeded from
the other.
</content>
</entry>
<entry>
<title>lectio-ef-dump: emit the Epistle and Gospel citations</title>
<updated>2026-08-15T00:07:29Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-15T00:07:29Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=3ad70f087f30075e6414d85195a5ca037e14f627'/>
<id>urn:sha1:3ad70f087f30075e6414d85195a5ca037e14f627</id>
<content type='text'>
colitur's differential compares reading citations from this release onward,
and needs them per day rather than per lectionary key -- this engine resolves
a feria to the preceding Sunday's Mass itself, which is exactly the behaviour
the differential has to check.
</content>
</entry>
<entry>
<title>NOTICE: the Wujek corpus is public domain</title>
<updated>2026-08-14T11:41:57Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T11:41:57Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=70125430599dce372dad248350df2de740255770'/>
<id>urn:sha1:70125430599dce372dad248350df2de740255770</id>
<content type='text'>
Drops the copyright caveat on the ~300 deuterocanonical verses sourced from
the 1962 edition, and the redistribution restriction that followed from it,
on the author's ruling. The source edition stays recorded as provenance so
the corpus can still be re-derived or checked.

The SBLGNT attribution is untouched: CC BY 4.0 requires it of anyone
redistributing the text, which a fullbible binary does.
</content>
</entry>
<entry>
<title>release: v0.46.0</title>
<updated>2026-08-14T11:26:32Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T11:26:32Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=051b4b8c7859f64b3fad8c343924d7c353945ec2'/>
<id>urn:sha1:051b4b8c7859f64b3fad8c343924d7c353945ec2</id>
<content type='text'>
</content>
</entry>
<entry>
<title>changelog: 0.46.0</title>
<updated>2026-08-14T11:26:21Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T11:26:21Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=726cd708962d798fb09e4994a5bf7e7bbf0a6cc7'/>
<id>urn:sha1:726cd708962d798fb09e4994a5bf7e7bbf0a6cc7</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Merge branch 'polish-ui-and-calendar': the gomobile facade and the EF calendar fixes</title>
<updated>2026-08-14T11:22:16Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-14T11:22:16Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=913974b10a993af251b25125d1a417c452ad785c'/>
<id>urn:sha1:913974b10a993af251b25125d1a417c452ad785c</id>
<content type='text'>
Two bodies of work that shared a branch.

The gomobile facade (2026-08-03..05): mobile.PartLabels, Days, and the
observed rank on DayInfo, so dlectio stops hardcoding part IDs and rank
strings; the 1962 part labels become i18n data; the documented gomobile
bind command is corrected so it reproduces the shipped .aar.

The EF calendar fixes (2026-08-12): seven defects found by differencing
this engine against colitur, a second 1962 implementation built from the
Missal's General Rubrics rather than from this codebase. RG 96 transfers
were not skipping II-class days; a II-class privileged feria was not
yielding to a feast; Sunday ranks, the two Rose Sundays and Holy Thursday's
colour were wrong; and scripts/gen-sanctoral-ef inferred ranks, deduped
and tagged classes wrongly, which put 15 III-class feasts into the shipped
tridentine-calendar.ini as bare commemorations and dropped four entries
outright.

Holy Thursday was violet in both engines, which is how a shared lineage
hides a defect: this project's ini is generated from missalemeum and
colitur's data was bootstrapped from here, so an error inherited by both
is invisible to a differential. It took the Missal itself to see it.

The EF oracle test now asserts rank and colour, not season alone. One
known gap is recorded in the source rather than fixed, as out of scope:
RG 95 chained transfers (calendar.go).
</content>
</entry>
<entry>
<title>Merge branch 'fix/ef-precedence-defects': seven EF calendar defects</title>
<updated>2026-08-12T15:15:03Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T15:15:03Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=3b32c002d3eddda5ece9422442717657b9fee63b'/>
<id>urn:sha1:3b32c002d3eddda5ece9422442717657b9fee63b</id>
<content type='text'>
Fixes seven defects in the EF calendar, each found by differential and
oracle comparison against an independently-written engine and each
backed by a cited paragraph of the Rubricae Generales verified against
the 1962 Missal:

  RG 96  transfers must skip II-class days (the Precious Blood was
         landing on the Visitation)
  RG 91  a II-class privileged feria yields to an equal-class feast
         (St Matthew was losing to the September Ember Wednesday)
  RG 11  all Sundays of Advent, Lent and Passiontide are I class
         (only Advent I was), which also settles St Joseph on a Lent
         Sunday
  RG 131 Rose on Gaudete and Laetare, which the EF path never emitted
  RG 122 Holy Thursday is white

and the sanctoral generator itself, whose rank inference had tagged 15
III-class feasts as commemorations, dropped four entries to slug
collisions, and mis-tagged three class fields.

The EF oracle test asserted Season only, which is why none of this ever
failed. It now asserts rank and colour, with a cited allow-list.

Two commemorations had been deleted on a primary-source claim the
primary source contradicts: the Archivum Liturgicum transcription
silently drops commemoration lines where the photographic scans carry
them. Six of the seven affected dates are now present; the seventh
(25 December) is blocked by an ingestion limit that reads only the
first of three Christmas Masses, recorded at its cause.

Known gap, recorded in source: RG 95/97/98 chained transfers, where two
I-class feasts translate to the same day.
</content>
</entry>
<entry>
<title>gen-sanctoral-ef, caldata: fix round 3 -- guard coverage, rank pins, name test, Anastasia</title>
<updated>2026-08-12T13:27:00Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-12T13:27:00Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=c655c525ef07deafb113a291489b396c81d7ce4a'/>
<id>urn:sha1:c655c525ef07deafb113a291489b396c81d7ce4a</id>
<content type='text'>
Second external re-review returned Spec pass on round 2 (all ten prior
findings addressed, C1/C2 fixed at the root, mechanism claims held
under mutation) and found two blocking items in the I3 guard itself,
plus three recommended hardenings. All verified independently before
fixing.

BLOCKING 1: refYearExplainsAbsence's own doc comment said the id-rank
exclusion covers "6-31 December"; the code implemented `Day() &gt;= 26`.
A typo (26 -&gt; 6), but the wrong kind to have on the one comment this
whole review chain exists to keep honest -- fixed as part of the
rewrite below, not left as an isolated one-character correction.

BLOCKING 2: the guard covered only 6 of the 13 MM-DD values round 1's
own temporal_ef.go changes actually made refYearExplainsAbsence
couple to. Measured, not just reasoned about: running the function's
body against the branch-point engine versus HEAD over the six
reference years flips its verdict on 50 dates across 12-17 through
12-23 (round 1's late-Advent promotion, RG 91 entry 18, a 140-day
change) AND 12-26 through 12-31 (the Nativity-octave promotion, RG
67/68, already guarded). The late-Advent half was unguarded.

No live bug today -- confirmed by regenerating: the ini is
BYTE-IDENTICAL before and after this fix. The only sanctoral entry in
17-23 December is `thomas` (21 December), reached via harvestDate's
`obs` (observed-office) path, never refYearExplainsAbsence's
commemoration-id-trust path at all. Widened the guard to 17-31
December anyway, on the side of the known-safe default
(RankCommemoration) rather than wait for the first real entry in that
range to repeat I3's exact failure shape. The two sub-ranges are NOT
the same strength of evidence, and the doc comment says so explicitly
now: 26-31 December rests on a positive RG 68(d)/(e) citation naming
Thomas Becket and Silvester directly as bare "Commemoratio, no
class"; 17-23 December is a precautionary exclusion with no equivalent
citation -- RG 91 entry 18 ranks the FERIA, not any commemoration
that might coincide with it, and (per defect 2's own finding) a
genuine class-2 feast there would actually WIN against the ferias's
own privilege, so "the day is class-2" does not reliably explain a
class-2 saint's absence here the way it does for the Nativity octave's
two named cases. Recorded as a real asymmetry, not smoothed over.

RECOMMENDED 3: rank = commemoration is now pinned for all four entries
this task's two review rounds touched -- romanus, eusebius-confessor
(C2), thomas-becket, silvester (I3) -- not just their presence and
date. `git grep` before this commit returned zero hits for
thomas-becket or silvester rank anywhere in *_test.go; a future
regeneration could have rewritten either back to class-4, the exact
I3 failure mode, with the suite green throughout.

RECOMMENDED 4: TestTridentineNamesPreservedAcrossRegeneration
rewritten on both axes the review found loose. It counted name.pl
only -- a hardcoded single language, the identical "whitelist of two"
mistake C1's own generator fix exists to stop repeating, just moved
into the test instead. Now DISCOVERS every name.&lt;lang&gt; key actually
present in the data (so a regeneration dropping name.la, or losing a
future name.de, is caught the same way as name.pl) and asserts the
discovered language set is exactly {en, pl} -- not just each count.
The &gt;= 315 floor had 7 entries of slack (the review proved 6 missing
Polish names still passed it); tightened to the exact, independently
verified true count (322), zero slack.

RECOMMENDED 5: the 25 December Anastasia gap and its cause are now
recorded, not just her absence. Two compounding, independently
checked causes: fetchOnce reads only `data[0]`, missalemeum's FIRST
of Christmas Day's three Masses, so a commemoration attached to a
second or third Mass (the calendarium's own "In secunda Missa:
Commemoratio S. Anastasiae Mart.") is structurally invisible to this
harvester for ANY date, not just this one -- but ALSO, checked live,
missalemeum's own "commemorations" list is empty on all three of the
date's records, not just the first, so a fetchOnce rewritten to merge
all of a date's Masses would still not recover her. Documented at
both fetchOnce's own definition and the PRIMARY-SOURCE NOTE, since
the two facts belong to different questions (a real code limitation
worth fixing someday vs. an upstream data gap this generator cannot
close at all).

Witnesses: TestTridentineCommemorationRanksPinned (new),
TestTridentineRomanusAndEusebiusPresent (extended with rank),
TestTridentineNamesPreservedAcrossRegeneration (rewritten). No pre-fix
failure to report for the two new/tightened tests specifically --
these are regression GUARDS against a bug class already fixed in
round 2, not fixes for a currently-red state; their value is in what
they would now catch, not what they catch today. internal/caldata/
tridentine-calendar.ini is NOT regenerated by this commit -- confirmed
byte-identical before and after re-running the generator, exactly as
"no live bug today" predicts.
</content>
</entry>
</feed>
