diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-19 22:26:33 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-19 22:26:33 +0200 |
| commit | 7fd042f547582801d39e33718e1d3a6e7f2078b3 (patch) | |
| tree | 4eb03cd4481e5e03128945d0d428359528eb1361 /test/test_lang_coverage.ml | |
| parent | d72868ab9ea4f3170eff22a731fdc171469eddf7 (diff) | |
| download | colitur-7fd042f547582801d39e33718e1d3a6e7f2078b3.tar.gz colitur-7fd042f547582801d39e33718e1d3a6e7f2078b3.zip | |
feat(lang): walk commemorations and transfers, name every slug they surface
test_lang_coverage.ml's own coverage test used to walk only the OBSERVED
day of each date (one Celebration.t per Liturgical_day.t). A liturgical
day also carries a second stream of slugs -- commemorations (kept when the
observed day does not fully displace a losing candidate, RG 108-111) and
transfers (an impeded I/II-class feast moved to a later date, RG 96-98) --
and nothing here ever looked at them. The test asserted coverage of what
it happened to WALK, not of what the engine can EMIT, so it passed green
while the ordo booklet printed raw slugs ("Commemoratio canute-martyr",
"Commemoratio maur-abbot", "Commemoratio peter"). test_lang_coverage.ml
now walks observed, every entry in commemorations, transferred_in, and
every entry in transferred_out.
That extension turned up 120 slugs with no Latin name across 2020-2045,
now added to lang/la.ini: 112 are data/ef/sanctoral.sexp companions the
temporal-only walk never reached; 5 (barbara, commemoration-of-st-peter,
commemoration-of-the-seven-sorrows, major-litanies, rogation-wednesday)
are data/ef/adjustments.sexp's own hand-authored Add directives; 3
(ef-nativity-octave-day-2/3/4) are temporal days with no calendarium
heading to transcribe, built by the same pattern days 5-7 already use.
Seven of the sanctoral names are cited to docs/research/scan1.txt rather
than LT.txt: the 2006 web-capture transcription silently drops several
real commemorations that both photographic scans carry (donatus, romanus,
eusebius-confessor, naboris-et-felicis, sts-gervasius-and-protasius,
sts-felix-and-adauctus, and praxedis-virginis -- the last for a spurious
ligature LT.txt introduces, "Praxedis" confirmed correct against both
scans). The same 120 names, extracted verbatim from sanctoral.sexp's and
adjustments.sexp's own English fields rather than retyped, are added to
lang/en.ini.
make check-citations: 400 LT.txt citations checked, 0 wrong, 0 malformed,
0 cannot verify. Teeth proved by deleting canute-martyr's own name (a
Commemoration_only slug that can never be the observed day, only ever a
commemoration) and confirming the coverage test fails naming exactly that
slug, then restoring it.
Diffstat (limited to 'test/test_lang_coverage.ml')
| -rw-r--r-- | test/test_lang_coverage.ml | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/test/test_lang_coverage.ml b/test/test_lang_coverage.ml index 96a3383..34758b2 100644 --- a/test/test_lang_coverage.ml +++ b/test/test_lang_coverage.ml @@ -20,7 +20,27 @@ let la () = Task 3 restricted this to "^ef-" slugs only (la.ini's [celebration] table carried the temporal half alone at the time); Task 4 added the sanctoral half and REMOVED that filter -- every slug is now in scope, with no - exceptions. *) + exceptions. + + Task 5 CLOSED A SECOND BLIND SPOT: this test used to walk only the + OBSERVED day (one Celebration.t per date). A Liturgical_day.t also + carries a whole second stream of slugs -- commemorations (kept when the + observed day does not fully displace a losing candidate, RG 108-111) and + transfers (an impeded I/II-class feast moved to a later date, RG 96-98). + The ordo booklet printed raw slugs ("Commemoratio canute-martyr", + "Commemoratio maur-abbot", "Commemoratio peter") precisely because + nothing here ever looked at [commemorations], [transferred_in] or + [transferred_out] -- the test asserted coverage of what it happened to + WALK, not of what the engine can EMIT. Now walks all four fields, so any + slug reachable through any of them is in scope. *) +let slugs_of_day (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t) = + let open Colitur_kernel in + let slug (c : _ Celebration.t) = Slug.to_string c.Celebration.slug in + (slug d.Liturgical_day.observed) + :: List.map (fun (c, _priv) -> slug c) d.Liturgical_day.commemorations + @ (match d.Liturgical_day.transferred_in with None -> [] | Some c -> [ slug c ]) + @ List.map (fun (c, _date) -> slug c) d.Liturgical_day.transferred_out + let test_every_slug_has_a_latin_name () = let t = la () in let layer = match Test_support.load_ef_layer () with Ok l -> l | Error e -> Alcotest.failf "%s" e in @@ -28,19 +48,18 @@ let test_every_slug_has_a_latin_name () = let missing = ref [] in for y = 2020 to 2045 do Array.iter - (fun (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t) -> - let slug = - Colitur_kernel.Slug.to_string - d.Colitur_kernel.Liturgical_day.observed.Colitur_kernel.Celebration.slug - in - (* A miss returns the key itself, so name = slug means "no entry". *) - if L.celebration t slug = slug && not (List.mem slug !missing) then - missing := slug :: !missing) + (fun d -> + List.iter + (fun slug -> + (* A miss returns the key itself, so name = slug means "no entry". *) + if L.celebration t slug = slug && not (List.mem slug !missing) then + missing := slug :: !missing) + (slugs_of_day d)) (Colitur_kernel.Calendar.year ctx layer y) done; if !missing <> [] then - Alcotest.failf "%d slugs have no Latin name, e.g. %s" (List.length !missing) - (String.concat ", " (List.filteri (fun i _ -> i < 5) !missing)) + Alcotest.failf "%d slugs have no Latin name: %s" (List.length !missing) + (String.concat ", " (List.sort compare !missing)) let test_vocabularies_are_complete () = let t = la () in |
