summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 01:42:00 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 01:42:00 +0200
commit254cfd7d9111b0f23f9c44e82d3e31d5817dc5a4 (patch)
treea14a1e43e95d5bb3b03cd9832776461ea9440605 /tools
parenta2654a1e4d8987a251bcefbad2b0f0b867a6c6e6 (diff)
parent0f6454c123f1514c1cf255faed8d9b8c752c6347 (diff)
downloadcolitur-254cfd7d9111b0f23f9c44e82d3e31d5817dc5a4.tar.gz
colitur-254cfd7d9111b0f23f9c44e82d3e31d5817dc5a4.zip
Merge branch 'ef-rebootstrap': re-bootstrap the sanctoral, refresh the differential
Re-bootstraps data/ef/sanctoral.sexp from lectio's corrected generator (322 -> 327 entries), propagating fixes colitur had inherited wholesale: 15 entries wrongly marked commemoration-only that are really III-class feasts, four entries missing entirely, six commemorations an electronic transcription had hidden, and two class corrections. 38639 days change across 1583-9999, in three shapes with no remainder: 2245 where a III-class feast now correctly beats a class-4 feria, 35174 where one of five restored commemorations appears, and 1220 on 13 January. All five restored entries were verified against a photographic scan -- real, correctly ranked, and confined to their own dates. 13 January is NOT fixed by this. It moves from one wrong answer to a different one, because RG 112 and a Holy Family office are both unbuilt. Recorded as its own allow-list entry with a citation and a count, rather than left inside a season-boundary entry's cardinality pin, and deliberately not pinned by a golden test. Then refreshes the lectio differential fixture, which predated the seven EF defects fixed in that project. Nine allow-list entries close -- each was a real divergence adjudicated in colitur's favour, and each closes because lectio was fixed, with its RG citation preserved. The list goes from twelve entries to four; the remaining 540 differences are fully attributed with none unexplained.
Diffstat (limited to 'tools')
-rw-r--r--tools/bootstrap_sanctoral.ml41
1 files changed, 33 insertions, 8 deletions
diff --git a/tools/bootstrap_sanctoral.ml b/tools/bootstrap_sanctoral.ml
index 19adc0b..4868c6c 100644
--- a/tools/bootstrap_sanctoral.ml
+++ b/tools/bootstrap_sanctoral.ml
@@ -94,8 +94,10 @@ let parse_slug sec =
| Ok s -> s
| Error e -> die "section [%s]: invalid slug: %s" sec.name e
-(* All 322 entries use plain MM-DD (spec §4.1); anything else is a date form
- the mapping does not cover. *)
+(* Every entry uses plain MM-DD (spec §4.1; 327 of them as of the
+ 2026-08-12 ef-rebootstrap, up from 322 -- this rule itself is about the
+ date FORM, not a count, so it does not go stale as entries are added or
+ removed); anything else is a date form the mapping does not cover. *)
let parse_date sec =
let raw = field sec "date" in
match String.split_on_char '-' raw with
@@ -140,10 +142,15 @@ let parse_colour sec =
(* class = lord|bvm|saint -> Subject.t; absent -> Subject.Saint (decision 1:
Celebration.make's kernel default is Subject.Temporal, correct for the
temporal cycle and wrong for every sanctoral entry -- overridden here,
- never left to the default). Only 6 of 322 entries carry an explicit
- class in the source, and all 6 are "lord" as of this bootstrap; bvm/saint
- are mapped in case a future lectio update adds one, but "temporal" is
- rejected -- no sanctoral entry is the temporal cycle's own office. *)
+ never left to the default). Only 6 of 327 entries carry an explicit
+ class in the source (STALE DENOMINATOR CORRECTED, ef-rebootstrap fix
+ round 1, F6 -- was "6 of 322"; the count of 6 itself did not move, but
+ WHICH six did: the 2026-08-12 re-bootstrap dropped `class = lord` from
+ `most-holy-name-of-mary` and added it to
+ `commemoration-of-the-baptism-of-the-lord`, a straight swap, net zero),
+ and all 6 are "lord" as of this bootstrap; bvm/saint are mapped in case
+ a future lectio update adds one, but "temporal" is rejected -- no
+ sanctoral entry is the temporal cycle's own office. *)
let parse_subject sec =
match field_opt sec "class" with
| None -> Subject.Saint
@@ -155,10 +162,28 @@ let parse_subject sec =
| Some s -> s
| None -> die "section [%s]: unknown class %S" sec.name raw)
+(* name.en is always required; name.pl is not -- the 2026-08-12 re-bootstrap
+ (RG16(a) blast-radius task) found 5 of the source's 327 entries missing
+ it outright, 322 still carrying it (CORRECTED, fix round 1, F6: was "5
+ of the source's 322 entries" -- the source has 327, of which 5 lack
+ name.pl and 322 have it; the 322 is a coincidence of the OLD total, not
+ the new one) (agnes-secundo, boniface-martyr, eusebius-confessor, evaristus,
+ theodore -- all 5 either newly added or newly un-hidden by lectio's own
+ generator fix, never previously reachable through this tool at all, since
+ every entry the OLD ini shipped happened to carry both languages). Prior
+ to this the field was unconditionally required (`field sec "name.pl"`,
+ which `die`s on absence) -- correct for a byte-faithful mirror of a
+ source that always had it, wrong once the source legitimately does not:
+ Names.t itself is an open, per-language assoc list (names.mli) with no
+ rule that every entry must carry every language colitur happens to know
+ about, so requiring pl here was this tool's own invented constraint, not
+ a kernel one. Falling back to en-only (never a placeholder string) is the
+ same posture the kernel takes elsewhere for a genuinely absent field. *)
let parse_names sec =
let en = field sec "name.en" in
- let pl = field sec "name.pl" in
- Names.of_list [ (Lang.of_string_exn "en", en); (Lang.of_string_exn "pl", pl) ]
+ match field_opt sec "name.pl" with
+ | Some pl -> Names.of_list [ (Lang.of_string_exn "en", en); (Lang.of_string_exn "pl", pl) ]
+ | None -> Names.of_list [ (Lang.of_string_exn "en", en) ]
(* reading.* is deliberately ignored -- Plan 4's lectionary bootstrap. *)
let convert_entry sec : V.rank Layer.entry =