aboutsummaryrefslogtreecommitdiff
path: root/test/test_oracle.ml
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_oracle.ml')
-rw-r--r--test/test_oracle.ml72
1 files changed, 70 insertions, 2 deletions
diff --git a/test/test_oracle.ml b/test/test_oracle.ml
index a86fd76..ae5c396 100644
--- a/test/test_oracle.ml
+++ b/test/test_oracle.ml
@@ -3,6 +3,20 @@
layer 4 of the design spec's five (colitur CLAUDE.md "Validation" section;
layer 3, the lectio differential, is test_differential.ml, already green).
+ *** WIP, 2026-08-13, branch ef-rg112-rg110: this file is EXPECTED RED
+ right now. [Observed_identity_mismatch]/[Observed_identity_unresolved]
+ (below) are new -- this layer used to compare the observed day's rank and
+ colour and stop there, never whether it is actually the RIGHT day (Holy
+ Family, 11 January 2026, is rank 2/white on both sides purely by
+ coincidence -- an ordinary unnamed Sunday and Holy Family share both).
+ Landing the strengthened comparator FIRST, red, before touching any
+ production code, is the point: it is the regression net the rest of this
+ task's fix commits are checked against, not a change bundled in alongside
+ the fix. The very next commits make it green again (data/ef/expected-
+ divergences-missalemeum.sexp's own M-series entries below, and this
+ file's own [layer_m_reason] widening) -- see that file and
+ docs/research/rules-register.md for the running account.
+
*** WHY THIS LAYER EXISTS, AND WHAT IT CAN DO THAT THE LECTIO DIFFERENTIAL
CANNOT (test_differential.ml's own header comment, limit 1) ***
@@ -280,6 +294,15 @@ type colitur_row = {
c_date : string;
c_rank : int;
c_colour : char;
+ c_observed_slug : string;
+ c_observed_name : string option;
+ (** colitur's own resolved English name for the OBSERVED celebration --
+ [None] for a TEMPORAL-origin day (an ordinary Sunday, a feria, a
+ movable named feast: {!Rite_ef.Temporal_ef}'s own [build] never
+ sets [names], the SAME gap this file's header already documents
+ for commemorations, see [Comm_identity_unresolved]), the same
+ [Names.find ... en] read [c_commemorations] below already uses,
+ applied to [LD.observed] instead of a commemoration candidate. *)
c_commemorations : (string * int * Cel.status * string option) list;
(** slug, rank, status, English name *)
}
@@ -321,6 +344,8 @@ let colitur_rows_2026_2027 () =
{ c_date = Date.to_iso8601 day.LD.date;
c_rank = rank_to_int cel.Cel.rank;
c_colour = colour_to_char cel.Cel.colour;
+ c_observed_slug = Slug.to_string cel.Cel.slug;
+ c_observed_name = Names.find cel.Cel.names en;
c_commemorations = commemorations
}
:: !rows
@@ -335,7 +360,15 @@ let colitur_rows_2026_2027 () =
(* header for the mapping and its exact limits. *)
(* ---------------------------------------------------------------------- *)
-type field = Rank | Colour_f | Comm_presence | Comm_count | Comm_identity_mismatch | Comm_identity_unresolved
+type field =
+ | Rank
+ | Colour_f
+ | Comm_presence
+ | Comm_count
+ | Comm_identity_mismatch
+ | Comm_identity_unresolved
+ | Observed_identity_mismatch
+ | Observed_identity_unresolved
let field_name = function
| Rank -> "rank"
@@ -344,6 +377,40 @@ let field_name = function
| Comm_count -> "commemoration-count"
| Comm_identity_mismatch -> "commemoration-identity-mismatch"
| Comm_identity_unresolved -> "commemoration-identity-unresolved"
+ | Observed_identity_mismatch -> "observed-identity-mismatch"
+ | Observed_identity_unresolved -> "observed-identity-unresolved"
+
+(* CORRECTING the gap this file's own header names (added under this task,
+ branch ef-rg112-rg110): the axes above all compare the day's OBSERVED
+ celebration's rank and colour ([Rank]/[Colour_f]) and the admitted
+ COMMEMORATIONS' identity ([Comm_identity_*]) -- nothing until now compared
+ the OBSERVED celebration's own identity, WHICH day is actually being kept,
+ only what class/colour it happens to carry. Holy Family (11 January 2026:
+ oracle title "The Holy Family: Jesus, Mary & Joseph", colitur's own
+ observed slug the plain "ef-time-after-epiphany-sunday-1", BOTH rank 2 and
+ colour white on both sides) is exactly the shape this axis exists to
+ catch -- rank and colour already agreed by coincidence (an ordinary,
+ unnamed II-class Sunday and Holy Family share both), so nothing above
+ ever saw a difference. Same mapping and the same honesty about its limit
+ as [identity_diff] just above: colitur identifies a day by SLUG,
+ missalemeum by an English TITLE string, and the bridge is
+ {!Celebration.t}.names, read directly off [LD.observed] by
+ [colitur_rows_2026_2027] into [c_observed_name] -- resolvable for a
+ SANCTORAL-origin observed day (a saint's feast winning the day outright),
+ NEVER for a TEMPORAL-origin one (an ordinary Sunday, a feria, a movable
+ named feast -- {!Rite_ef.Temporal_ef}'s own [build] never sets [names]).
+ [Observed_identity_unresolved] is that TEMPORAL-origin case: counted and
+ reported, never silently skipped, the same discipline
+ [Comm_identity_unresolved] already established and the brief demands
+ again here ("a day whose observed identity cannot be resolved must be a
+ counted, allow-listed outcome, never a silent skip"). Unlike commemoration
+ identity, this axis needs no presence/count gate first -- there is always
+ exactly one observed day on each side, no list-length ambiguity to
+ resolve before a title comparison is even meaningful. *)
+let observed_identity_diff (c : colitur_row) (o : oracle_row) =
+ match c.c_observed_name with
+ | None -> Some Observed_identity_unresolved
+ | Some name -> if String.equal name o.o_title then None else Some Observed_identity_mismatch
(* Identity (Task B): only even attempted once presence AND count already
agree (both non-empty, same length) -- see this file's own header,
@@ -378,7 +445,8 @@ let diff_fields (c : colitur_row) (o : oracle_row) =
(if c_has && o_has && List.length c.c_commemorations <> List.length o.o_commemorations then
Some Comm_count
else None);
- identity_diff c o
+ identity_diff c o;
+ observed_identity_diff c o
]
(* ---------------------------------------------------------------------- *)