diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-12 10:26:11 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-12 10:26:11 +0200 |
| commit | 7ac8a25700c9d930eaaa4f9895665248dac32c52 (patch) | |
| tree | cea70d0a68234ac928ddf538ec7dc287ad96f9da | |
| parent | 3159bed3c71c35fecc141cfd1453e27b6a4a3780 (diff) | |
| download | colitur-7ac8a25700c9d930eaaa4f9895665248dac32c52.tar.gz colitur-7ac8a25700c9d930eaaa4f9895665248dac32c52.zip | |
docs(citations): migrate register line-number pointers to stable anchors
68 "register line N" pointers in tracked code and data cited the
register's line numbers directly. The register has moved since: line 334
(cited six times as RG 91 entry 8) is now rose/colour prose; lines
375-376 (cited as "RG 109 leaves Advent/Lent Ember ordinary") are now
RG 26, the paragraph that refutes that exact reading; line 374 (cited as
RG 109(a)) is now RG 25's Latin; line 378 (RG 111) is blank.
expected-divergences.sexp even wrote "RG 91 line 332" three times, as
though the line offset were part of the rubric's own identity. Since
docs/research/rules-register.md is gitignored, no reader of the public
repo could resolve any of these, and -- since the register has moved on
its own copy too -- neither can the author's.
Replaced every pointer with an anchor that survives editing: the RG
paragraph/entry number itself (already present in nearly every case,
since the citation text already names "RG 91 entry N" or "RG 109(a)"
next to the stale line number -- the line number was redundant, not
load-bearing) plus a "§4" or quoted-subsection-heading pointer into the
register for readers who want to locate the fuller discussion. Also
corrected one genuinely stale content error found while migrating its
anchor: test_precedence_ef.ml's RG33 disposition-cases comment still said
"a I/II-class vigil impeded by any Sunday" -- the pre-Task-16
mistranscription the register itself corrects to II/III class; fixed the
prose alongside its citation, since leaving a wrong RG-class claim next
to a freshly-verified anchor would be worse than the stale line number it
replaced.
Covers lib/rites/rite_ef/precedence_ef.ml (18), precedence_ef.mli
(already fixed with item 1), test/test_precedence_ef.ml (44, including
two instances that only word-wrapped "register\nline N" across a line
break and so did not match a same-line grep), and
data/ef/expected-divergences.sexp (5, including three "RG 91 line 332"
instances). All 68 original pointers resolved -- none needed guessing;
every citation's target rule was already named in the surrounding prose.
No behaviour change: every edit is a comment/citation/data-note change.
Verified byte-identical `colitur day` output across 1583, 1900, 1902,
2008, 2011, 2026, 2038, 9999. 259/259 tests green.
| -rw-r--r-- | data/ef/expected-divergences.sexp | 10 | ||||
| -rw-r--r-- | lib/rites/rite_ef/precedence_ef.ml | 37 | ||||
| -rw-r--r-- | test/test_precedence_ef.ml | 97 |
3 files changed, 72 insertions, 72 deletions
diff --git a/data/ef/expected-divergences.sexp b/data/ef/expected-divergences.sexp index 6b7bbdd..c8d863d 100644 --- a/data/ef/expected-divergences.sexp +++ b/data/ef/expected-divergences.sexp @@ -20,15 +20,15 @@ ((id C1) (citation "RG 72-73 (Nativity/Epiphany season boundary, Jan 1-13) + RG 119a (white through \"expletum tempus Epiphaniae\"); register §3c item 1") (verdict colitur) - (note "6-13 January is Christmastide in colitur, matching RG 72-73's explicit boundary at 13 January (corroborated independently by RG 119a's colour rule, register lines 241-246). lectio's efSeason switches to time-after-epiphany on 6 January. The season disagreement cascades into colour (green vs white) and, on 7-8 January specifically, into the ferial slug family name (colitur's ef-christmas-2-<weekday> vs lectio's ef-time-after-epiphany-1-<weekday> for the same two days).") + (note "6-13 January is Christmastide in colitur, matching RG 72-73's explicit boundary at 13 January (corroborated independently by RG 119a's colour rule, §3b). lectio's efSeason switches to time-after-epiphany on 6 January. The season disagreement cascades into colour (green vs white) and, on 7-8 January specifically, into the ferial slug family name (colitur's ef-christmas-2-<weekday> vs lectio's ef-time-after-epiphany-1-<weekday> for the same two days).") (expected_rows 368)) ((id C2) - (citation "RG 91 line 332 (\"Sundays of Advent, Lent, Passiontide, and Low Sunday\" -- I class, unqualified); extends register §3c item 4 (stated there for Advent only) to Lent on the same textual basis") + (citation "RG 91 entry 6, §4 (\"Sundays of Advent, Lent, Passiontide, and Low Sunday\" -- I class, unqualified); extends register §3c item 4 (stated there for Advent only) to Lent on the same textual basis") (verdict colitur) - (note "Advent II & IV and Lent I-III are I class in colitur, matching RG 91's own unqualified line 332 (already confirmed for Passion Sunday, Palm Sunday, Low Sunday and Advent I, where lectio agrees). lectio's temporal_ef.go generic Sunday branch assigns Class2 and special-cases only Advent I, Passion/Palm/Low Sunday -- a lectio gap for the remaining five Sundays this entry covers.") + (note "Advent II & IV and Lent I-III are I class in colitur, matching RG 91's own unqualified entry 6 (already confirmed for Passion Sunday, Palm Sunday, Low Sunday and Advent I, where lectio agrees). lectio's temporal_ef.go generic Sunday branch assigns Class2 and special-cases only Advent I, Passion/Palm/Low Sunday -- a lectio gap for the remaining five Sundays this entry covers.") (expected_rows 215)) ((id C3) - (citation "RG 91 line 332 (same I-class Sunday rule as C2) + RG 131 (rose indult, Gaudete/Laetare, \"in Officio et Missa diei dominici tantum\")") + (citation "RG 91 entry 6, §4 (same I-class Sunday rule as C2) + RG 131 (rose indult, Gaudete/Laetare, \"in Officio et Missa diei dominici tantum\")") (verdict colitur) (note "Gaudete (Advent III) and Laetare (Lent IV): I class per C2's citation, plus the RG 131 rose indult. lectio has no Rose case in its EF colour function and zero rose rows in tridentine-calendar.ini -- Rose exists only on lectio's OF path -- so it prints violet for both Sundays.") (expected_rows 89)) @@ -58,7 +58,7 @@ (note "Rogation Monday and Tuesday exist as colitur's own ef-rogation-{monday,tuesday} slugs (violet) whenever no higher-ranked saint intervenes. lectio computes no Rogation days at all and shows the plain paschaltide-week-6 feria instead.") (expected_rows 31)) ((id C9) - (citation "RG 95 (translation is a right of I-class FEASTS only) + RG 91 line 332 (Sundays are a separate table row, not feasts) + RG 109(a) (\"of a Sunday\" is a privileged commemoration, presupposing the Sunday stays put) + RG 96 (the general translation walk) -- the same reasoning already fixed for the analogous impeded-Sunday defect in Precedence_ef (Task 9)") + (citation "RG 95 (translation is a right of I-class FEASTS only) + RG 91 entry 6, §4 (Sundays are a separate table row, not feasts) + RG 109(a) (\"of a Sunday\" is a privileged commemoration, presupposing the Sunday stays put) + RG 96 (the general translation walk) -- the same reasoning already fixed for the analogous impeded-Sunday defect in Precedence_ef (Task 9)") (verdict colitur) (note "St Joseph (19 March, I class) colliding with a Lent Sunday (I class per C2): colitur keeps the Sunday observed and transfers Joseph to the next free day (usually 20 March; in years the walk is congested enough to cross Easter, as far as 1 April -- 2008, 2035, 2046, independently pinned by this project's own transfer tests). lectio instead puts Joseph ON the Sunday, displacing the Lenten Sunday office RG 95 says cannot be displaced by a translated feast.") (expected_rows 15)) diff --git a/lib/rites/rite_ef/precedence_ef.ml b/lib/rites/rite_ef/precedence_ef.ml index 3c417bb..9997bb2 100644 --- a/lib/rites/rite_ef/precedence_ef.ml +++ b/lib/rites/rite_ef/precedence_ef.ml @@ -152,7 +152,7 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc (* 7: I-class ferias not above -- Ash Wednesday; Mon/Tue/Wed of Holy Week. Thu-Sat of Holy Week are the Triduum, entry 2 above, not this entry. *) else if is_temporal && rank = Class1 && (off = -46 || (off >= -6 && off <= -4)) then 7 - (* 8: All Souls -- register line 334's own text carries a qualifier this + (* 8: All Souls -- RG 91 entry 8's own text (§4) carries a qualifier this transcription must honour: "yields to an occurring Sunday". 2 November is always Time_after_pentecost (well clear of Advent/Lent/Passiontide and of every other entry's own Easter-relative or fixed date), so a @@ -182,9 +182,9 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc not the universal layer (11), and marked as an indult overlay (12's "not indult" test having just failed). *) else if (not is_temporal) && (not is_vigil) && rank = Class1 then 13 - (* 14: Feasts of the Lord, II class -- register line 341, deliberately - UNQUALIFIED (contrast entry 16 at line 342, which explicitly says "not - of the Lord"; RG 37c, register line 393, speaks of "II-class feasts of + (* 14: Feasts of the Lord, II class -- RG 91 entry 14, deliberately + UNQUALIFIED (contrast entry 16, which explicitly says "not + of the Lord"; RG 37c (§4, "Sundays") speaks of "II-class feasts of the Lord" replacing an occurring II-class Sunday with no universal qualifier either). No layer test here, unlike 11/12/13 and 16/19/20: the register does not split this entry into universal/proper/indult, @@ -232,7 +232,7 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc Office (RG 88, see temporal_ef.ml's [temporal]), so those never carry this entry unless they happen to fall on the Saturday itself. Excludes vigils for the same reason 11-13/14/16/19/20/23/24 do: RG 91 has no - IV-class vigil at all (its own vigil list, register lines 381-384, + IV-class vigil at all (RG 91's own vigil list, §4 "Vigils", stops at III class), so one would be an anomaly, not this entry. *) else if is_temporal && (not is_vigil) && rank = Class4 && weekday = Date.Sat then 27 (* 28: IV-class ferias -- the unqualified catch-all (temporal_ef.ml's own @@ -339,7 +339,7 @@ let impedes_vigil (winner : Vocab_ef.rank Precedence.candidate) = let nativity_octave_prefix = "ef-nativity-octave-day-" (* RG 109's own three named seasons for (e), "of ferias of Advent, Lent and - Passiontide" (register line 376) -- temporal_ef.ml's generic + Passiontide" (§4, "Commemorations") -- temporal_ef.ml's generic <season>-<week>-<weekday> ferial fallback slugs, whose season word is [season_slug_word]'s output for exactly these three (vocab_ef.ml: Advent and Passiontide are unmodified [season_to_string]; Lent likewise). Also @@ -349,7 +349,7 @@ let nativity_octave_prefix = "ef-nativity-octave-day-" [universal_layer] -- private: nothing outside [privilege_of] needs it. *) let alp_feria_prefixes = [ "ef-advent-"; "ef-lent-"; "ef-passiontide-" ] -(* RG 109 (register lines 374-377, docs/research/rules-register.md §4): the +(* RG 109 (docs/research/rules-register.md §4, "Commemorations"): the closed list of privileged commemorations, checked in the register's own lettered order. A candidate matching none of (a)-(f) is ordinary, per the register's own closing sentence, "All others are ordinary." Read entirely @@ -374,10 +374,10 @@ let privilege_of (c : Vocab_ef.rank Precedence.candidate) : Precedence.privilege let slug = Slug.to_string cel.Celebration.slug in let is_temporal = c.Precedence.origin = Precedence.Temporal in let open Vocab_ef in - (* (a) register line 374: "of a Sunday" -- the same slug marker RG 33's + (* (a) RG 109(a) (§4): "of a Sunday" -- the same slug marker RG 33's [impedes_vigil] already reads to answer "is this candidate a Sunday". *) if is_sunday_slug slug then Precedence.Privileged - (* (b) register line 374-375: "of a I-class day" -- the candidate's own + (* (b) RG 109(b) (§4): "of a I-class day" -- the candidate's own rank. In this codebase's current disposition rules the ONLY way a [Class1] candidate ever reaches [Commemorate] at all is via [Celebration.status = Commemoration_only] (a plain [Feast]-status @@ -385,17 +385,17 @@ let privilege_of (c : Vocab_ef.rank Precedence.candidate) : Precedence.privilege branch is real but its only reachable witness today is that shape; see the task report. *) else if rank = Class1 then Precedence.Privileged - (* (c) register line 375: "of days within the Octave of the Nativity". *) + (* (c) RG 109(c) (§4): "of days within the Octave of the Nativity". *) else if is_temporal && String.starts_with ~prefix:nativity_octave_prefix slug then Precedence.Privileged - (* (d) register line 375-376: "of September Ember days" -- named on its + (* (d) RG 109(d) (§4): "of September Ember days" -- named on its own because September falls entirely outside (e)'s three seasons (Advent/Lent/Passiontide) under ANY reading, not because it needs excluding FROM (e) the way review round 1's F1/F2 finding corrected the Advent/Lent Ember sets below to no longer need. *) else if is_temporal && String.starts_with ~prefix:september_ember_prefix slug then Precedence.Privileged - (* (e) register line 376: "of ferias of Advent, Lent and Passiontide" -- + (* (e) RG 109(e) (§4): "of ferias of Advent, Lent and Passiontide" -- CORRECTED, fix round 1 (F1/F2): this branch previously excluded the Advent and Lent Ember sets via [not (is_ember_18 slug)], reading RG 109(e)'s bare "feriis Adventus, Quadragesimae" as tacitly narrower than @@ -428,7 +428,7 @@ let privilege_of (c : Vocab_ef.rank Precedence.candidate) : Precedence.privilege it under its own name. *) else if is_temporal && List.exists (fun p -> String.starts_with ~prefix:p slug) alp_feria_prefixes then Precedence.Privileged - (* (f) register line 376-377: "of the Major Rogations, in Mass" -- the + (* (f) RG 109(f) (§4): "of the Major Rogations, in Mass" -- the Major Litanies (25 April, RG 80) are not yet computed anywhere in this codebase (temporal_ef.ml's own comment on [temporal]'s Rogation branch: "The Major Litanies... are a fixed date and are not yet computed; they @@ -478,13 +478,12 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate) cel.Celebration.rank = Class1 && not (is_sunday_slug (Slug.to_string cel.Celebration.slug)) then - (* RG 95 (register lines 323, 363): only I-class FEASTS have the right + (* RG 95 (§4, "Occurrence" and "Transfer/translation"): only I-class FEASTS have the right of translation -- RG 91's own table lists Sundays as a separate row - (entry 6, register line 332) from feasts (entries 11-13, register - lines 337-339), so a Sunday is never a "feast" in RG 95's sense, and + (entry 6) from feasts (entries 11-13), so a Sunday is never a "feast" in RG 95's sense, and [is_sunday_slug] (the same marker RG 33's [impedes_vigil] and RG 109(a)'s [privilege_of] already use) excludes it here. This is the - branch that completes Task 7's All Souls fix (register line 334, RG + branch that completes Task 7's All Souls fix (RG 91 entry 8): All Souls is I class, not a vigil, and not a Sunday slug, so once it loses to an occurring Sunday it still reaches here and transfers -- to 3 November, now DIRECTLY authorised by RG 96 @@ -613,7 +612,7 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate) the temporal Class4 [Omit] branch above because a Sunday is never IV class -- RG 11-12/91 entry 6/15 make every Sunday I or II class, never a "feria" at all in Caput IV's own sense, RG 21): RG 109(a) - (register line 374) lists "of a Sunday" as a privileged commemoration + (§4) lists "of a Sunday" as a privileged commemoration category, which presupposes an impeded Sunday stays put rather than moving to another day the way a feast does -- [privilege_of] tags it [Privileged] via the same [is_sunday_slug] marker, with no further @@ -632,7 +631,7 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate) Precedence.Commemorate (privilege_of loser) (* Task 9: how many of the day's commemorations RG 111 admits, and which - (docs/research/rules-register.md §4, register line 378, "Commemorations" + (docs/research/rules-register.md §4, "Commemorations", RG 111). [band] decides who wins the day; [disposition] decides who is even eligible to be commemorated, and tags each with its RG 109 privilege via [privilege_of]; this decides how many of THOSE survive. diff --git a/test/test_precedence_ef.ml b/test/test_precedence_ef.ml index efbdb04..a0e1db1 100644 --- a/test/test_precedence_ef.ml +++ b/test/test_precedence_ef.ml @@ -49,45 +49,45 @@ let off n = D.add_days easter n (* (description, date, candidate, expected RG 91 entry). *) let cases = - [ (* Entry 1 -- register line 327: Nativity, Easter Sunday, Pentecost Sunday. *) + [ (* Entry 1 -- RG 91 entry 1 (§4): Nativity, Easter Sunday, Pentecost Sunday. *) ("1 Nativity", mk 2026 12 25, cand "ef-nativity", 1); ("1 Easter Sunday", off 0, cand "ef-easter-sunday", 1); ("1 Pentecost Sunday", off 49, cand "ef-pentecost", 1); - (* Entry 2 -- register line 328: Sacred Triduum. Thu-Sat of Holy Week, + (* Entry 2 -- RG 91 entry 2 (§4): Sacred Triduum. Thu-Sat of Holy Week, NOT entry 7 (which stops at Wednesday -- see entry 7 below). *) ("2 Holy Thursday", off (-3), cand "ef-holy-thursday", 2); ("2 Good Friday", off (-2), cand "ef-good-friday", 2); ("2 Holy Saturday", off (-1), cand "ef-holy-saturday", 2); - (* Entry 3 -- register line 329. *) + (* Entry 3 -- RG 91 entry 3 (§4). *) ("3 Epiphany", mk 2026 1 6, cand "ef-epiphany", 3); ("3 Ascension", off 39, cand "ef-ascension", 3); ("3 Trinity", off 56, cand "ef-trinity", 3); ("3 Corpus Christi", off 60, cand "ef-corpus-christi", 3); ("3 Sacred Heart", off 68, cand "ef-sacred-heart", 3); ("3 Christ the King", T.christ_the_king 2026, cand "ef-christ-the-king", 3); - (* Entry 4 -- register line 330. Sanctoral-origin: neither feast is part + (* Entry 4 -- RG 91 entry 4 (§4). Sanctoral-origin: neither feast is part of temporal_ef's movable cycle. *) ( "4 Immaculate Conception", mk 2026 12 8, cand ~origin:P.Sanctoral ~subject:Sub.Bvm ~layer:PE.universal_layer "ef-immaculate-conception", 4 ); ("4 Assumption", mk 2026 8 15, cand ~origin:P.Sanctoral ~subject:Sub.Bvm ~layer:PE.universal_layer "ef-assumption", 4); - (* Entry 5 -- register line 331. *) + (* Entry 5 -- RG 91 entry 5 (§4). *) ("5 Nativity Vigil", mk 2026 12 24, cand "ef-nativity-vigil", 5); ("5 Octave day (Circumcision)", mk 2026 1 1, cand "ef-circumcision", 5); - (* Entry 6 -- register line 332. *) + (* Entry 6 -- RG 91 entry 6 (§4). *) ("6 Advent Sunday", T.advent_start 2026, cand "ef-advent-sunday-1", 6); ("6 Lent Sunday", off (-42), cand "ef-lent-sunday-1", 6); ("6 Passion Sunday (I Passiontide)", off (-14), cand "ef-passion-sunday", 6); ("6 Palm Sunday (II Passiontide)", off (-7), cand "ef-palm-sunday", 6); ("6 Low Sunday", off 7, cand "ef-low-sunday", 6); - (* Entry 7 -- register line 333: Ash Wednesday and Mon/Tue/Wed of Holy + (* Entry 7 -- RG 91 entry 7 (§4): Ash Wednesday and Mon/Tue/Wed of Holy Week ONLY -- Thu-Sat are entry 2 above, not this entry. *) ("7 Ash Wednesday", off (-46), cand "ef-ash-wednesday", 7); ("7 Monday of Holy Week", off (-6), cand "ef-holy-monday", 7); ("7 Tuesday of Holy Week", off (-5), cand "ef-holy-tuesday", 7); ("7 Wednesday of Holy Week", off (-4), cand "ef-holy-wednesday", 7); - (* Entry 8 -- register line 334. 2 Nov 2026 is a Monday (verified + (* Entry 8 -- RG 91 entry 8 (§4). 2 Nov 2026 is a Monday (verified independently below the table), so this row is the plain case. The register's own qualifying case -- "yields to an occurring Sunday" -- gets its own row and its own end-to-end test after this table (2 Nov @@ -101,31 +101,31 @@ let cases = [test_all_souls_yields_to_sunday] below; this row pins the specific integer [band] returns. *) ("8 All Souls (yields to a Sunday, 2 Nov 2025)", mk 2025 11 2, cand ~origin:P.Sanctoral ~layer:PE.universal_layer "ef-all-souls", 16); - (* Entry 9 -- register line 335. *) + (* Entry 9 -- RG 91 entry 9 (§4). *) ("9 Pentecost Vigil", off 48, cand "ef-pentecost-vigil", 9); - (* Entry 10 -- register line 336: both range boundaries, to guard the + (* Entry 10 -- RG 91 entry 10 (§4): both range boundaries, to guard the off-by-one an inclusive Easter-offset window invites. *) ("10 Easter octave, day+1", off 1, cand "ef-easter-1-mon", 10); ("10 Easter octave, day+6", off 6, cand "ef-easter-1-sat", 10); ("10 Pentecost octave, day+50", off 50, cand "ef-pentecost-1-mon", 10); ("10 Pentecost octave, day+55", off 55, cand "ef-pentecost-1-sat", 10); - (* Entry 11 -- register line 337. *) + (* Entry 11 -- RG 91 entry 11 (§4). *) ( "11 Universal I-class feast", mk 2026 6 29, cand ~origin:P.Sanctoral ~subject:Sub.Saint ~layer:PE.universal_layer "ef-ss-peter-paul", 11 ); - (* Entry 12 -- register line 338. The one non-base-layer case the brief + (* Entry 12 -- RG 91 entry 12 (§4). The one non-base-layer case the brief asks for explicitly: same date/rank/subject as 11, only the layer differs, so this row isolates the layer test as the deciding factor. *) ( "12 Proper I-class feast (non-base layer)", mk 2026 6 29, cand ~origin:P.Sanctoral ~subject:Sub.Saint ~layer:"diocese-warsaw" "ef-local-patron", 12 ); - (* Entry 13 -- register line 339. *) + (* Entry 13 -- RG 91 entry 13 (§4). *) ( "13 Indult I-class feast", mk 2026 6 29, cand ~origin:P.Sanctoral ~subject:Sub.Saint ~layer:(PE.indult_prefix ^ "local-grant") "ef-indult-feast-1", 13 ); - (* Entry 14 -- register line 341, deliberately UNQUALIFIED (contrast - entry 16, line 342, which explicitly says "not of the Lord"). *) + (* Entry 14 -- RG 91 entry 14 (§4), deliberately UNQUALIFIED (contrast + entry 16, which explicitly says "not of the Lord"). *) ( "14 Feast of the Lord, II class", mk 2026 7 1, cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer "ef-precious-blood", @@ -138,21 +138,21 @@ let cases = cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:"diocese-warsaw" "ef-local-feast-of-the-lord", 14 ); - (* Entry 15 -- register line 342: an ordinary Sunday not named at entry 6 + (* Entry 15 -- RG 91 entry 15 (§4): an ordinary Sunday not named at entry 6 -- Septuagesima is II class (RG 11-12 names only Advent/Lent/ Passiontide/Easter/Low/Pentecost as I class). *) ("15 II-class Sunday (Septuagesima)", off (-63), cand ~rank:V.Class2 "ef-septuagesima-sunday", 15); - (* Entry 16 -- register line 342. *) + (* Entry 16 -- RG 91 entry 16 (§4). *) ( "16 Universal II-class feast, not of the Lord", mk 2026 1 20, cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Saint ~layer:PE.universal_layer "ef-some-saint", 16 ); - (* Entry 17 -- register line 343: days WITHIN the Nativity octave (26-28 + (* Entry 17 -- RG 91 entry 17 (§4): days WITHIN the Nativity octave (26-28 Dec are Stephen/John/Innocents -- sanctoral, not this entry; 1 Jan is entry 5's Octave DAY, not this entry either). *) ("17 Nativity octave, 29 Dec", mk 2026 12 29, cand ~rank:V.Class2 "ef-nativity-octave-day-5", 17); ("17 Nativity octave, 31 Dec", mk 2026 12 31, cand ~rank:V.Class2 "ef-nativity-octave-day-7", 17); - (* Entry 18 -- register line 343-344: Advent 17-23 Dec ferias AND the + (* Entry 18 -- RG 91 entry 18 (§4): Advent 17-23 Dec ferias AND the Ember days of Advent/Lent/September share this one entry. The second row is deliberately a Lent date (season Lent, NOT Advent) to prove the Ember-slug path fires on its own, not merely because it also happens @@ -164,17 +164,17 @@ let cases = rather than a hand-typed "ef-lent-ember-wed" -- closes review finding 3's coupling concern for the Ember prefixes specifically. *) ("18 Lent Ember Wednesday (from Temporal_ef.temporal)", off (-39), of_temporal (off (-39)), 18); - (* Entry 19 -- register line 344. *) + (* Entry 19 -- RG 91 entry 19 (§4). *) ( "19 Proper II-class feast", mk 2026 1 20, cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Saint ~layer:"diocese-warsaw" "ef-local-saint-2", 19 ); - (* Entry 20 -- register line 345. *) + (* Entry 20 -- RG 91 entry 20 (§4). *) ( "20 Indult II-class feast", mk 2026 1 20, cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Saint ~layer:(PE.indult_prefix ^ "local-grant-2") "ef-indult-feast-2", 20 ); - (* Entry 21 -- register line 345 (RG 28-34). Two rows: the Ascension + (* Entry 21 -- RG 91 entry 21 (§4, RG 28-34). Two rows: the Ascension Vigil is the one II-class vigil temporal_ef already produces today (temporal-origin); the Assumption Vigil stands in for the sanctoral-origin case no task has loaded data for yet -- proving @@ -194,12 +194,12 @@ let cases = cand ~origin:P.Sanctoral ~rank:V.Class2 ~subject:Sub.Lord ~layer:PE.universal_layer "ef-precious-blood-vigil", 21 ); - (* Entry 22 -- register line 347-348 (corrected: ends at Palm Sunday, not + (* Entry 22 -- RG 91 entry 22 (§4) (corrected: ends at Palm Sunday, not Passion Sunday). Both a Lent and a Passiontide feria, clear of Ash Wednesday, Holy Week and the Ember days. *) ("22 Lent feria", off (-41), cand ~rank:V.Class3 "ef-lent-1-mon", 22); ("22 Passiontide feria", off (-12), cand ~rank:V.Class3 "ef-passiontide-1-tue", 22); - (* Entry 23 -- register line 349. NOTE the table's own order here is the + (* Entry 23 -- RG 91 entry 23 (§4). NOTE the table's own order here is the REVERSE of 11/12 and 14/16/19/20 above: entry 23 (particular calendars) is numbered BELOW entry 24 (universal), so a proper III-class feast outranks a universal one -- transcribed as the @@ -207,13 +207,13 @@ let cases = ( "23 Proper III-class feast (non-base layer)", mk 2026 6 30, cand ~origin:P.Sanctoral ~rank:V.Class3 ~layer:"diocese-warsaw" "ef-local-saint-3", 23 ); - (* Entry 24 -- register line 349. *) + (* Entry 24 -- RG 91 entry 24 (§4). *) ( "24 Universal III-class feast", mk 2026 6 30, cand ~origin:P.Sanctoral ~rank:V.Class3 ~layer:PE.universal_layer "ef-some-saint-3", 24 ); - (* Entry 25 -- register line 350. *) + (* Entry 25 -- RG 91 entry 25 (§4). *) ("25 Advent feria to 16 Dec", mk 2026 12 1, cand ~rank:V.Class3 "ef-advent-1-tue", 25); - (* Entry 26 -- register line 350. *) + (* Entry 26 -- RG 91 entry 26 (§4). *) ( "26 III-class vigil", mk 2026 8 9, cand ~origin:P.Sanctoral ~rank:V.Class3 ~layer:PE.universal_layer "ef-lawrence-vigil", 26 ); @@ -238,12 +238,12 @@ let cases = mk 2026 8 9, cand ~origin:P.Sanctoral ~rank:V.Class3 ~layer:PE.universal_layer "vigil-of-st-lawrence", 26 ); - (* Entry 27 -- register line 352: an otherwise-unoccupied IV-class + (* Entry 27 -- RG 91 entry 27 (§4): an otherwise-unoccupied IV-class Saturday. *) ( "27 Office of the BVM on Saturday", off 62, cand ~rank:V.Class4 "ef-time-after-pentecost-1-sat", 27 ); - (* Entry 28 -- register line 352: the unqualified IV-class catch-all. *) + (* Entry 28 -- RG 91 entry 28 (§4): the unqualified IV-class catch-all. *) ("28 IV-class feria", off 65, cand ~rank:V.Class4 "ef-time-after-pentecost-1-tue", 28); (* Not an RG 91 row at all: a I-class candidate marked as a vigil, which is not the Nativity or Pentecost (entries 5/9, the only I-class @@ -264,7 +264,7 @@ let cases = [not is_temporal] guard's role in the entry-25 mutation test recorded in the task report). *) ("unclassified: I-class temporal candidate on an unnamed date", mk 2026 7 15, cand "ef-unnamed-day", PE.unclassified); - (* RG 91's own vigil list (register lines 381-384) stops at III class -- + (* RG 91's own vigil list (§4, "Vigils / octaves / Rogations / Sunday classes") stops at III class -- there is no IV-class vigil for entry 28's ferial catch-all to absorb. *) ( "unclassified: IV-class candidate marked as a vigil", mk 2026 6 20, cand ~rank:V.Class4 "ef-second-mystery-vigil", PE.unclassified ) @@ -298,7 +298,7 @@ let test_all_souls_yields_to_sunday () = (S.to_string resolution.P.observed.P.cel.Cel.slug) (* Task 8: [disposition] -- what happens to the day's LOSING candidate (RG - 92-95, 33, 94; register lines 316-325, 381-384). Table-driven like [band]'s + 92-95, 33, 94; §4). Table-driven like [band]'s own [cases] above, one row per rule, each checked against a description of which register clause it pins. [disposition] takes no context (see precedence.mli's [rules.disposition]), so "is the winner a Sunday" is read @@ -320,7 +320,7 @@ let an_ordinary_sunday = cand ~rank:V.Class2 "ef-time-after-pentecost-sunday-11" let disposition_cases = - [ (* RG 95 -- register line 323-325: only I-class feasts transfer; a + [ (* RG 95 -- §4, "Occurrence": only I-class feasts transfer; a II-class feast loses to a I-class day and is COMMEMORATED, not transferred. Paired with the next row (a I-class loser, same shape of winner) so the discriminating factor is provably the LOSER's own @@ -334,14 +334,14 @@ let disposition_cases = cand "ef-nativity", cand ~origin:P.Sanctoral ~layer:PE.universal_layer "ef-local-i-class-feast", "Transfer" ); - (* Fix round 1 (post-Task-9 review): RG 95 (register lines 323, 363) + (* Fix round 1 (post-Task-9 review): RG 95 (§4, "Occurrence" and "Transfer/translation") restricts the right of translation to I-class FEASTS -- RG 91's own - table lists Sundays as a separate row (entry 6, register line 332) - from feasts (entries 11-13, lines 337-339) -- so an impeded I-class + table lists Sundays as a separate row (entry 6) + from feasts (entries 11-13) -- so an impeded I-class Sunday must NOT transfer, unlike the plain I-class feast row above: same [Class1] rank, same kind of winner, the ONLY difference is that - this loser's slug carries [PE.sunday_marker]. RG 109(a) (register - line 374) confirms this from the other direction: "of a Sunday" is a + this loser's slug carries [PE.sunday_marker]. RG 109(a) (§4) + confirms this from the other direction: "of a Sunday" is a privileged commemoration category, which presupposes an impeded Sunday stays put rather than moving to another day the way a feast does. Sourced from [Temporal_ef.temporal]'s own real output (Advent I @@ -356,8 +356,9 @@ let disposition_cases = cand ~origin:P.Sanctoral ~layer:PE.universal_layer "ef-immaculate-conception", of_temporal (T.advent_start 2026), "Commemorate(Privileged)" ); - (* RG 33 -- register line 383-384: a I/II-class vigil impeded by any - Sunday or a I-class feast is entirely OMITTED, not commemorated. The + (* RG 33 -- §4, "Vigils / octaves / Rogations / Sunday classes": a II- or + III-class vigil impeded by any Sunday or a I-class feast is entirely + OMITTED, not commemorated. The vigil is sourced from [Temporal_ef.temporal]'s own real output (as [of_temporal]'s existing callers above do), not a hand-typed "ef-ascension-vigil", so a drift in temporal_ef's vigil-slug @@ -456,7 +457,7 @@ let disposition_cases = RG 95's transfer, not after. Its expected privilege is [Privileged], not [Ordinary]: this loser's [rank] is [Class1] (the default [cand] leaves unless overridden, deliberately kept here for the - branch-order proof above), and RG 109(b) (register line 374-375, "of + branch-order proof above), and RG 109(b) (§4, "of a I-class day") makes any [Class1] commemoration privileged regardless of how it reached [Commemorate] -- Task 8's placeholder [interim_privilege] used to hide this (always [Ordinary]); Task 9's @@ -542,7 +543,7 @@ let disposition_cases = "Commemorate(Ordinary)" ) ] -(* Task 9: [privilege_of]'s RG 109 categories (register lines 374-377), +(* Task 9: [privilege_of]'s RG 109 categories (§4, "Commemorations"), exercised through [PE.disposition]'s [Commemorate] payload -- [privilege_of] itself is private, so this is the only vantage point a test outside precedence_ef.ml has on it. Each row below is built to match ONLY the one @@ -560,14 +561,14 @@ let disposition_cases = correctly NOT conflated with it, which is the strongest claim available without inventing an unfounded slug convention. *) let privilege_cases = - [ (* (a) register line 374: "of a Sunday". [an_ordinary_sunday] is Class2, + [ (* (a) RG 109(a) (§4): "of a Sunday". [an_ordinary_sunday] is Class2, not Class1, not within the Nativity octave, not an Ember day, not a feria of Advent/Lent/Passiontide -- matches (a) alone. *) ( "(a) an ordinary Sunday commemoration is privileged", cand "ef-nativity", an_ordinary_sunday, "Commemorate(Privileged)" ); - (* (c) register line 375: "of days within the Octave of the Nativity" -- + (* (c) RG 109(c) (§4): "of days within the Octave of the Nativity" -- sourced from [Temporal_ef.temporal]'s own output (29 Dec 2026, Class2, "ef-nativity-octave-day-5"), not a hand-typed slug, for the same coupling-safety reason the file's own [of_temporal] rows use it @@ -577,7 +578,7 @@ let privilege_cases = cand "ef-nativity", of_temporal (mk 2026 12 29), "Commemorate(Privileged)" ); - (* (d) register line 375-376: "of September Ember days" -- 23 Sep 2026 is + (* (d) RG 109(d) (§4): "of September Ember days" -- 23 Sep 2026 is the September Ember Wednesday (independently derived from [Temporal_ef]'s own third-Sunday-of-September rule: first Sunday of September 2026 is the 6th, +14 days = 20th, +3 = 23rd), sourced from @@ -593,7 +594,7 @@ let privilege_cases = cand "ef-nativity", of_temporal (mk 2026 9 23), "Commemorate(Privileged)" ); - (* (e) register line 376: "of ferias of Advent, Lent and Passiontide" -- + (* (e) RG 109(e) (§4): "of ferias of Advent, Lent and Passiontide" -- two rows, one per season named, both from [Temporal_ef.temporal]'s own generic ferial fallback, neither a Sunday, Ember day, or within the Nativity octave. *) @@ -666,7 +667,7 @@ let privilege_cases = "Omit" ) ] -(* Task 9: [PE.admit] -- RG 111's admission counts (register line 378), +(* Task 9: [PE.admit] -- RG 111's admission counts (§4, "Commemorations"), given commemorations ALREADY tagged with their real privilege (as [PE.disposition] now tags them -- see [privilege_cases] above). Every candidate/privilege pair here is built directly, not routed through @@ -719,7 +720,7 @@ let slugs_of admitted = List.map (fun (c, _) -> S.to_string c.P.cel.Cel.slug) admitted let admit_cases = - [ (* RG 111 (register line 378): "I class: none save one privileged." *) + [ (* RG 111 (§4): "I class: none save one privileged." *) ( "I-class day, only an ordinary commemoration due -> none admitted", observed_class1, [ (ordinary_hi, P.Ordinary) ], @@ -928,7 +929,7 @@ let test_ii_class_sunday_privileged_witness_admitted_end_to_end () = [ ("ef-some-saint", "omitted: admission limit reached") ] (List.map (fun (c, reason) -> (S.to_string c.P.cel.Cel.slug, reason)) resolution.P.omitted) -(* Completes Task 7's carried fix (register line 334): on a real Sunday +(* Completes Task 7's carried fix (RG 91 entry 8, §4): on a real Sunday landing on 2 November, All Souls does not merely lose (that was Task 7's [band] fix, proved by [test_all_souls_yields_to_sunday] above) -- it must be TRANSFERRED, not commemorated and not omitted. All Souls is I class |
