From 0a4bb4e6c3cbcafb302962d9d1e70b5a0bb554b8 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 17 Aug 2026 17:46:31 +0200 Subject: feat(cli): --overlay FILE, so a local calendar can be supplied The Overlay algebra has been built and tested since Plan 2, and Date_spec grew movable variants last commit, but there was still no way to hand colitur a file: bin/main.ml applied exactly one overlay, the shipped data/ef/adjustments.sexp, with the path hardcoded. This is the plumbing. --overlay is repeatable and ordered, and applies ON TOP of the shipped adjustments rather than instead of them. That ordering is the whole point: adjustments.sexp carries RG 110's own 30 June companion, the Major Litanies, St Barbara and Rogation Wednesday, and a user file that replaced it would silently drop all four while appearing merely to add a local feast. Overlay.merge is last-writer-wins, so a local calendar can still override a universal entry deliberately, by naming its slug. The dispatch needed real argument parsing. It matched Sys.argv as an exact array, which does not survive a repeatable flag -- two --overlay arguments are a different array shape from one, and each further flag would multiply the patterns again. Flags are now stripped first and the remaining words matched as command plus year. Hand-rolled, because the dependency list is frozen and this is fifteen lines. One defect found by the cram suite on the first run: the unknown-option guard rejected --help and --version, having excluded only their short forms. Refused, not ignored, on easter and temporal. Neither reads sanctoral data -- temporal deliberately runs the cycle before any layer exists -- so accepting the flag there and silently doing nothing is the failure mode this project refuses everywhere else. A file that fails to load is fatal, exactly as the shipped overlay is; a directive naming a slug that does not exist warns on stderr and the run continues. The second matters more for a user file than for ours: a typo in a diocesan calendar should say so rather than quietly do nothing. test/fixtures/overlay-example-diocesan.sexp is a worked example and is labelled as invented, not calendar data. It carries both shapes a real local calendar needs: a fixed-date patron, and a dedication on "the first Sunday of October" -- which is the case the Date_spec work existed to unlock and which lands on 4 October in 2026, 3 October in 2027, 1 October in 2028. The dedication is I class because a church's own dedication anniversary is I class in that church; at III class it lost to the II-class Sunday every year, which a first draft demonstrated correctly and uselessly. The man page gains an OVERLAYS section saying plainly that an overlay is applied, NOT validated: the five test layers assert things about the shipped calendar and none of them can vouch for a file the user supplies. This is the first feature that lets someone change what colitur computes, and that distinction should not have to be inferred. --- CLAUDE.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'CLAUDE.md') diff --git a/CLAUDE.md b/CLAUDE.md index f09c555..8edcdb2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -71,8 +71,8 @@ overlays**. year into a rata-die table, with the domain filter in `Layer.index` itself (both edges, 1582 and 10000, bit during development). This unblocked **Rogation Wednesday** (RG 87/88/89, register ยง6.10) and is what a - user-supplied overlay needs for a local movable feast. The `--overlay` CLI - plumbing is **not yet built**. + user-supplied overlay needs for a local movable feast. The `--overlay` CLI plumbing + is **built** (see below). - **Kernel** (`lib/kernel`, pure, total, bounded 1583โ€“9999): `Computus` (Gregorian + Julian Easter + anchors), `Date` (proleptic Gregorian arithmetic), `Overlay` (ordered layer-merge algebra: field-level add/suppress/replace/edit, last-writer- @@ -303,10 +303,22 @@ M20 added by the `ef-major-litanies` task, M18 394 not 395 accordingly). Fixtures live in `test/fixtures/` with asserted SHA-256s. **CLI**: `colitur easter `, `temporal `, `day `, -`readings `, `-h`/`--help`, `-V`/`--version`. Man page in +`readings `, `-h`/`--help`, `-V`/`--version`, and `--overlay FILE` +(repeatable, ordered; `day`/`readings` only). Man page in `man/colitur.1`; `Makefile` installs binary + data + man page into `~/.local` by default. Tagged **v0.1.0**. +**User overlays** apply ON TOP of the shipped `adjustments.sexp`, never +instead of it โ€” replacing would silently drop RG 110's companion, the Major +Litanies, Barbara and Rogation Wednesday. `Overlay.merge` is +last-writer-wins, so a local calendar can still override a universal entry +by naming its slug. Refused on `easter`/`temporal` (they read no sanctoral +data) rather than silently ignored. **An overlay is applied, not validated** +โ€” the five layers assert things about the SHIPPED data and cannot vouch for +a user file; a directive matching nothing warns on stderr and continues, a +file that fails to load is fatal. Worked example, both a fixed and a movable +local feast: `test/fixtures/overlay-example-diocesan.sexp`. + `--help` prints to **stdout** and exits **0**; a usage error prints one line to **stderr** and exits **2**. The distinction is asserted in `test/cli.t`, both directions, because it is the sort of thing that silently rots. -- cgit v1.3