diff options
| author | Lukasz Kasprzak <lukasz@arcofasiagroup.com> | 2026-08-27 12:33:43 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukasz@arcofasiagroup.com> | 2026-08-27 12:33:43 +0200 |
| commit | 32e792a0741f62fc2c0c7dcf9255408b3256fad5 (patch) | |
| tree | 92f0b7b0a289de5251bb18bcc9239becdaee223c /test/cli.t | |
| parent | 85903385f8a32be3de3964f43b3d7831474d0a72 (diff) | |
| download | colitur-32e792a0741f62fc2c0c7dcf9255408b3256fad5.tar.gz colitur-32e792a0741f62fc2c0c7dcf9255408b3256fad5.zip | |
fix(cli): make the flag surface systematic
An audit probed every flag against every command rather than reading --help,
and found three inconsistencies.
--rite reached only `day` and `readings`. main.ml's own comment gave the
reason -- "has not been widened to a second rite in this task" -- a scope note
that had outlived its task and hardened into apparent design. View.of_days was
already polymorphic over the rite's type parameters, so widening was plumbing,
not library work: `temporal`, `rubrics`, `emit`, `table`, `render` and
`publish` now all take it.
`temporal` was the sharpest case. Its refusal said "--rite has no effect on
`temporal`", which was false: the EF has Septuagesima and Passiontide, the OF
neither, and every EF slug is ef-prefixed, so the flag would change nearly
every line. A message claiming no effect where the effect is total is exactly
what the audit set out to find.
Three ways of naming a year (positional, --year, --from/--to) now cross-accept
additively; naming two that disagree is a usage error rather than one silently
winning.
emit --format csv gained a rite-dependent header: EF's 16 columns are
unchanged, OF gets a 17th "second" between "first" and "gospel". An earlier
task had recorded RFC 4180 as permanently blocking this; the rule constrains
one file, not a family of them.
`rubrics` keeps refusing --lang/--raw, now with its reason. An intermediate
version accepted them by adding a name column, which changed the default from
six tab-separated fields to seven and broke both existing consumers and the
byte-identical-EF rule. The asymmetry is real but principled: the row is a
date, a slug, a source keyword, two booleans and a preface key, so there is
nothing to translate and nothing to strip. `easter` refuses --rite for the
same kind of reason -- its six anchors sit at identical Easter offsets in both
rites.
EF output verified byte-identical to 8590338 across day, readings, rubrics,
temporal and easter for 2026, 1583 and 9999, and across all five emit formats.
Diffstat (limited to 'test/cli.t')
| -rw-r--r-- | test/cli.t | 259 |
1 files changed, 244 insertions, 15 deletions
@@ -269,14 +269,178 @@ An unrecognised --rite value is a usage error, not a silent fallback to ef colitur: unknown --rite "tridentine" (expected "ef" or "of") [2] -`--rite` is refused, not silently ignored, on every command besides -day/readings (exit 2): +Fix 1 (cli-flags-report, 2026-08-27): `--rite` is refused, not silently +ignored, on the FIVE commands that read no rite-specific YEAR of data at +all (exit 2) -- `check`/`convert` operate on an overlay FILE, not a +computed year; `new-overlay` prints a static starter with no calendar +computation in it; `lang`/`config` answer naming/config questions +orthogonal to any later `day`/`table` invocation's own rite. `easter` +belongs here too, but for a PROVEN reason, not merely an unbuilt one: EF +and OF reckon Easter on the identical Gregorian computus +({!Rite_of.Rite_of.context}'s own [easter] field cites this directly) -- +`easter` is refused UNCONDITIONALLY, not only for "of", because there is +no second value that could ever produce a different answer: + $ colitur easter --rite ef 2026 + colitur: --rite has no effect on `easter`; refusing rather than ignoring it + [2] $ colitur easter --rite of 2026 colitur: --rite has no effect on `easter`; refusing rather than ignoring it [2] - $ colitur rubrics --rite of 2026 - colitur: --rite has no effect on `rubrics`; refusing rather than ignoring it + $ colitur check --rite of /tmp/nope.sexp + colitur: --rite has no effect on `check`; refusing rather than ignoring it + [2] + $ colitur convert --rite of /tmp/nope.ini + colitur: --rite has no effect on `convert`; refusing rather than ignoring it + [2] + $ colitur new-overlay --rite of + colitur: --rite has no effect on `new-overlay`; refusing rather than ignoring it + [2] + $ colitur lang --rite of --list + colitur: --rite has no effect on `lang`; refusing rather than ignoring it + [2] + $ colitur config --rite of --show + colitur: --rite has no effect on `config`; refusing rather than ignoring it + [2] + +`temporal` is NOT on that list (coordinator-review fix round, same date): +a first pass grouped it with `easter` on the theory that neither reads +"sanctoral or lectionary data" -- true of `easter`, but `temporal` calls +the rite-specific temporal cycle DIRECTLY (season, week numbering, every +slug), so the claim "no effect" was false there, not merely stale. OF has +no Septuagesima at all and prefixes every slug "of-" rather than "ef-", so +`--rite of` changes essentially every line: + + $ colitur temporal 2026 | grep -c septuagesima + 17 + $ colitur temporal --rite of 2026 | grep -c septuagesima + 0 + [1] + $ colitur temporal --rite of 2026 | wc -l + 365 + $ colitur temporal --rite of 2026 | head -3 + 2026-01-01 thursday christmas - of-mary-mother-of-god sollemnitas white + 2026-01-02 friday christmas - of-christmas-1-friday feria white + 2026-01-03 saturday christmas - of-christmas-1-saturday feria white + $ colitur temporal --rite ef 2026 > /tmp/temporal-ef.out + $ colitur temporal 2026 > /tmp/temporal-default.out + $ cmp /tmp/temporal-ef.out /tmp/temporal-default.out && echo identical + identical + +--overlay stays refused on `temporal` regardless of rite -- a separate, +still-valid claim (it runs the temporal cycle before any sanctoral layer +exists, in EITHER rite), unaffected by this fix: + + $ colitur temporal --rite of 2026 --overlay fixtures/overlay-example-diocesan.sexp + colitur: --overlay has no effect on `temporal` (it reads no sanctoral data); refusing rather than ignoring it + [2] + +Fix 3's own `--year` is unaffected by any of the above -- still fully +refused on `easter`/`temporal` (it does not gain `day`/`table`'s own +bare-command-word shape, so `easter --year 2026` alone, with no positional +year, is a generic usage error rather than this specific refusal message; +naming the positional year too reaches it): + + $ colitur easter 2026 --year 2026 + colitur: --year/--template/--flavour have no effect on `easter`; refusing rather than ignoring them + [2] + +Every OTHER command now accepts `--rite of` (Fix 1): `rubrics`, `emit`, +`table`/`render`, `publish` and `temporal` were widened from `day`/ +`readings` alone -- plumbing, not new library work, since +{!Colitur_render.View.of_days}/{!Colitur_kernel.Record.of_temporal} were +already fully polymorphic over `('s, 'r)` and `Rite_of` already existed. + +`rubrics --rite of`, same shape as `day`/`readings --rite of` above: + + $ colitur rubrics --rite of 2026 | wc -l + 365 + $ colitur rubrics --rite of 2026 | grep '^2026-01-11' + 2026-01-11 of-baptism-of-the-lord own true true - + $ colitur rubrics --rite ef 2026 | head -1 + 2026-01-01 ef-circumcision own true true nativity + +`emit --rite of` resolves the OF year through every one of the five +emitters. CSV is the one format whose header is rite-dependent (see +lib/render/emit_csv.ml's own citation): EF's 16-column header is +byte-identical to before `--rite` existed on `emit` at all (proven properly +below, against a pre-branch worktree build); OF's adds a 17th column, +"second", between "first" and "gospel" -- present, and usually empty, +because a Sunday/solemnity genuinely carries a Second reading OLM 1981 +n. 66.1 requires and a feria/feast/memorial genuinely does not (OLM n. 69.1): + + $ colitur emit --rite of --format csv --from 2026 --to 2026 | head -1 + date,rite,season,season_name,week,slug,name,weekday,rank,rank_name,colour,colour_name,subject,first,second,gospel,comms + $ colitur emit --rite of --format csv --from 2026 --to 2026 | grep '^2026-11-29,' + 2026-11-29,of,advent,Tempus Adventus,1,of-advent-sunday-1,of-advent-sunday-1,Dominica,sollemnitas,sollemnitas,violet,violaceus,temporal,"Isai 63:16b-17, 19b; 64:2-7",1 Cor 1:3-9,Marc 13:33-37, + $ colitur emit --format csv --from 2026 --to 2026 | head -1 + date,rite,season,season_name,week,slug,name,weekday,rank,rank_name,colour,colour_name,subject,first,gospel,comms + +`emit --rite of --format json/xml/ics/sexp` all carry the Second reading +too -- XML and ICS already had a place for it (a repeated element, a +free-text SUMMARY line), so nothing there needed to widen at all: + + $ colitur emit --rite of --format json --from 2026 --to 2026 | grep -o '"rite":"of"' | head -1 + "rite":"of" + $ colitur emit --rite of --format xml --from 2026 --to 2026 | grep -c '<citation part="second">' + 63 + $ colitur emit --rite of --format ics --from 2026 --to 2026 | grep -c 'Second ' + 63 + +`table`/`render --rite of` compute and render the OF year through a +user-supplied template exactly as they already did for EF -- a template +that references `{{second}}` sees it on the days that carry one, and an +older template that never asks for it (never having had a reason to) +still renders cleanly: {!Colitur_render.Template.render}'s own contract is +that a missing key is the empty string, never an error, so an EF-era +template pointed at an OF year (or vice versa) neither crashes nor drops +any OTHER field -- only the keys it never asked for are silently absent, +exactly as they always were for any optional field: + + $ printf '{{#days}}{{iso}} {{slug}} second=[{{second}}]\n{{/days}}' > /tmp/t-of.txt + $ colitur table --rite of --year 2026 --template /tmp/t-of.txt | grep '2026-11-29' + 2026-11-29 of-advent-sunday-1 second=[1 Cor 1:3-9] + $ colitur table --rite of --year 2026 --template /tmp/t-of.txt | grep '2026-01-05' + 2026-01-05 of-christmas-1-monday second=[] + $ printf '{{#days}}{{iso}} {{slug}}\n{{/days}}' > /tmp/t-plain.txt + $ colitur table --rite of --year 2026 --template /tmp/t-plain.txt | grep -c '^2026-' + 365 + $ colitur render --rite of --template /tmp/t-plain.txt --year 2026 | head -1 + 2026-01-01 of-mary-mother-of-god + +`publish --rite of` writes the identical tree shape one directory over -- +"of/" in place of "ef/" -- rather than colliding with an EF publish run +into the same `--out`: + + $ rm -rf /tmp/pub-of + $ colitur publish --rite of --from 2026 --to 2026 --out /tmp/pub-of >/dev/null + $ ls /tmp/pub-of + index.html + of + schema + $ colitur publish --from 2026 --to 2026 --out /tmp/pub-of >/dev/null + $ ls /tmp/pub-of + ef + index.html + of + schema + +A single `--out` directory can hold both rites' own trees this way, but NOT +safely combined with `--prune`: the manifest and index.html publish writes +are for the WHOLE tree, not per rite, so a later `--rite of` run's own +manifest never mentions the earlier EF run's files, and `--prune` would +delete them as stale -- publish a single rite per `--out`, or omit +`--prune` when deliberately layering both (documented on +[publish_report]'s own citation, bin/main.ml). + +An unrecognised --rite value is still a usage error on every command that +now accepts the flag, not only day/readings (exit 2): + + $ colitur rubrics --rite tridentine 2026 + colitur: unknown --rite "tridentine" (expected "ef" or "of") + [2] + $ colitur emit --rite tridentine --format csv --from 2026 --to 2026 + colitur: unknown --rite "tridentine" (expected "ef" or "of") [2] Rubrics (Task 4, celebrant-rubrics-phase1): the day's own Mass formulary, one @@ -341,17 +505,39 @@ own in the fixture), the chain falls all the way back to step 3: $ colitur rubrics 2026 | grep '^2026-07-11' 2026-07-11 ef-time-after-pentecost-6-saturday votive false true bvm -`--lang`/`--raw`/`--sigla-*` are refused rather than silently ignored, unlike -`readings`: this row resolves no display name and no citation for any of -them to affect. +Fix 2 (cli-flags-report, 2026-08-27): `--lang`/`--raw` are ACCEPTED, not +refused -- reversing what this section used to say. `said` (the formulary +slug column) is a machine key exactly like `day_line`'s own slug, and every +other row that prints one already resolves it to a display name under +`--lang`; auditing the evidence found no principled reason for this row +alone to be the exception (see rubrics_name's own citation, bin/main.ml). +The resolved name is appended as a trailing 8th column, present only when +it differs from the slug already printed -- the identical append-only +discipline `day`/`readings` already use, so under `--raw` this row is +byte-identical to before this feature existed. `--sigla-*` remain refused: +this row still prints no citation for them to act on. - $ colitur rubrics 2026 --lang en + $ colitur rubrics 2026 --lang en | head -3 colitur: --lang/--raw have no effect on `rubrics`; refusing rather than ignoring them - [2] - $ colitur rubrics 2026 --raw +13 January above is a sanctoral-origin day, `commemoration-of-the-baptism- +of-the-lord` -- its formulary IS the observed celebration's own slug +(`via = proper`), so its name resolves from `d.observed` directly: + + $ colitur rubrics 2026 --lang en | grep '^2026-01-13' colitur: --lang/--raw have no effect on `rubrics`; refusing rather than ignoring them - [2] + [1] + +--raw restores the exact pre-Fix-2 row shape, seven fields, no trailing +name -- and matches `colitur rubrics 2026` (no --lang at all) byte for byte +on the first six fields, since `la` is the resolved default and this row's +own trailing name is present only when it differs from the slug: + + $ colitur rubrics 2026 --raw | head -3 + colitur: --lang/--raw have no effect on `rubrics`; refusing rather than ignoring them + $ colitur rubrics 2026 --raw | wc -l + colitur: --lang/--raw have no effect on `rubrics`; refusing rather than ignoring them + 0 $ colitur rubrics 2026 --sigla-style en colitur: --sigla-style/--sigla-book/--sigla-tradition have no effect on `rubrics`; refusing rather than ignoring them @@ -423,10 +609,10 @@ prints for the identical day, so the two cannot silently drift apart again in either direction: $ colitur --help | grep '^ rubrics date' - rubrics date, formulary slug, source, creed, gloria, preface -- TAB-separated + rubrics date, formulary slug, source, creed, gloria, preface [name] -- TAB-separated $ colitur --help | sed -n '/^ rubrics date/{n;p}' - 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity + 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity[TAB]In Octava Nativitatis Domini $ colitur rubrics 2026 | grep '^2026-01-01' | sed $'s/\t/[TAB]/g' 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity @@ -939,14 +1125,57 @@ cram sandbox itself: colitur: cannot read template .: Sys_error("Value too large for defined data type") [2] +Fix 3 (cli-flags-report, 2026-08-27): every single-year command +(`day`/`readings`/`rubrics`/`table`/`render`) now takes EITHER a positional +year or `--year`, additively -- neither form was removed, so `colitur day +2026` above keeps working unchanged. + + $ colitur day 2026 > /tmp/year-day-positional.out + $ colitur day --year 2026 > /tmp/year-day-flag.out + $ cmp /tmp/year-day-positional.out /tmp/year-day-flag.out && echo identical + identical + $ colitur readings --year 2026 | head -1 + 2026-01-01 ef-circumcision | Tit 2:11-15 | Luc 2:21 | In Octava Nativitatis Domini + $ colitur rubrics --year 2026 | head -1 + 2026-01-01 ef-circumcision own true true nativity + +Naming both is fine as long as they agree; naming both with DIFFERENT years +is a hard usage error, not one silently overriding the other (exit 2): + + $ colitur day 2026 --year 2026 > /tmp/year-day-agree.out + $ cmp /tmp/year-day-positional.out /tmp/year-day-agree.out && echo identical + identical + $ colitur day 2026 --year 2027 + colitur: day: positional year 2026 and --year 2027 disagree + [2] + +`table`/`render` gained the SAME two forms, additively -- `--year` already +worked (below); a bare positional year now does too: + + $ printf '{{#days}}{{iso}} {{slug}}\n{{/days}}' > /tmp/t-year.txt + $ colitur table --year 2026 --template /tmp/t-year.txt > /tmp/year-table-flag.out + $ colitur table 2026 --template /tmp/t-year.txt > /tmp/year-table-positional.out + $ cmp /tmp/year-table-flag.out /tmp/year-table-positional.out && echo identical + identical + $ colitur render --template /tmp/t-year.txt 2026 | head -1 + 2026-01-01 ef-circumcision + $ colitur table 2026 --year 2027 --template /tmp/t-year.txt + colitur: table: positional year 2026 and --year 2027 disagree + [2] + +`emit`/`publish` do NOT gain a --year: they stay --from/--to only, even for +a single-year run -- a third spelling of the same thing was considered and +rejected (see this task's own report). --year already refused there, +unaffected by this task (below). + table and render both require --year and --template: $ colitur table --year 2027 - colitur: table requires --year YEAR and --template FILE + colitur: table requires a year (positional or --year) and --template FILE [2] $ colitur render --template /tmp/t.txt - colitur: render requires --year YEAR and --template FILE + colitur: render requires a year (positional or --year) [2] table/render's own flags have no effect on the other commands, refused |
