aboutsummaryrefslogtreecommitdiff
path: root/lib
Commit message (Collapse)AuthorAgeFilesLines
* kernel(validate): invariant harness over liturgical yearsLukasz Kasprzak2026-08-112-0/+108
| | | | | | | | | | | Coverage, season contiguity and completeness, Sunday-aligned week numbering, slug well-formedness, weekday agreement and vocabulary closure. Checks run over a liturgical year rather than a civil one, since Christmastide straddles January and would otherwise appear to recur. Run against EF temporal for landmark years, both Easter extremes, and 200 random years across 1583..9998 -- the property layer is how confidence reaches past the oracle horizon.
* rite(ef): give Pentecost, its Vigil and Christ the King their weekLukasz Kasprzak2026-08-111-3/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | named hardcoded week = None for ef-pentecost-vigil, ef-pentecost and ef-christ-the-king, unlike the five sibling named Sundays (Easter, Low Sunday, Passion Sunday, Palm Sunday, Trinity), which already carry the explicit week number that week computes for the same date. Because these three sit inside a season run rather than at a run boundary, the omission let the week number jump on the following Monday without an intervening Sunday marking the change -- breaking week continuity in every single year in the domain. This was found by the new Validate invariant harness (Task 14), which flagged exactly two failures in every one of the 8416 years 1583..9998, both on the Monday after one of these days. Season contiguity itself was clean across the whole domain; only week numbering was affected. Pentecost and its Vigil are fixed Easter offsets, so they take the literal values (7 and 8) that week already computes for them. Christ the King's date varies by year, so the same expression week evaluates is inlined instead, since week is defined later in the file and cannot be called from named. Added a general property test, prop_named_week_agrees_with_week, checking across 200 random years that wherever named gives an explicit week, it matches what week independently computes for that date -- covering all sibling entries, not just the three fixed here, so the same drift cannot silently reappear in a future addition to named.
* rite(ef): ferias, Ember days, Rogations and the temporal entry pointLukasz Kasprzak2026-08-112-0/+150
| | | | | | | | | | | | | | | | | | | | Ferial ranks per RG 91: I class in Holy Week and the privileged octaves (entries 7, 10), II class for Advent 17-23 and the Ember days (entry 18), III class for Advent to 16 December and Lent/Passiontide (entries 22, 25), IV class per annum (entry 28). Two further divergences from lectio, both from the table: Advent 17-23 are II class, and the Lenten Ember days are II class rather than ordinary Lenten ferias. Rogations (RG 80/87) exist at all, which lectio does not compute. Gaudete and Laetare are rose. Two corrections against the primary source beyond the task brief's draft. Entry 7 (verified against the Latin: "feria IV cinerum et II, III et IV Hebdomadae sanctae") covers only Ash Wednesday and Monday-Wednesday of Holy Week; Thursday-Saturday are the Sacred Triduum, entry 2, cited separately. Rogation Monday and Tuesday keep the ordinary ferial rank of their season (RG 88: "de Litaniis minoribus nihil fit in Officio") rather than a fixed class, since no RG 91 entry ranks them specially. A module-type constraint proves Temporal_ef satisfies the kernel RITE contract.
* rite(ef): pin down floor_div and week/sunday_slug agreementLukasz Kasprzak2026-08-111-14/+18
| | | | | | | | | Task 12 review: add a permanent regression test for floor_div's negative branch (Ash Wednesday, 4 days before the Lent I origin -- the only date in the system where it fires), and stop sunday_slug from independently recomputing the Pentecost-relative week number that week already computes. A cross-check test pins the two together before the refactor and continues to guard against future duplication.
* rite(ef): Sunday slugs, week numbering and the resumed-Sunday tailLukasz Kasprzak2026-08-112-0/+90
| | | | | | | | Week origins are Sundays, so week numbers are constant Sunday-to-Saturday; the origin is season-specific, which is why Validate must not assume a run starts at 1. When Easter is early the surplus Sundays after Pentecost resume the Sundays after Epiphany that Septuagesima cut short, and the last Sunday before Advent always keeps the 24th (Last) Mass.
* rite(ef): fix RG 91 citation gaps in named temporal daysLukasz Kasprzak2026-08-111-8/+17
| | | | | | | | | | | | | | | Circumcision (1 Jan) is the Octave Day of the Nativity, RG 91 entry 5, the same table entry as the Nativity vigil -- not covered by the entries-1-3 group it sat under. Passion Sunday, Palm Sunday and Low Sunday are RG 91 entry 6 (I-class Sundays of Passiontide and Low Sunday); Ash Wednesday is entry 7 (I-class ferias). All five branches now carry their own citation, and the function-level comment states the full coverage instead of a narrower one. Also corrects the Nativity-octave range from RG 64-70 to RG 63-70, matching the register's own citation for the octave rules. Comment-only change; behaviour is unaffected.
* rite(ef): named temporal days, vigils and the Nativity octaveLukasz Kasprzak2026-08-112-0/+58
| | | | | | | | | | The I-class feasts of the Lord (RG 91 entries 1-3), the Nativity, Ascension and Pentecost vigils (RG 28-34), and the days within the Octave of the Nativity (RG 64-70). Christ the King is the last Sunday of October per the 1960 calendar, not the OF's last Sunday before Advent. Rogation Wednesday coincides with the Ascension vigil; with no precedence framework until Plan 3, temporal emits the higher-ranked vigil.
* rite(ef): season boundaries per RG 71-77Lukasz Kasprzak2026-08-112-0/+60
| | | | | | | | Christmas Time runs to 13 January inclusive (RG 72-73) and time after Epiphany opens on 14 January (RG 77), diverging from lectio, which starts time-after-epiphany at 6 January. Holy Saturday stays in Passiontide: the Easter Vigil is a night Mass, and a per-day calendar assigns a date by the season governing its day-hours.
* rite(ef): season and rank vocabulary per RG 71-77 and RG 8Lukasz Kasprzak2026-08-113-0/+96
| | | | | | | Eight seasons in canonical liturgical-year order, each carrying its RG citation, and the four classes. season_slug_word is deliberately distinct from season_to_string: slugs are lectionary keys adopted verbatim from lectio, which calls Paschaltide 'easter' and Christmastide 'christmas'.
* fix(record): derive headers and to_row from a single columns listLukasz Kasprzak2026-08-111-4/+17
| | | | | | | | | Make alignment impossible: both headers and to_row are derived from a single list of (name, extractor) pairs, so reordering one without the other is impossible. CSV schema cannot silently mislabel columns. Add a meaningful test that pins the header names in order, not just length. This catches column reordering regressions.
* kernel(record): flat all-string canonical output viewLukasz Kasprzak2026-08-112-0/+63
| | | | | | | The boundary where rite-parametric types stop. CSV, JSON and the template engine all render from this one schema, so they never see a type variable. headers/to_row cover the scalar columns; names and citations are variable-arity and wait for the richer encoders in Plan 5.
* kernel(overlay): ordered layer-merge algebra with diagnosticsLukasz Kasprzak2026-08-112-0/+138
| | | | | | | add/suppress/replace/field-edit folded in order, last writer wins per field, empty the identity. A directive naming an unknown slug, or adding one that already exists, yields a diagnostic rather than silence or a hard failure: overlays must survive a shifted base while still surfacing authoring errors.
* kernel(layer): sanctoral layer with canonical order and date indexLukasz Kasprzak2026-08-112-0/+81
| | | | | | | Entries sort by slug so equal layers serialise identically. The by-date index is built once per layer rather than per year, since fixed dates are year-independent; a full-domain sweep would otherwise rescan every entry for every day. load turns parse and validation failures into result.
* kernel: correct false compiler-constraint claim in Celebration commentLukasz Kasprzak2026-08-111-2/+6
| | | | | | | | | | The comment explaining Celebration's single type parameter claimed OCaml rejects a type variable that appears in no field. That is false: a phantom season parameter compiles cleanly. The real reason is a design choice, not a compiler constraint -- a celebration has no season of its own (season is contextual to the day, and lives in Temporal.t), and a phantom parameter would carry no information while forcing every consumer to thread a meaningless variable.
* kernel: Vocab, Celebration and Temporal parametric typesLukasz Kasprzak2026-08-116-0/+124
| | | | | | | | Rite specificity is carried by type parameters plus a vocab record of operations rather than by functors: the same guarantee that a rite cannot name another rite's season, without threading module plumbing through every kernel module. Celebration takes only the rank parameter, since it has no season field and OCaml rejects a type variable that appears in no field.
* kernel: fix sexp deriving, add missing tests, canonicalize removeLukasz Kasprzak2026-08-116-74/+13
| | | | | | | | | | | | | Use [@@deriving sexp] with open Sexplib0.Sexp_conv instead of hand-rolling converters (fixes non-standard Citation shape and missing field validation). Names.t_of_sexp wraps derived version to enforce canonical sort on load. Add tests: - Names of_list duplicate handling - Names sexp canonical sort guarantee (identical serialization) - Names and Date_spec sexp roundtrips Fix Names.remove to canonicalize output (defensive against non-canonical input).
* kernel: Names, Citation and Date_specLukasz Kasprzak2026-08-116-0/+161
| | | | | | | Names is an open language-keyed assoc kept in canonical order so equal name sets serialise identically. Citation carries references only, never text. Date_spec ships the one form the EF sanctoral needs; 29 February is constructible and resolves to None in common years.
* kernel: Slug and Lang validated private stringsLukasz Kasprzak2026-08-114-0/+79
| | | | | | Both parse through a smart constructor returning result, and both hand-write t_of_sexp so a malformed value in a data file is rejected at load rather than silently accepted -- deriving the converter would have bypassed validation.
* kernel: Colour and Subject shared vocabularyLukasz Kasprzak2026-08-114-0/+39
| | | | | | The six liturgical colours and the Lord/BVM/saint/temporal distinction are common to both Roman forms, so they are shared closed variants rather than rite-parametric. Subject is so named because class is an OCaml keyword.
* kernel(date): ISO-8601 rendering, validating parse, sexp convertersLukasz Kasprzak2026-08-113-3/+42
| | | | | | | Adds sexplib and ppx_sexp_conv to the project and wires the ppx into the kernel library. Date's sexp form is an ISO-8601 atom rather than the opaque rata die, so data files stay human-editable and parsing revalidates the 1583..9999 domain.
* kernel(computus): Easter-relative movable-feast anchorsLukasz Kasprzak2026-07-312-0/+17
| | | | | | Ash Wednesday/Palm Sunday/Ascension/Pentecost/Corpus Christi as Easter+/-N. Verified vs 2026 dates; exhaustive weekday invariants 1583..9999 (Ash Wed=Wed, Ascension/Corpus Christi=Thu, Palm/Pentecost=Sun).
* kernel(computus): Gregorian + Julian EasterLukasz Kasprzak2026-07-312-0/+40
| | | | | | | Anonymous Gregorian (Meeus/Jones/Butcher) for OF+EF; Meeus Julian mapped to the proleptic-Gregorian date for future eastern rites. Verified vs known dates (2000/2024-27, 1583; Orthodox 2023/24) and EXHAUSTIVELY over 1583..9999: every Easter is a Sunday in [Mar22,Apr25].
* kernel(date): proleptic Gregorian date, validated make + arithmeticLukasz Kasprzak2026-07-312-0/+81
| | | | | | | Hinnant civil<->days rep (1970-epoch rata die); make validates month/day and the 1583..9999 domain; of_rata/add_days are total arithmetic. Weekday, compare. Tested: known weekdays, leap boundaries, rejects; qcheck round-trip / add-inverse / weekday-cycle properties over random in-range dates.
* chore: scaffold dune project (kernel lib + cli + tests)Lukasz Kasprzak2026-07-311-0/+2
OCaml 5.2.0 local switch; colitur_kernel library, a colitur executable stub, and an alcotest+qcheck test runner. AGPL LICENSE, README, generated colitur.opam.