summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--lib/kernel/precedence.mli12
-rw-r--r--lib/kernel/vocab.ml2
-rw-r--r--lib/kernel/vocab.mli2
-rw-r--r--lib/rites/rite_ef/precedence_ef.ml10
-rw-r--r--lib/rites/rite_ef/precedence_ef.mli2
6 files changed, 17 insertions, 14 deletions
diff --git a/README.md b/README.md
index 9b11d73..6f71f6c 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,8 @@ reading citations, correct to year 9999. See the design and rules research under
opam switch create . 5.2.0 -y # first time: local OCaml switch
opam install -y dune alcotest qcheck qcheck-alcotest sexplib ppx_sexp_conv
dune build
-dune test
+dune test # fast suite (~3s)
+COLITUR_EXHAUSTIVE_SWEEP=1 dune test --force # + every year 1583-9999 (~50s)
dune exec colitur -- easter 2026 # Easter and its Easter-relative anchors
dune exec colitur -- temporal 2026 # the EF temporal cycle only, one line per day
dune exec colitur -- day 2026 # the full resolved EF calendar (temporal + sanctoral)
diff --git a/lib/kernel/precedence.mli b/lib/kernel/precedence.mli
index 4225eb7..ae054dd 100644
--- a/lib/kernel/precedence.mli
+++ b/lib/kernel/precedence.mli
@@ -47,11 +47,13 @@ type ('s, 'r) rules = {
{!resolve}'s own [omitted] accounting distinguishes an admitted
candidate from a dropped one by PHYSICAL equality ([==]) on the
candidate value, not structural equality -- a rebuilt record is
- [=] to the original but not [==], so {!resolve} would then count
- it as dropped a SECOND time (once because it is genuinely absent
- from the admitted set, once because its identity no longer
- matches its own admitted copy), silently double-counting rather
- than raising. This obligation previously lived only in one rite's
+ [=] to the original but not [==], so {!resolve} cannot match the
+ rebuilt copy against the original it was given. The celebration
+ then surfaces TWICE in the same day's result -- once in
+ {!resolution.commemorations} (the rebuilt copy, admitted) and once
+ in {!resolution.omitted} (the original, which nothing in the
+ admitted set matches). One admission, double-reported, silently
+ rather than raising. This obligation previously lived only in one rite's
own module documentation (Rite_ef.Precedence_ef.admit); stated
here because this signature -- not any one rite's implementation
of it -- is what an author of the next rite reads. *)
diff --git a/lib/kernel/vocab.ml b/lib/kernel/vocab.ml
index bcb48b8..a4e61a3 100644
--- a/lib/kernel/vocab.ml
+++ b/lib/kernel/vocab.ml
@@ -14,7 +14,7 @@ type ('s, 'r) t = {
carried item 1: EF has each season in one run, but the modern
form's Ordinary Time does not, so the expected run sequence had
to become rite-supplied rather than derived from this field).
- For EF specifically {!Rite_ef.rite_ef.ml} sets season_runs to
+ For EF specifically [Rite_ef.rite] sets season_runs to
this very list, so the two happen to agree there, but Validate
itself no longer reads [seasons] to build its expectation. *)
season_to_string : 's -> string;
diff --git a/lib/kernel/vocab.mli b/lib/kernel/vocab.mli
index bcb48b8..a4e61a3 100644
--- a/lib/kernel/vocab.mli
+++ b/lib/kernel/vocab.mli
@@ -14,7 +14,7 @@ type ('s, 'r) t = {
carried item 1: EF has each season in one run, but the modern
form's Ordinary Time does not, so the expected run sequence had
to become rite-supplied rather than derived from this field).
- For EF specifically {!Rite_ef.rite_ef.ml} sets season_runs to
+ For EF specifically [Rite_ef.rite] sets season_runs to
this very list, so the two happen to agree there, but Validate
itself no longer reads [seasons] to build its expectation. *)
season_to_string : 's -> string;
diff --git a/lib/rites/rite_ef/precedence_ef.ml b/lib/rites/rite_ef/precedence_ef.ml
index fcd2116..db7e708 100644
--- a/lib/rites/rite_ef/precedence_ef.ml
+++ b/lib/rites/rite_ef/precedence_ef.ml
@@ -685,11 +685,11 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate)
than rebuilt ones; undocumented for rite authors" -- documented here,
now that this is the function that note was about). Building a fresh
[{ c with ... }] record anywhere below would silently defeat that
- accounting: the dropped candidate would then match nothing in
- [admitted], and {!Precedence.resolve} would count it as dropped a
- SECOND time (once for real, once because its identity no longer
- matches its own admitted copy) without ever raising -- a silent
- double-count, not a crash, which is exactly why this comment exists. *)
+ accounting: the original would then match nothing in [admitted], so the
+ celebration would surface TWICE in the same day -- once in
+ [commemorations] (the rebuilt copy) and once in [omitted] (the original,
+ which nothing admitted matches). One admission, double-reported, and no
+ crash to announce it, which is exactly why this comment exists. *)
let sorted = List.stable_sort compare_dignity comms in
let is_privileged (_, p) = p = Precedence.Privileged in
let observed_rank = observed.Precedence.cel.Celebration.rank in
diff --git a/lib/rites/rite_ef/precedence_ef.mli b/lib/rites/rite_ef/precedence_ef.mli
index 161d890..55f947e 100644
--- a/lib/rites/rite_ef/precedence_ef.mli
+++ b/lib/rites/rite_ef/precedence_ef.mli
@@ -135,7 +135,7 @@ val sunday_marker : string
can construct: [Vocab_ef.rank] (RG 8) and {!Celebration.status} are both
closed variants, and the five cases above -- an if/else-if chain ending
in the unconditional [Commemorate] catch-all -- exhaust every value
- those two fields can take between them; there is no fifth,
+ those two fields can take between them; there is no sixth,
"unclassified" case the way {!band} needs one, because this function's
own return type has no such slot to fall into by accident. *)
val disposition :