summaryrefslogtreecommitdiff
path: root/test/cli.t
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukasz@arcofasiagroup.com>2026-08-27 12:33:43 +0200
committerLukasz Kasprzak <lukasz@arcofasiagroup.com>2026-08-27 12:33:43 +0200
commit32e792a0741f62fc2c0c7dcf9255408b3256fad5 (patch)
tree92f0b7b0a289de5251bb18bcc9239becdaee223c /test/cli.t
parent85903385f8a32be3de3964f43b3d7831474d0a72 (diff)
downloadcolitur-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.t259
1 files changed, 244 insertions, 15 deletions
diff --git a/test/cli.t b/test/cli.t
index 588616c..22890c1 100644
--- a/test/cli.t
+++ b/test/cli.t
@@ -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