aboutsummaryrefslogtreecommitdiff
path: root/CHANGELOG.md
blob: a8cc7418e9131e643da4f62a530ddfed380f6dc7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Changelog

One line per release. Versions are git tags (`vX.Y.Z`).

## [1.2.1] - 2026-09-03
- **Ten corrupt reading references in the OF lectionary, every one in a Year II entry.** Nine ended at verse 22 where the OLM ends them at 20 (`Mark 1:14-22`, `Mark 4:1-22`, `Mark 5:1-22`, `Matthew 7:15-22`, `Matthew 17:14-22`, `Matthew 18:15-22`, `1 Samuel 1:9-22`, `1 Samuel 3:1-10,19-22`, `James 5:13-22`); the tenth read `Matthew 17:9a,10-135`, a verse Matthew 17 does not have. Not one Year I entry was affected -- that distribution is what makes this a transcription fault rather than ten independent slips. Eight corrections are confirmed **verbatim in the Latin OLM 1981**, the primary source rather than a witness; the two the OCR does not yield are impossible on their face, since James ends at 5:20 and Matthew 17 has twenty-seven verses. Corrected **upstream in lectio** and this calendar regenerated from it, per the data file's own instruction not to hand-edit a generated artifact -- the diff is exactly the source SHA-256 pin plus the ten references.
- **Found by building the readings validation the OF had never had.** The litcal layer compared season, grade and identity and stopped there, so every reading colitur served had been validated by nothing except the lineage it arrived on. Two detections, neither sufficient alone: an **internal invariant** needing no external data at all -- in Ordinary Time the OF weekday Gospel does not depend on the year of the cycle, OLM n. 69 point 4 alternates only the First reading, so a `-i`/`-ii` pair whose Gospel differs is a defect by construction -- which catches six; and the **litcal comparison**, which catches three of those plus the four the invariant structurally cannot see, being First readings and an Advent entry that no such symmetry constrains. The invariant is scoped to Ordinary Time deliberately: unscoped it reports seventeen further pairs in Advent 4 and the Christmas octave, all of them correct, since those weekdays are keyed to the calendar date. Mutation-tested, and worth recording how: a first attempt changed *both* halves of a pair and passed for the wrong reason. Measured, the 20-vs-22 divergence class against litcal goes 26 to 0.
- **`--help` is one screen, not the manual.** It printed 374 lines -- every output format, the RFC 4180 quoting rule, the template scope hazard, the publish manifest semantics. All of it real documentation, all of it already in `colitur(1)` beside the binary. A help text nobody reads at the terminal is not more helpful than a short one, it is less, because the reader stops looking. Now 42 lines, and each dropped section was checked to have a man-page counterpart rather than assumed to. One check moved rather than died: `cli.t` pinned `rubrics`' documented field list against what it actually prints, because that count drifted once and stayed wrong for a whole review round; it now reads the worked example out of the man page, which `test/dune` gains as a cram dep.
- Also: `L6`/`L7`, the Sacred Heart / John the Baptist tie at an equal Tabula entry, gains the citation its own note said did not exist -- Tabula I.3 enumerates *"Sollemnitates Domini, beatae Mariae Virginis, et Sanctorum"*, an order rather than a bare category, which read that way settles the tie against colitur's alphabetical answer. Recorded with the counter-argument (entry 4 marks its internal order with explicit lettering; entry 2's list cannot be an ordering at all) and with what would settle it. Verdict stays open and behaviour is unchanged. 917 tests.

## [1.2.0] - 2026-08-28
- **Reading the output yourself, rather than through `awk`.** `--pretty` draws each day as its own box instead of a row: a heading with the date and the liturgical colour, then the celebration, its rank and season, and any commemorations, each on its own line. The box art is **pure ASCII** -- only `+`, `-` and `|`, never Unicode box-drawing -- because this format exists to be pasted or piped into a document, a mail or a plain-text ordo, and U+2500 and its relatives survive that only when every stage agrees about encoding and font; alignment counts UTF-8 code points rather than bytes, so a name carrying a ligature still lines the right edge up. Colour is written only when stdout is a terminal, `NO_COLOR` is honoured on presence whatever its value (the convention's own rule -- reading it as a boolean is how tools get it wrong), and the colour column degrades to its initial rather than simply vanishing when piped. Nothing should be written to parse it: its layout is free to change, which is precisely what the default format is not.
- **`--month N`, `--date YYYY-MM-DD` and `--today`** narrow a report to part of a year. They matter most under `--pretty`, whose boxes span seven lines and so survive no line-wise `grep` at all -- the nearest equivalent is a paragraph-mode `awk` incantation that works only because the boxes happen to be blank-line separated -- but they are **independent** of it and narrow the default format too. The three are **alternatives, not a stack**: naming two is an error rather than a silent win for one. `--date` and `--today` NAME a year, so on those two the year may be omitted (`colitur day --today` is a complete command) and must agree when given as well, the same rule the positional year and `--year` already follow; the disagreement message names the flag, because with `--today` the second year appears nowhere on the command line for the reader to find. `--month` names no year and so still needs one. `temporal` refuses `--year` yet accepts `--date`/`--today` including as its year source, which is not an inconsistency: `--year` is a second spelling of the positional year, which `temporal` deliberately does not offer, whereas `--date` selects a DAY and merely happens to determine which year contains it.
- Both are accepted by `day`, `readings`, `rubrics` and `temporal`, and **refused** by every other command rather than accepted and quietly ignored -- `emit`/`table`/`render`/`publish` already choose their shape through `--format` or `--template`, and `easter` prints six key/value lines rather than a day grid. `--pretty` had shipped undocumented in both `--help` and `colitur(1)`; both now describe it, alongside a new NARROWING A REPORT section. Default output is byte-identical to 1.1.0 across seven years, five commands and both rites, and across all five emit formats and the shipped templates. 916 tests.

## [1.1.0] - 2026-08-27
- **The Ordinary Form, as a peer rite.** `--rite of` on every command that a rite can affect. This release exists as much for what it tested as for what it adds: the `Rite` abstraction was designed against a single rite, and until now nothing had shown it generalised. It does -- `rite_of` satisfies `Rite.t` with no kernel special-casing. Six modules (vocab, temporal, precedence, rubrics, lectionary, and the bundle); the calendar transcribed from the **2002 Latin typical edition**, 209 entries, with **one independently citable overlay per post-2002 decree** rather than a merged file, so every change since the typical edition can be read, cited and reverted on its own; 1 725 reading citations. Where `--rite` cannot affect a command, the refusal says why in substance rather than reporting a scope boundary. EF output is byte-identical to 1.0.0, verified across `day`, `readings`, `rubrics`, `temporal` and `easter` for 2026, 1583 and 9999, and across all five emit formats.
- **Building a second rite found five places the kernel had absorbed EF assumptions.** Two are fixed: `Validate`'s hardcoded `[First; Gospel]` reading set is now rite-supplied, and `transfer_target`'s "strictly later" obligation became "must differ from origin", which is the real invariant. The other three are documented with the rule that forced them.
- **The known limitation, stated plainly**: the OF has no published-ordo witness, where the EF has three. Its external validation rests on litcal -- a second *implementation*, not a second *publication* -- whose identity comparison reaches about 12% of non-Triduum days. A wrong-saint-same-grade defect would not be caught today.
- *(This entry was backfilled on 2026-08-28; 1.1.0 was tagged without one. Its content is taken from the v1.1.0 tag message, not reconstructed.)*

## [1.0.0] - 2026-08-24
- **colitur now prints what a real ordo prints for the Mass.** That is the whole of this release, and the scoping rule it was built to: nothing more, nothing less. `colitur rubrics <year>` gives, per day, which Mass formulary is said and how that was reached (`proper`/`own`/`preceding-sunday`/`common`/`votive`), the Gloria, the Creed and the preface; commemorations gained their Low-Mass/sung distinction. **The Creed** is RG 475-476, whose clause (a) reads the TEMPORAL cycle rather than the observed day — *"in qualibet dominica, etsi eius Officium alicui festo locum cedat"*, a Sunday impeded by a feast still says it — and whose clause (e) turns on *natalicia*, which is why the rubric must name the Chair of St Peter and St Barnabas explicitly and why the Conversion of St Paul is excluded; the Apostle list was derived from the shipped data and verified entry by entry rather than transcribed. **The Gloria** is RG 431-432, whose clause (a) defers a Mass question to the Breviary — *"quotiescumque ad Matutinum dictus est hymnus Te Deum"* — so the Te Deum is implemented as its own cited predicate from Breviary nn. 237-238 rather than collapsed into a colour heuristic. **The preface** is RG 482-499's chain, proper else seasonal else common, with RG 483 bounding it: no commemoration ever induces a proper preface. **Chants are deliberately absent** and always will be: a priest has the Missal open, and an ordo's job is what the book cannot tell you when you open it.
- **Four rubrical defects, every one found by an external witness rather than by inspection.** *The Creed was said at Requiem Masses* — RG 476(f) forbids it, and All Souls had been wrong every year; closed via a `Colour.Black` proxy sound because black occurs exactly twice in the whole engine. *The bissextile shift was missing entirely* — the calendarium's own February footnote moves St Matthias to 25 February and St Gabriel to 28 February in a leap year, *"et bis dicitur sexto calendas"*; 2 041 leap years, 6 983 days, and it surfaced only because a witness year covering 2024 was added. *Rogation Monday and Tuesday were violet* — RG 119(b) makes Paschaltide white and RG 128 does not list Rogations at all; the violet belongs to the votive Rogation Mass, not the day's office, and fixing it cascaded correctly into the Gloria. *The ferias after the Ascension resumed the preceding Sunday's Mass* — the Missal's own marginal rubric repeats the Ascension's through the week; 16 350 days.
- **The single-lineage problem is broken, not merely documented.** Layers 3 and 4 both descend from Divinum Officium, so for two years this project had one witness counted twice. It now has **three independent publishers over seven witness-years** — the FIUV universal Ordo (Latin, recording the Te Deum 262 times, and so a second witness on the Breviary clause whose own source is a single web transcription), three Latin Mass Society editions, and three from extraordinaryform.org. Preface agreement is 358/363, 358/363, 361/362, 395/395, and three LMS years at 396/396, 399/399, 398/398. Each source was characterised before use — probed on dates where the rubric predicts OPPOSITE answers — because an ordo prints a MENU of permitted Masses and comparing against the wrong item manufactures divergences: that trap produced 200 false colour findings, 12 false class findings, and one adjudication that had to be publicly withdrawn, all inside this release's own development.
- Also: RG 33's own second-order consequences settled; RG 111(a)'s sung-Mass cap exposed as a derivation over data already validated rather than a new stored field; RG 497 shown to lack the *natalicium* restriction RG 475(e) carries, adjudicated on four witness confirmations across two publishers; and two apparent sanctoral gaps shown to be `Missae pro aliquibus locis` in the Missal's own words — particular feasts colitur is right to exclude, and which an overlay supplies. 761 tests, every year 1583-9999.

## [0.10.1] - 2026-08-21
- **RG 33's third omission trigger**, the last unbuilt clause in the EF module. A II- or III-class vigil is omitted entirely not only when it falls on a Sunday or a I-class feast, but *"vel si festum cui praemittitur in alium diem transferri aut ad commemorationem reduci contingat"* — if the feast it precedes fails to keep its own day. Only the first two triggers were implemented; the code comment recording the third as unbuilt argued that no witness existed in the shipped data, and that was simply wrong: it fires on **1 744 days** across 1583–9999, in three shapes, every one classified against a pre-change binary. 1 199 are St Lawrence's vigil dropped because 10 August fell on a Sunday and reduced the feast to a commemoration; 545 are St John the Baptist's or Peter and Paul's dropped because the Sacred Heart or Corpus Christi took the feast's day and it transferred under RG 96. Both halves reduce to one question — is the feast the observed office tomorrow? — so the kernel asks it once per candidate after transfers settle, in a single pass with no fixed point: a vigil is a candidate only on its own day, never on its feast's, so suppressing it cannot change what the next day observes. `Precedence.rules` gains `vigil_feast`, which returns the slug of the feast a vigil precedes, because the kernel cannot infer it — only two of the five vigil/feast pairs share a slug stem. **Verified outside the project's own lineage, which is rare here**: O'Connell's *The Celebration of Mass* (1964) states all three triggers and independently confirms the five-vigil inventory and its class split, and the Latin Mass Society Ordo 2024–2025 gives 9 August 2025 as "OUR LADY on SATURDAY IV Cl W / Commem of St Romanus M" with no vigil — colitur's output field for field, and discriminating because that edition lists six other vigils including the Assumption's five days later. An earlier claim that the Ordo already in `docs/research/` corroborated this was **withdrawn**: it omits St Lawrence's vigil on every date it covers, including one where the rule says to keep it, so its agreement was a gap coinciding with the right answer. The clause's transferred-feast shape still has no day-level witness, which the allow-list note states rather than glosses. Two cited allow-list entries (C39 vs lectio, an adjudicated class vs the oracle); the RG 128 golden pin asserting St Lawrence's vigil is violet moved 2025 → 2027, its own comment having reasoned about the vigil's weekday and missed that the rule also looks at the feast's. 575 tests.

## [0.10.0] - 2026-08-21
- Two configuration gaps and a diagnosis. **`flavour` is now a config key.** It was the one rendering setting with no way to set it once: `template` and `format` had keys, the escaping flavour did not, so a template whose extension says nothing about its output needed the flag on every invocation. It is normally inferred from the extension and unset still means "infer", which is why `config --show` reports `(infer)` rather than `(none)` — an unset flavour is not an absence. There is deliberately no silent fallback, because guessing it wrong yields malformed output rather than ugly output. **An INI overlay handed to `--overlay` is diagnosed rather than left to fail.** The INI form is a SOURCE format that `colitur convert` turns into the S-expression one; feeding it directly failed deep in the sexp reader with "more than one S-expression in file", naming neither the cause nor the cure — and the shipped examples under `data/ef/examples/` are exactly what someone would try it with. The detector's own first version capped its scan at 40 lines while `poland.ini`'s comment header is 43, so it silently never fired on the very file it was written for. Also: the README's about page carried three false claims — that older tags are not downloadable (true for one morning), that the OF form exists (`lib/rites/` holds `rite_ef` alone), and suite timings from a much smaller suite — and gains a status section stating not just the five validation layers but what they cannot see, since the differential and the oracle share one data lineage. 570 tests.

## [0.9.0] - 2026-08-20
- An audit of the shipped program, and the fixes it found. **The citation parser accepted OCaml integer-literal syntax**, so `Luke 1_1:5` read as chapter ELEVEN and `+5` as 5 — a transcription typo silently becoming a *different chapter*, reachable through any user overlay. Numbers are now plain digits and positive, and a descending range is rejected. **Four pairs of different books shared a full title**: 1 and 2 Corinthians both rendered "Epistola ad Corinthios", as did Thessalonians, Timothy and Peter — 108 citations in 2027 alone that a reader cannot resolve to a book. This was the Kings defect fixed one release earlier and simply not generalised. A test now forbids it, while allowing the case where two ids *are* the same book under different numbering, which a tradition relates. **Spec §8.5 went from recorded to delivered**: shipped styles did not re-parse their own rendered output — 32 of 52 Latin abbreviations and 49 of 52 full titles failed — so a citation copied out of colitur's own output into an overlay was passed through untouched and printed in the wrong language, silently. Every shipped name is now a registered spelling and `split_book` learned multi-word titles. **Overlay errors stopped naming OCaml source files at the reader**: the five-path rewriter is replaced by a generic one applied at every load path, so "rank: is not one of the allowed values (at Class9)" replaces a raw `Of_sexp_error` dump. Also: the `new-overlay` scaffold shows `citations` at the right nesting level (it documented the field without showing it, and the nesting is the single easiest thing to get wrong); `config --show` validates before printing rather than exiting 2 after five rows; error messages no longer echo whole file lines, which copied an unrelated file's contents to stderr when a flag pointed at one; and a month answers to both spellings of its own name, since an unknown template key renders as the empty string and the mistake produced a silently blank heading. `--raw` output is byte-identical to 0.8.0 across the whole domain. 569 tests.

## [0.8.0] - 2026-08-20
- Output, naming, and configurable citations — the release that made everything a reader sees a file rather than a value in code. **Rendering**: a logic-less template engine (Mustache subset, no partials, no lambdas, no code execution) with *mandatory* per-flavour escaping — `latex typst groff html xml ics none` — plus five emitters (`csv json sexp xml ics`, the last RFC 5545 with stable UIDs and 75-octet folding), `colitur table`/`render`/`emit`/`publish`, and eleven shipped templates: an ordo booklet in six flavours and a wall calendar in four. **Naming**: language tables and a config file, so slugs stop reaching the page — `ef-septuagesima-sunday-2` was printing in a booklet because nothing asserted coverage. Latin names for the whole temporal cycle and sanctoral, transcribed from the Missal, with a citation checker wired into the suite; `--raw` keeps the bare-slug form. The coverage test at first walked only the *observed* day and so never saw commemorations or transfers, which is exactly how "Commemoratio canute-martyr" reached a printed page. **Citations became configurable**: parsed into structure and re-rendered, so book names, abbreviations, punctuation and numbering tradition are each a file — `[bible]` and `[sigla]` sections in a language file, `lang/traditions.ini` for Vulgate-versus-modern numbering, three config keys and flags. Naming and renumbering are deliberately separate mechanisms; conflating them is how a citation ends up naming the wrong book. The design's own survey of "the shipped data" had read one of three citation-bearing files and missed twenty-one book tokens — `sanctoral.sexp` carries more citations than the lectionary does — and the fact was already written down in `commons.sexp`'s header, which called the inconsistency "cosmetic" because nothing parsed those strings. **Differential closure**: lectio adopted eight corrections argued from the Missal, so on those days the shared lineage is broken and colitur is no longer the outlier; the fixture was regenerated and seven divergence classes closed. Also: `publish --prune` refused a manifest entry escaping `--out` (a real traversal, found by canary), `fold_ics` was made total on arbitrary octets, and four vacuous assertions were replaced with real ones. 559 tests.

## [0.7.0] - 2026-08-18
- A flat INI form for overlays, a reference man page, and two real local calendars. **`colitur convert FILE.ini`** transpiles a flat, section-per-slug format to the S-expression one — `status`, `subject` and `layer` all default, so an ordinary local saint's feast says only what distinguishes it, and dates flatten to `MM-DD`, `easter+N` and `oct/sun/-1`. It is a front door, not a second data model: it parses to exactly the `Overlay.t` the sexp form does, and a test asserts the two produce identical values. It is deliberately less expressive — `Add`, `Suppress`, single-field `Edit` — and refuses `Replace`, multi-field and citation edits *by name* rather than dropping them. **The conversion verifies its own output**: the emitted text is parsed back with the same function that loads an overlay and must mean what the INI said, or nothing is written — a transpiler emitting valid-but-wrong sexp is the failure a convenience format invites, and `colitur check` could never catch it. That check was wrong on the first attempt in exactly that way, re-serialising the parsed value instead of parsing the emitted text; a mutation corrupting the renderer sailed through it, and the fix makes the same mutation redden two tests. **`colitur-overlay(5)`** documents the format in full — every directive, every field, the three date shapes — and, more usefully, *how an overlay is applied*: load, merge, resolve, emit, with the point made explicit that overlay entries take part in precedence on equal terms, so "my feast does not appear" is almost always a lost contest rather than a load failure. **Two real calendars ship** beside the invented example: **Poland**, 17 entries from the *Calendarium Perpetuum pro Dioecesium Poloniae* (1964), with three unrecoverable classes marked as inferences and a warning about the 1921/1934 *Proprium Poloniae* still bound into many missals; and **Benedictine**, two entries and a comment explaining why — the monastic rite grades feasts Duplex and Semiduplex below II class, where the Roman calendar has III and IV, so most Benedictine propers cannot be expressed here at all, and rather than invent a mapping the source never states, that file lists two dozen excluded feasts by name. Both are examples, not authorities. 405 tests.

## [0.6.0] - 2026-08-18
- Writing a local calendar gets a feedback loop. An overlay is still **applied, not validated** — the five test layers assert things about the *shipped* calendar and cannot vouch for a user's file — but until now the only way to learn whether yours did what you meant was to generate a year of output and grep for your own slug, and the only way to see that a directive matched nothing was to notice a warning scroll past among 365 lines. **`colitur check FILE ...`** loads each overlay, applies it to the real shipped calendar, and reports the directive counts, the slug each one targets, and any directive that found no target; it exits 2 on a load failure or an unmatched directive, so it composes into a Makefile or a pre-commit hook. It answers three narrow questions — does the file parse, does every directive find its target, what does the merged result contain — and does *not* check a calendar against the rubrics, which the help text and man page both say, because the name invites a stronger reading than the command earns. **`colitur new-overlay`** prints a commented starter to stdout for redirection, rather than writing a file where it likes; every value in it is a placeholder that will appear in `day` output if left unedited, so a half-finished overlay is visible rather than silently inert. **The format is less hostile too**: `citations` and `layer` may now be omitted from an added celebration, defaulting to empty and to the overlay's own `id` — they were the two of eight fields carrying nothing an author could supply, and omitting them used to fail with `lib/kernel/celebration.ml.t_of_sexp: the following record elements were undefined`, naming a source file the author will never open. An explicitly stated value still wins, pinned in both directions. Parse errors stop naming kernel source paths. The leniency is scoped to overlays alone: `Layer.load`, which reads the shipped sanctoral, stays strict, because a missing field there is a defect rather than a convenience. 398 tests.

## [0.5.0] - 2026-08-18
- Two corrections, both found in primary sources the project already had but had not fully read. **`ubaldus` (16 May) and `didacus` (13 November) are III-class feasts, not commemorations** — found by auditing *all 290* fixed-date sanctoral entries against the Missal's own universal calendarium, anchored on the Roman calends column because the arabic day numbers are OCR-wrecked and the dominical letters vanish in some months. They were the only two status defects in the file; the 15 days the automated pass could not reach were read by hand. Universality is structural, not a judgement call: the calendarium carries no *pro aliquibus locis* marker in its 573 lines while the wider Missal carries 79 elsewhere, and each saint has his own Mass entry in the Proprium, which a bare commemoration never has. Neither needed a proper authored — each takes its Mass from a Common with only its Oratio proper — though one Common was newly transcribed (*Missa Iustus*, 1 Cor 4:9-14 / Luke 12:32-34, read independently in both scans). 13 036 days change, every one classified. **RG 113's first sentence is now implemented**: *"Commemoratio de Tempore fit primo loco"* — only its second sentence was, so ordering ran through the precedence table for every commemoration including the seasonal one. Reconciled with RG 110(c)'s *"ante omnes alias commemorationes"* by the term the two rubrics share, whose sense RG 113's own sentence fixes: season, then the inseparable Peter/Paul pair, then table order. 3 533 days change, **every one order-only** — identical commemoration sets, verified as sorted multisets. Also: every Latin quotation in the rules register re-audited against the electronic transcription — all 26 rubric quotations verbatim, zero errors — which established that rubrics must be checked against the transcription and propers against the photographic scans, the confusion that nearly lost RG 110(c). 396 tests.

## [0.4.0] - 2026-08-18
- Three colour corrections, and the first findings in this project's history made against sources **outside its own data lineage**. colitur was bootstrapped from lectio, lectio's ini is generated from missalemeum, and missalemeum uses Divinum Officium's data files — so the differential and the oracle, layers 3 and 4, are one witness counted twice, and an error inherited at the root is invisible to both. Two sources outside that tree were admitted this release, each with its rubrical edition established *before* use: a published **1962 Ordo** (three liturgical years, 1091 days, 1504 permitted Masses) and **O'Connell's *The Celebration of Mass*, 4th ed. (1964)**, revised throughout to the Codex Rubricarum (1960) and the 1962 Missal. **Good Friday is black, not violet** (RG 128(b)'s own exception for the *Actio liturgica ... usque ad Communionem exclusive*, with RG 132) — recorded in the register as an acknowledged gap since Task 16 and closed here. **The Vigil of the Assumption and the Vigil of St Lawrence are violet**, not white and red (RG 128, "vigils of II and III class outside Paschaltide"); the Ascension's vigil is untouched, being the one such vigil *inside* Paschaltide. That rule had sat transcribed in the register since 11 August, disagreeing with the shipped data the whole time, while both layers stayed green on the shared error. 22 809 days change across 1583–9999, every one colour-only, none unclassified — and the two vigils' identical 7 196 was verified against an independent implementation rather than accepted. Also: **rose stays on Gaudete and Laetare**, now a decided position rather than an unexamined one (RG 131 is permissive, so the colour field carries a permission there, not a requirement). Divergences from every Divinum-Officium-lineage source are cited, not adopted: C37 and M29. 395 tests.

## [0.3.1] - 2026-08-18
- Adjudications and evidence only; no behaviour change. **M13 closed** — St Joseph is not displaced from Passion Friday: the hypothesis the entry rested on (a rubric at Joseph's own propers entry, "the same shape as the Annunciation's") was checked directly and is false, and the analogue does not exist either, the Annunciation's exception living in RG 96 rather than its propers. **Mass I of the BVM Saturday** needs no corroborating oracle year because none can exist: Advent has no IV-class ferias, so that office never falls there. **A third oracle window, 2035**, witnessing `isidore-of-seville` and with him `common-of-doctors`, the one Common no window had ever tested — closing step 4's blind spot as far as the method allows, the last two saints being unreachable by construction. 393 tests.

## [0.3.0] - 2026-08-17
- Three EF corrections and a new resolution step, all argued from the Missal rather than from oracle agreement. **The votive Mass of Our Lady on Saturday** (RG 309(a)): the office had been kept since v0.1 but read the feria's Mass, so the day observed Our Lady and read the parable of the weeds; it now selects among the Missal's five *Missae de sancta Maria in sabbato* by season — 87 611 reading rows, every one a Saturday. **The Seven Sorrows of Passion Friday**, a movable commemoration colitur had no trace of, buildable only once `Date_spec` grew `Easter_offset`; adding it *reversed* an allow-list verdict, since RG 111(d) admits two commemorations on a III-class day and colitur admits exactly two where the oracle drops one. **The week after Trinity**, which now says the Mass the Missal prints for it, under RG 299's *nisi propria Missa assignetur* — and the same rule shows the Christ-the-King-week divergence was never a bug at all. RG 299 also closes a standing gap: the ferial-Mass rule was recorded as unconfirmed against the primary source and is now cited.

## [0.2.0] - 2026-08-17
- `Date_spec` carries movable dates: `Easter_offset` and `Nth_weekday` beside `Fixed`, whose on-disk form is unchanged so all 327 sanctoral entries parse untouched. Easter comes from the rite, not the kernel, which ships both Gregorian and Julian and must not pick. `Layer` keeps a split index — fixed entries year-independent as before, movable ones resolved per civil year. That unblocked **Rogation Wednesday** (RG 87/88/89), recorded as architecturally blocked since 13 August on reasoning that turned out to rest on `Date_spec`'s expressiveness rather than the entity's nature: 2 257 days across the domain, and in the other 6 160 an impeded feast takes the single slot RG 111 allows. And it unblocked **`colitur --overlay FILE`** (repeatable, ordered), which applies a user calendar on top of the shipped one — never instead of it — so a diocese or parish can add local feasts, fixed or movable. An overlay is applied, not validated: the five test layers assert things about the shipped calendar and cannot vouch for a user's file. Also: a second oracle year (2038, live-captured) closing the Common route's blind spot, `--version`, a Makefile, and a man page.

## [0.1.0] - 2026-08-17
- First tag. The Extraordinary Form (1962 Roman Missal) end to end: the complete temporal cycle, the resolution engine (occurrence, precedence, commemorations, transfers) against the sanctoral calendar, and the Mass reading citations for every day — correct and total over 1583–9999, with no clock, randomness or environment read below the CLI. Four commands (`easter`, `temporal`, `day`, `readings`) plus `--help`/`--version`, a man page, and a Makefile that installs binary, calendar data and man page into `~/.local` by default. Validated in five layers: types, QCheck properties over every year in the domain, a 16 801-day differential against the sibling lectio engine, two independent missalemeum oracle windows (2026–2027 and 2038), and ~36 hand-verified golden pins — 375 tests. Rules are computed against the Missal and its *Rubricae Generales*, with every published-calendar divergence adjudicated against the primary text rather than adopted; several are resolved in this engine's favour and cited in the register. Not included: the Ordinary Form, the chants (Psalm/Gradual/Tract/Alleluia/Sequence, deliberately rejected rather than guessed), and template-driven output.