<feed xmlns='http://www.w3.org/2005/Atom'>
<title>lectio.git, branch main</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=main</id>
<link rel='self' href='https://git.labunix.xyz/lectio.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/'/>
<updated>2026-09-03T19:13:45Z</updated>
<entry>
<title>Merge branch 'fix-of-lectionary-year-ii'</title>
<updated>2026-09-03T19:13:45Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-09-03T19:13:45Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=d12602184b63c84412d796806e9c2bac0919744b'/>
<id>urn:sha1:d12602184b63c84412d796806e9c2bac0919744b</id>
<content type='text'>
Ten corrupt OF reading references, every one in a Year II entry, found by a
downstream project comparing this data against a second lineage.
</content>
</entry>
<entry>
<title>fix(caldata): ten corrupt OF reading references, all Year II</title>
<updated>2026-09-02T10:32:33Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-09-02T10:32:33Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=a8c83aad5849a1ae948dde2ad217463d9ff89c77'/>
<id>urn:sha1:a8c83aad5849a1ae948dde2ad217463d9ff89c77</id>
<content type='text'>
Nine end at verse 22 where the OLM ends them at 20; the tenth reads
"Matthew 17:9a,10-135", a verse Matthew 17 does not have. Every one is in a
Year II entry, or in advent-2-sat, which has no year cycle. Not one Year I
entry is affected -- that distribution is what makes this a transcription
fault rather than ten independent slips.

  ordinary-1-mon-II     Mark 1:14-22          -&gt; Mark 1:14-20
  ordinary-3-wed-II     Mark 4:1-22           -&gt; Mark 4:1-20
  ordinary-4-mon-II     Mark 5:1-22           -&gt; Mark 5:1-20
  ordinary-12-wed-II    Matthew 7:15-22       -&gt; Matthew 7:15-20
  ordinary-18-sat-II    Matthew 17:14-22      -&gt; Matthew 17:14-20
  ordinary-19-wed-II    Matthew 18:15-22      -&gt; Matthew 18:15-20
  ordinary-1-tue-II     1 Samuel 1:9-22       -&gt; 1 Samuel 1:9-20
  ordinary-1-wed-II     1 Samuel 3:1-10,19-22 -&gt; 1 Samuel 3:1-10,19-20
  ordinary-7-sat-II     James 5:13-22         -&gt; James 5:13-20
  advent-2-sat (x2)     Matthew 17:9a,10-135  -&gt; Matthew 17:9a,10-13

Eight are confirmed verbatim against the Latin OLM 1981: "Mc 1, 14-20",
"Mc 4, 1-20", "Mc 5, 1-20", "Mt 7, 15-20", "Mt 17, 14-20", "Mt 18, 15-20",
"1 Sam 1, 9-20", "1 Sam 3, 1-10. 19-20", "Mt 17, 10-13". The two the OCR does
not yield are impossible on their face: James ends at 5:20, and Matthew 17 has
twenty-seven verses. litcal independently gives the corrected form for six of
the ten.

Found by two methods, neither sufficient alone. In Ordinary Time the OF
weekday Gospel does not depend on the year of the cycle -- OLM n. 69 point 4
alternates the FIRST reading only -- so a -I/-II pair whose gospel differs is
a defect by construction; that catches six. The other four are First readings
and the Advent entry, which no such symmetry constrains, and they were caught
by comparing against litcal.

Found while building a readings-comparison layer in colitur, whose OF
lectionary is generated from this file and had inherited all ten.
</content>
</entry>
<entry>
<title>merge: make the calendar engine stop repeating whole-year work per day</title>
<updated>2026-08-25T08:45:28Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-25T08:45:28Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=f110c338718a6eea3693fb6afb4f7fcc5b77003b'/>
<id>urn:sha1:f110c338718a6eea3693fb6afb4f7fcc5b77003b</id>
<content type='text'>
A seven-day view resolved the year seven times. Each readings.Load stacked
the calendar data layers and re-read the Bible book table -- both
date-independent -- and the EF path rebuilt the year's entire transfer plan
and its occupancy scan on every single day.

Three logic-neutral fixes: hoist the date-independent setup out of the Days
loop; memoise the EF transfer plan on (year, Selection, content hash of the
merged sanctoral); and build the occupancy index once alongside it rather
than scanning per candidate.

EF's seven-day view goes 74ms to 16ms, its multiple over OF from ~13x to
~3x. OF is unchanged, as it never touched the EF paths.

Output is byte-identical throughout, proven by SHA-256 over a 492-case
sweep spanning both forms, both languages, four corpora, the Triduum, a
Requiem day and the three Joseph/Annunciation collision years. The caches
are keyed on content, not identity, so a user overlay invalidates them --
asserted by a test that varies the overlay and requires the answer to
change, itself mutation-proved by dropping the content hash and watching it
fail.
</content>
</entry>
<entry>
<title>perf(calendar): precompute the EF occupancy index alongside the transfer plan</title>
<updated>2026-08-24T20:02:39Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-24T20:02:39Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=b24702cc9b8d7f2e408bb92032e8f7fa2aaa836b'/>
<id>urn:sha1:b24702cc9b8d7f2e408bb92032e8f7fa2aaa836b</id>
<content type='text'>
The prior commit (ea6e598) memoised efTransferPlan but left the SAME
occupiedByClass1/Or2 O(len(merged)) scan pattern in a second place:
transferIfImpededEF's own fallback path, called from computeEF once per
day for every class-1 candidate the (now cached) plan does not resolve
-- confirmed by CPU profile, not assumed: computeEF.func1 (the old
occupiedByRank closure) was ~62% of BenchmarkDays7EF's total time,
almost all of it inside buildCelebration, called from BOTH efTransferPlan
internally AND this second, uncached site.

Before optimising, established precisely what "occupied" depends on, per
the coordinator's warning that occupancy might genuinely mutate during
planning (efTransferPlan's own `claimed` map suggested as much). It does
not: occupiedByRank asks only "does some OTHER entry's ORIGINAL,
untransferred date (buildCelebration + celebrationDate, which never
considers a transfer) equal d" -- a pure function of (merged content,
year, sel) alone, identical to what the transfer-plan cache already
keys on. `claimed`, by contrast, genuinely mutates during one planning
pass (it tracks which TARGET days a transfer walk has already assigned)
and is NOT part of occupiedByRank's computation at all -- it remains
computed fresh inside efTransferPlan every call, untouched by this
change. These are independent, not the same thing wearing two names:
efTransferPlan's own forward-walk loop already checks both, plus a
third condition (the target day's own temporal class), as separate
disjuncts.

Given that, an occupancy INDEX -- not a second cache, and not a
"we already know the answer" shortcut derived from plan's absence (which
would have been correct for the transferIfImpededEF fallback's own
control flow ONLY by coincidence: it ignores the unconditional All Souls
Sunday-transfer special case that runs before the class-1 check on ANY
rank, so a shortcut skipping straight past it would misfire the moment a
user overlay retagged All Souls class-1, however unlikely on shipped
data) -- is the safe fix: buildEFOccupancyIndex does the same
merged-scan ONCE, into date -&gt; []{slug, rank}, and .occupied does the
exact O(1)-ish lookup + tiny-list filter occupiedByRank always computed,
just precomputed. transferIfImpededEF's own signature, control flow and
All Souls handling are completely unchanged; only what its two closure
parameters read from changed.

The index shares the transfer-plan cache's existing key (year, Selection,
SHA-256 of merged) rather than adding a new one -- both are pure in
exactly those three inputs, built in the same pass, so one key correctly
covers both. Only the plan is copied per call (clonePlan); the index,
which can hold one entry per merged slug (~330 on shipped data), is
returned uncopied and documented immutable-after-construction -- safe
under Go's concurrent-read guarantee since nothing anywhere writes to a
returned index.

New TestEFOccupancyIndexDetectsSameDateClass1Collision covers a path
no existing test reached: two class-1 SANCTORAL entries sharing one
ORIGINAL date (St Joseph/the Annunciation, covered by the prior commit's
tests, collide via HOLY WEEK's temporal precedence on DIFFERENT dates,
never with each other). A synthetic overlay (Compute's own public API,
same style as the existing tests) puts two class-1 entries on the same
otherwise-ordinary date: alone, either is simply observed; both
together, RG 97/98 transfer both forward and the shared date reverts to
its temporal office. Mutation-proved: dropping the index's exceptSlug
self-exclusion (reverted after) made the test fail immediately -- every
class-1 entry saw itself in the index and wrongly self-impeded, even the
single-entry case. TestEFTransferPlanCacheConcurrentUse gained a third,
disjoint key exercising this same collision path from goroutines
alongside the two existing ones; `go test -race` on the whole package is
clean.

Benchmarked (interleaved before/after, same method throughout this
branch): BenchmarkDays7EF drops from ~46-48ms (the prior commit's own
plan-cache-only state) to ~15-18ms/op (allocs 208639 -&gt; 98727, -53%;
bytes 16.1MB -&gt; 4.2MB, -74%) -- roughly a further 3x, ~4.6x cumulative
against the original ~74ms. BenchmarkDaysWeek (OF, which never touches
any of this) is unaffected: ~4.9-5.9ms/op both before and after, with
byte-for-byte identical allocs/bytes in every run -- the ms-level
wobble is machine noise, not a regression.

A fresh CPU profile confirms the new remaining bottleneck precisely:
writeSortedFields/hashMergedForPlan (the cache key's own SHA-256 of
merged, ~330 entries) is now ~35% of total time, because it still runs
on EVERY day (7x/week) to know whether a call is a cache hit, even
though the work it gates now mostly isn't. Not fixed here: hoisting the
key computation itself up to mobile.Days's batch level (mirroring the
first commit on this branch, b6ee8f0) would need Compute's public
signature to accept a precomputed key, a bigger surface change than this
task's scope, reported rather than taken unilaterally.

Output identity re-verified: the same 492-case sweep (both forms, both
UI languages, all four corpora, the leap day/Triduum/Requiem/season-
boundary dates, and the three Joseph/Annunciation years) is
byte-identical (SHA-256-equal) before and after -- the same SHA-256 as
the prior commit's own sweep, confirming zero output drift across the
whole chain. go test ./... and make ci (both build tags,
oracle/differential suite included) are green; go test -race on the
whole internal/calendar package is clean.
</content>
</entry>
<entry>
<title>perf(calendar): memoise the EF transfer plan across a shared calendar</title>
<updated>2026-08-24T19:42:48Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-24T19:42:48Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=ea6e59862dbdb607b9bcb221212a85ee3e4bd84a'/>
<id>urn:sha1:ea6e59862dbdb607b9bcb221212a85ee3e4bd84a</id>
<content type='text'>
computeEF calls efTransferPlan once per day, but the plan is pure in
(year, the merged sanctoral content, Selection) and identical for every
day sharing those three -- e.g. every date in one mobile.Days week.
Rebuilding it per day was a real cost: efTransferPlan walks every
merged entry looking for class-1 candidates, and for each one it
considers, occupiedByClass1/Or2 (an occurrence check it also uses)
walks merged AGAIN -- confirmed by CPU profile, not just by reading the
code (github.com/lukaszkasprzak/lectio/internal/calendar.computeEF.func1,
the occupiedByRank closure, at ~62% of BenchmarkDays7EF's total time
before this fix, almost all of it inside buildCelebration).

efTransferPlanCached (transfer_plan_cache.go) wraps efTransferPlan with
a small, bounded, thread-safe LRU (container/list + sync.Mutex, capped
at 64 entries -- gomobile may call in from multiple goroutines, and an
unbounded map keyed by year would grow as a user scrolls through
decades). The cache key is (year, Selection, a SHA-256 of merged's full
content): merged is a map, so it cannot be a map key field itself, and
Go's randomised map iteration order means two calls with identical
content can visit it differently, so the hash sorts slugs and, within
each entry, its Fields/Variant keys before hashing, and covers every
field of every entry -- not just Rank/Date, the ones efTransferPlan's
own read path happens to touch today, because which entries even
qualify as class-1 is itself computed from that data, and
occupiedByClass1/Or2 scan ALL of merged, not just the class-1 subset.
Selection is included even though EF date resolution ignores it today
(resolveDate never reads its sel parameter) -- keying on it costs
nothing (four small strings) and protects a future change from
silently poisoning a cache that never accounted for it. The returned
map is always a fresh copy (clonePlan), never the cached instance, so
sharing it across goroutines needs no further synchronisation.

Verified the key is complete rather than trusted: with the content hash
temporarily dropped from the key (mutation test, not committed),
TestEFTransferPlanCacheInvalidatesOnOverlay failed immediately -- a
plan warmed for the shipped 2008 calendar was wrongly served back for
the same year with a user overlay applied (the Annunciation suppressed,
which changes where the RG 96(a)/97/98 collision sends St Joseph: 31
March instead of 1 April, empirically confirmed against the pre-cache
code before the test was written). TestEFTransferPlanCacheInvalidatesOnYear
is a lighter companion covering the year field. TestEFTransferPlanCacheConcurrentUse
hammers the cache from 12 goroutines across two different keys and
reasserts correctness afterward; clean under `go test -race`.

Benchmarked (interleaved before/after, same method as the readings.Prepare
commit, to control for machine thermal drift): BenchmarkDays7EF drops
from ~48-51ms to ~32-35ms/op (allocs 253810 -&gt; 208639, -18%; bytes
28.1MB -&gt; 16.1MB, -43%), roughly a third faster. BenchmarkDaysWeek (OF,
which never calls efTransferPlan at all) is unaffected, ~3.5-4.1ms/op
both before and after -- within noise, confirming this change is
EF-only as intended.

EF remains well outside OF's range (~32ms vs ~4ms), and a fresh CPU
profile after this fix places the dominant remaining cost precisely: it
is the SAME occupiedByClass1/Or2 pattern, but living OUTSIDE
efTransferPlan -- transferIfImpededEF's own fallback path, called once
per day for every class-1 candidate NOT already resolved by the (now
cached) plan, i.e. the ordinarily-unimpeded ones (~15-20 of them),
each triggering another O(len(merged)) scan. That call site was not
part of what this task named, and memoising it is a materially
different change (it is keyed per-candidate, not once per day), so it
is reported here rather than folded into this commit.

Output identity re-verified: a 492-case sweep of mobile.Day/mobile.Days
(both forms, both UI languages, all four corpora, a leap day, the
Sacred Triduum, a Requiem day, Christmas/Pentecost/Assumption/All Souls
windows, and the three Joseph/Annunciation transfer-collision years
this fix specifically touches -- 2008, 2035, 2046) produced
byte-identical (SHA-256-equal) JSON before and after. go test ./... and
make ci (both build tags, oracle/differential suite included) are
green.
</content>
</entry>
<entry>
<title>perf(readings): stack calendar layers and load the book table once per Days call</title>
<updated>2026-08-24T14:35:01Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-24T14:35:01Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=b6ee8f09ad2c0bc9e83394e2427de861eb1e2a72'/>
<id>urn:sha1:b6ee8f09ad2c0bc9e83394e2427de861eb1e2a72</id>
<content type='text'>
mobile.Days (dlectio's 7-day calendar view) called readings.Load once per
date. Load's offlineLoad re-ran caldata.Stack (parses the embedded
calendar INI, plus any user calendar layer) and bible.LoadBookTable
(parses the embedded books.ini, plus any user override) on every call,
even though neither depends on the date -- only on cfg.Selection().Form
and cfg.Use, which mobile.Days holds fixed across its whole loop.

Verified before changing anything: isolated benchmarks put Stack+
LoadBookTable at ~1.1ms/call (OF) and ~1.6ms/call (EF) -- real INI
parsing and, for a user override, file I/O -- and for the OF form that
redundant work was ~67% of a 7-day view's total time.

Load gains a Prepared value (the layer stack + book table) and a
Prepare/LoadWith pair: Prepare builds a Prepared once, LoadWith reuses
it across dates. Load itself is unchanged, still calling Prepare on
every invocation -- every existing caller keeps its current behaviour
untouched. mobile.Days now Prepares once and loops LoadWith; mobile.Day
picks up the same fix for its own two same-cfg Load calls.

Benchmarked (interleaved before/after pairs, to control for machine
thermal drift): the OF 7-day view (BenchmarkDaysWeek) drops from
~11.5ms to ~6.4ms/op (allocs 53359 -&gt; 16347, -69%), an EF 7-day view
(BenchmarkDays7EF) from ~74ms to ~66-73ms/op (allocs 299204 -&gt; 253815,
-15%; the EF form's per-day calendar computation dominates its total
cost far more than OF's does, so the fix's share of the win is smaller
there), and a single Day call (BenchmarkDay1) from ~4.3ms to ~2.9ms/op
(allocs 15357 -&gt; 9192, -40%).

Output identity verified separately (not part of this diff): a 288-case
sweep of mobile.Day/mobile.Days across both forms, both UI languages,
all four corpora, a leap day, the Sacred Triduum, a Requiem day, and
windows spanning Christmas/Pentecost/Assumption/All Souls produced
byte-identical (SHA-256-equal) JSON before and after this change.

New TestLoadWithAgreesWithLoad asserts LoadWith(Prepare(cfg), cfg, opts)
equals Load(cfg, opts) for every case, so the fast path cannot silently
drift from the slow one. go test ./... and make ci (both build tags,
oracle/differential suite included) are green.
</content>
</entry>
<entry>
<title>fix(clectio-gen): write the verse keys gzipped as well as plain</title>
<updated>2026-08-18T16:08:20Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T16:08:20Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=fd3eda0da228d2417b8b7f9007533e214d7a5e80'/>
<id>urn:sha1:fd3eda0da228d2417b8b7f9007533e214d7a5e80</id>
<content type='text'>
clectio's Makefile unpacks gen/verses_&lt;form&gt;.keys from the COMMITTED .gz, and
its clean target deletes the plain file. clectio-gen wrote only the plain one,
so regenerating the tables without separately re-gzipping the keys left
gen/liturgy_&lt;form&gt;.h indexing verses the packed text did not hold.

clectio then dereferenced a NULL verse pointer. That shipped: 1246 of the 10957
EF dates in the 2025-2054 range segfaulted, 11% of the calendar. OF was
unaffected -- its tables had not been regenerated since the keys were last
packed.

The two artefacts are generated together, so they are now written together and
cannot drift. OF's keys are byte-different after this (Go's gzip, not gzip(1))
but content-identical, verified.
</content>
</entry>
<entry>
<title>fix(ef): two I-class feasts can no longer transfer onto the same day</title>
<updated>2026-08-18T15:33:20Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T15:33:20Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=e713da2d796eabc55d407ad2f8488861e7598798'/>
<id>urn:sha1:e713da2d796eabc55d407ad2f8488861e7598798</id>
<content type='text'>
RG 97/98 require a year's impeded I-class transfers to be resolved together.
transferIfImpededEF resolved each one independently, so when an early Easter
impedes both St Joseph (19 March) and the Annunciation (25 March), both walked
to the Monday after Low Sunday -- and St Joseph, losing pickEF there, was
observed on NO day of 2008, 2035 or 2046 at all. He appeared only as a
commemoration in the Annunciation's tail.

RG 96(a) settles it outright, and it is not a tie-break: the Annunciation
transferred after Easter has a sedes propria -- "quando est transferendum post
Pascha, transfertur, tamquam in sedem propriam, in feriam II post dominicam in
albis". It claims the Monday by law; the rest queue in RG 98's order (table
position, then the office impeded first) and walk around it.

New efTransferPlan resolves the whole year's transfers as a set and hands each
feast its target; transferIfImpededEF keeps the single-candidate walk and All
Souls. The stale doc comment recording this as a known unfixable limitation is
replaced -- its reasoning argued RG 97/98 tie-breaks, when RG 96(a) decides the
only collision the universal calendar actually produces.

  2008-04-01, 2035-04-03, 2046-04-03  ef-easter-2-tuesday -&gt; St Joseph

Matches colitur on all three. Mutation-tested: bypassing the plan reddens the
new test on all three years.

fix(ef): 13 January's Baptism is omitted when Holy Family falls on it

The Holy Family Mass propers, verbatim in both photographic scans of the 1962
Missal:

  "Si festum S. Familiae occurrerit die 13 ianuarii, Missa dicitur de festo
   S. Familiae, sine commemoratione Baptismatis D.N.I.C., et sine
   commemoratione dominicae."

Sine commemoratione: the Baptism is omitted outright, not merely outranked, so
the candidate is dropped rather than left in Others. Structurally the same
answer RG 91 entry 14 gives (Festa Domini II classis: primum mobilia, deinde
fixa), but the propers' rubric is the direct authority for the omission.

lectio kept the Baptism as the observed office on all seven such years in
2005-2050 -- 2008, 2013, 2019, 2030, 2036, 2041, 2047 -- and never observed the
Holy Family Mass on 13 January at all. It already had the Holy Family Mass on
every other Sunday after Epiphany, so this was the one date it could not reach.

13 rows of the 16801-day differential fixture change; colitur agrees with all
of them.
</content>
</entry>
<entry>
<title>fix(ef): the ferias between Epiphany and the Sunday after it</title>
<updated>2026-08-18T15:15:27Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T15:15:27Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=d27336dc65c7348dcda639b7e43e8948e7bb1caa'/>
<id>urn:sha1:d27336dc65c7348dcda639b7e43e8948e7bb1caa</id>
<content type='text'>
They repeat Epiphany's own Mass, Isa 60:1-6 / Matt 2:1-12. lectio gave them
the Mass of the first Sunday AFTER Epiphany (Rom 12:1-5 / Luke 2:42-52), which
belongs to the ferias that follow that Sunday, not to the ones before it.

The two groups cannot be told apart by slug: both are
ef-time-after-epiphany-1-&lt;weekday&gt;, because the week numbering starts at the
Sunday and the days before it fall in the same numbered week. So the split is
made on the date, against the same anchor efWeek uses.

Saturdays need no exclusion here -- an unoccupied Saturday in the window
carries Our Lady's office and her Mass, and that check runs first. colitur
reaches the same result by listing only the five non-Saturday weekdays.

7, 9 and 12 January 2026 now all match colitur, the 12th being the boundary
case: it follows the Sunday of the 11th and correctly keeps Rom 12:1-5.
</content>
</entry>
<entry>
<title>fix(ef): three saints with proper Masses had no readings at all</title>
<updated>2026-08-18T15:11:04Z</updated>
<author>
<name>Lukasz Kasprzak</name>
<email>lukas@labunix.xyz</email>
</author>
<published>2026-08-18T15:11:04Z</published>
<link rel='alternate' type='text/html' href='https://git.labunix.xyz/lectio.git/commit/?id=c4bface0c72283cef55f548feb2a4a3d9eff1e6c'/>
<id>urn:sha1:c4bface0c72283cef55f548feb2a4a3d9eff1e6c</id>
<content type='text'>
Francis of Paola (2 April), Thomas Aquinas (7 March) and John of God (8
March). Unlike the nine added in the previous commit these are NOT Common-
routed -- the Missal prints a proper Mass for each -- they simply had no
reading in this repository and resolved nothing.

John of God is the one worth a note: his Epistle, Ecclus 31:8-11, is also the
Common of a Confessor not a Bishop I, which makes him look Common-routed. He
is not; the Gospel differs and the Missal prints the Mass at his own date.

With these, every day of 2005-2050 resolves a reading. Nothing in that range
comes back empty any more, where before there were four such days.
</content>
</entry>
</feed>
