summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorŁukasz <lukasz@arcofasiagroup.com>2026-07-23 11:57:08 +0200
committerŁukasz <lukasz@arcofasiagroup.com>2026-07-23 11:57:08 +0200
commiteece293ab9849eb8367c791cf6b5d29697c6eaed (patch)
tree7264d60a934af051accfcdfe3fb703570c0da805 /docs
parent6d31f48ee0603b847223722ee0179dda08cb529c (diff)
downloadlectio-eece293ab9849eb8367c791cf6b5d29697c6eaed.tar.gz
lectio-eece293ab9849eb8367c791cf6b5d29697c6eaed.zip
Spec: add caching, sigla harvest + offline mode, offline config
- Two-layer cache (HTML + parsed JSON) for fast repeat same-day loads. - 'lectio update' harvests the site's published future sigla into a persistent TSV (~/.local/share/lectio/sigla.tsv). - Offline mode (config offline=true, --offline flag, or auto-fallback on network failure): reads from the harvest + embedded corpora, renders wuj/vul/grb/drb; pl is online-only so wuj takes the Polish role. - Config gains offline=false (seeded default).
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/specs/2026-07-23-lectio-go-rewrite-design.md91
1 files changed, 82 insertions, 9 deletions
diff --git a/docs/superpowers/specs/2026-07-23-lectio-go-rewrite-design.md b/docs/superpowers/specs/2026-07-23-lectio-go-rewrite-design.md
index 9cc8cb3..f0889e3 100644
--- a/docs/superpowers/specs/2026-07-23-lectio-go-rewrite-design.md
+++ b/docs/superpowers/specs/2026-07-23-lectio-go-rewrite-design.md
@@ -20,12 +20,17 @@ keeps working. `lectio` is a fresh project.
## Non-goals
-- Offline lectionary computation (computing the day's citations without the
- site) remains the separate `offline_readings` effort. `lectio` fetches the
- site like `ewangelia.py`; when an offline engine exists it slots in behind
- `internal/liturgy` without changing consumers.
+- **Computing** the day's citations from a liturgical-calendar engine (for dates
+ the site never published, or with no network and no prior harvest) remains the
+ separate `offline_readings` effort. `lectio` gets citations from the site, or
+ from a prior `lectio update` harvest — it does not compute them. When an
+ offline engine exists it slots in behind `internal/liturgy` unchanged.
- No new translations beyond the five already supported.
+Note: harvesting the site's **published** future sigla (`lectio update`) and
+reading them offline *is* in scope — it is the "harvest" path, distinct from
+calendar computation.
+
## Key decisions
| Decision | Choice |
@@ -46,7 +51,7 @@ Module: `github.com/lukaszkasprzak/lectio`. Location: `~/git/projects/lectio`.
```
cmd/lectio/main.go -> cli.Run(args, stdin, stdout, stderr) int
cmd/lectio-ui/main.go -> load config+data, tui.New(...), tea.NewProgram(...).Run()
-internal/liturgy/ fetch + parse niedziela.pl into []Section
+internal/liturgy/ fetch + parse niedziela.pl; cache; sigla harvest/offline
internal/bible/ embedded corpora + reference lookup + book aliases
internal/psalter/ psalm versification (port of psalm_versify.py)
internal/render/ text rendering: compare columns, section text (CLI)
@@ -93,14 +98,53 @@ subset the tool actually feeds it:
- `Fetch(date, refresh) (html, error)` — GET
`https://niezbednik.niedziela.pl/liturgia/{date}/Ewangelia` with a browser
- User-Agent; cache to `~/.cache/lectio/{date}.html` (honor `XDG_CACHE_HOME`).
- Cache only fully-published pages.
+ User-Agent. Cache only fully-published pages.
- `Parse(html) ([]Section, error)` — pick the **new** lectionary tab
(`tabnowy0all`), fall back to `tabstary0all` with a warning; extract each
section's heading, subtitle, citation, and paragraphs. Fail loudly if the tab
is present but empty or absent (layout change).
- `Section{Heading, Subtitle, Citation, Paragraphs}`.
+### Caching (fast repeat loads)
+Two layers under `~/.cache/lectio/` (honor `XDG_CACHE_HOME`):
+
+- Raw HTML `{date}.html` — skips the network re-fetch of a published page.
+- Parsed sections `{date}.json` — skips re-parsing; a repeat load the same day
+ hits this and is near-instant (no network, no parse).
+
+Only fully-published pages are cached (an unpublished future date keeps being
+retried, never cached as "empty"). `--refresh` bypasses both layers.
+`Load(date)` tries JSON → HTML(+parse, write JSON) → fetch(+cache both).
+
+### Sigla harvest (`lectio update`) and offline use
+The site publishes each day's reading **sigla** (the scripture citations) weeks
+to months ahead. `lectio update` walks forward from today, fetching each date
+and extracting its citations, until it reaches the unpublished horizon (a page
+with no readings). It writes them to a persistent TSV:
+
+ ~/.local/share/lectio/sigla.tsv (honor XDG_DATA_HOME)
+
+One row per reading section: `date <TAB> section_label <TAB> citation`, e.g.
+
+ 2026-07-22 1. czytanie Pnp 8, 6-7
+ 2026-07-22 Psalm Ps 63 (62), 2. 3-4. 5-6. 8-9 (R.: por. 2ab)
+ 2026-07-22 Ewangelia J 20, 1. 11-18
+
+`update` merges with the existing file (re-harvesting a date replaces its rows),
+warms the HTML/JSON cache for those dates, and reports how many days it added and
+the furthest date reached.
+
+**Offline use.** When offline (config `offline = true`, the `--offline` flag, or
+an automatic fallback after a failed fetch), `Load` reads the sigla TSV instead
+of the network. If the date is present it builds the sections from the stored
+citations and renders the four **embedded** Bible versions from the corpora — so
+after one `lectio update`, any harvested day reads fully offline in Wujek Polish,
+Latin, Greek and Douay-Rheims. The `pl` version (modern niedziela.pl / Biblia
+Tysiąclecia) is online-only and not embedded (copyright); **offline, `wuj`
+(Wujek) takes the Polish role** — `pl` is dropped from any version list and
+replaced by `wuj` where needed (see Config → `offline`). A date absent from the
+harvest gives a clear "run `lectio update` online" error.
+
## Versions and psalm systems
Ported from `ewangelia.py` constants:
@@ -147,6 +191,7 @@ lectio date D [--all] [--raw] [--width N] [--refresh] # D = YYYY-MM-DD
lectio compare LIST [--date D] [--all] [--width N] [--refresh]
LIST = comma versions (default: config `versions`)
lectio show VERSION [--date D] [--all] [--refresh] # one version's text
+lectio update [--days N] [--from D] # harvest future sigla to the TSV
lectio --version | lectio -v
lectio help | lectio -h | lectio <cmd> -h
```
@@ -154,7 +199,11 @@ lectio help | lectio -h | lectio <cmd> -h
- `--all` shows every reading (1st/2nd, psalm, acclamation, gospel); default is
the gospel only, unless config `all = true`.
- `--raw` drops banner/headings for piping.
-- `--refresh` bypasses the cache.
+- `--refresh` bypasses the cache and re-fetches.
+- `--offline` (global) skips the network and uses the sigla TSV; also applied
+ automatically when a fetch fails.
+- `update` harvests forward from today (or `--from D`) up to `--days N` (default:
+ until the unpublished horizon), writing the sigla TSV.
- Flags override config. Exit codes: 0 ok, 1 runtime error (fetch/parse), 2
usage error.
@@ -167,6 +216,8 @@ Bubble Tea Elm architecture, per the approved mockup (reader + version-switch):
- Keys: `tab`/`shift+tab` cycle versions (order = config `versions`, starting at
`default_version`); `←/→` change date (async re-fetch with a loading state);
`j/k` and `space`/`b` scroll; `g/G` top/bottom; `r` refresh; `q`/`ctrl+c` quit.
+- Offline (config/flag): the version cycle omits `pl` (uses `wuj` for Polish);
+ dates come from the harvest; a header hint shows the offline state.
- Async fetch via `tea.Cmd` returning a `readingsMsg` or `errMsg`; a spinner or
"ładowanie…" line while in flight.
- Lipgloss styling, theme-neutral (works on light/dark terminals); width-aware
@@ -206,11 +257,26 @@ versions = ["pl", "wuj", "vul", "grb", "drb"] # compare set + TUI cycle
default_version = "pl" # TUI start / `lectio show` default
width = 0 # CLI wrap width; 0 = detect terminal
all = false # default to all readings (true) or just the gospel (false)
+offline = false # true = never fetch; read only harvested sigla + cache
```
Unknown versions in config are rejected with a clear error. Invalid TOML falls
back to defaults with a stderr warning.
+`offline = true` (or the `--offline` flag) makes lectio work purely from the
+`lectio update` harvest and cache — it never touches the network, and `pl`
+(online-only) is dropped in favour of `wuj` as the Polish version:
+
+- Any version list drops `pl`; if the list had `pl` but not `wuj`, `wuj` takes
+ its place. So default `versions` become `["wuj","vul","grb","drb"]` offline.
+- `default_version`/`show pl` fall back to `wuj` offline.
+- A date not present in the sigla harvest gives a clear "not harvested; run
+ `lectio update` online" error.
+
+Seeded default is `offline = false` (a fresh install has no harvest yet); a user
+who runs `lectio update` on a schedule can flip it to `true` for a fast,
+network-free daily read.
+
## Porting map (Python → Go)
| Python (`ewangelia.py` / `psalm_versify.py`) | Go |
@@ -225,8 +291,12 @@ back to defaults with a stderr warning.
## Error handling
-- Network failure / unpublished date: clear stderr message, exit 1 (CLI) or an
+- Network failure: fall back to the sigla TSV (offline mode) if the date is
+ harvested — render the four embedded versions, note that `pl` is unavailable.
+ If the date is not harvested either, clear stderr message, exit 1 (CLI) or an
error line in the TUI (stay usable, let the user change date).
+- Unpublished future date: "no reading published for this date yet", exit 1;
+ `update` treats it as the horizon and stops.
- Layout change (tab missing/empty): explicit "site layout may have changed"
error, exit 1.
- A corpus lacking a passage (e.g. deuterocanonical book absent from a version):
@@ -241,6 +311,9 @@ back to defaults with a stderr warning.
- **psalter**: unit tests for `drb_verse` on titled/untitled/2-line-title psalms.
- **liturgy.Parse**: fixture tests against a few cached HTML pages (a normal day,
a split-reading feast, an unpublished date), asserting sections/citations.
+- **liturgy cache + sigla**: round-trip the parsed JSON cache; harvest sigla from
+ fixture pages into a temp TSV and read them back; offline `Load` builds sections
+ from the TSV and renders the embedded versions with `pl` noted unavailable.
- **render**: golden-text tests for a compare block and a section, including the
refrain dedup and psalm-number divergence.
- **config**: load/seed/override tests with a temp `XDG_CONFIG_HOME`.