| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Task 14 review, findings 1 and 2.
Finding 1: the only tests against Validate exercised the clean path against
real EF data, so the evidence that each check can actually fire lived in a
scratch mutation probe that was never committed. A future edit that quietly
weakened a check would leave the suite green, since a weaker check only
makes more inputs pass. Added a small synthetic two-season, two-rank rite
fixture in test_validate.ml -- not EF -- letting each test violate exactly
one invariant directly: a temporal that raises (coverage), a season that
recurs (seasons), a week that decreases mid-run (week), a weekday that
disagrees with Date.weekday (weekday), a rank absent from the declared vocab
(rank), and a colour outside Colour.all (colour, via a same-representation
Obj.magic value, safe here because the check compares by structural equality
rather than pattern match). A clean-baseline test confirms the fixture itself
reports zero failures before any mutation is applied.
Each new test was verified non-vacuous by temporarily weakening its
corresponding check in validate.ml, confirming the matching test fails, then
reverting -- the same trap one level up, checked explicitly rather than
assumed.
Finding 2: removed the slug well-formedness check. Slug.t is a private string
validated on every construction path, and to_string is the identity, so
round-tripping an existing Slug.t can never fail -- the check was structurally
incapable of firing. Folded the explanation into the comment block that
already covers why slug uniqueness isn't checked, since it's the same kind of
fact: a property the type system delivers, not one Validate needs to assert.
The colour check stays: unlike slug, Colour.all is a hand-maintained list
that can drift from the type, so it is only practically (not structurally)
tautological, the same class as the rank closure check.
|
| |
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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'.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
| |
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].
|
| |
|
|
|
|
|
| |
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.
|
|
|
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.
|