diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-12 17:13:06 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-08-12 17:13:06 +0200 |
| commit | a2654a1e4d8987a251bcefbad2b0f0b867a6c6e6 (patch) | |
| tree | 39360eccd3fa8ee5379fc46276d1e0ef0e6ff2b5 /lib/rites/rite_ef/precedence_ef.ml | |
| parent | e19adb9c7ea369cafe76e7eff50e9248a4a954d0 (diff) | |
| parent | e5b368dec8fdc9ab983ee0f1dee69c37883cbe12 (diff) | |
| download | colitur-a2654a1e4d8987a251bcefbad2b0f0b867a6c6e6.tar.gz colitur-a2654a1e4d8987a251bcefbad2b0f0b867a6c6e6.zip | |
Merge branch 'ef-rg16a': RG 16(a), RG 111(b), RG 113, and commemoration identity
Closes the largest known-wrong-output item on record (RG 16(a): a Feast
of the Lord occurring on a II-class Sunday leaves the Sunday
uncommemorated -- 5996 wrong days over 1583-9999) together with RG
111(b)'s rank floor on the day it holds, and gives the oracle layer the
ability to compare commemoration identity rather than only presence and
count.
Also corrects a methodological defect that had produced wrong rulings in
both this project and its sibling: docs/research/ holds an electronic
transcription alongside two photographic scans, and the transcription
silently drops commemoration lines -- seven across the year. Reasoning
from its silence had convicted the oracle wrongly on 14 August and
ruled a genuine 9 August commemoration spurious. The scans are the
primary source; the rule is now recorded at the top of the register.
RG 113 replaces an alphabetical same-rank tie-break that had no
rubrical warrant. A bare Commemoratio has no row in RG 91's table at
all, so band no longer hands one the entry of a III-class universal
feast: 4451 days, all four reordered pairs verified against a
photographic scan, zero observed-day changes.
Diffstat (limited to 'lib/rites/rite_ef/precedence_ef.ml')
| -rw-r--r-- | lib/rites/rite_ef/precedence_ef.ml | 333 |
1 files changed, 267 insertions, 66 deletions
diff --git a/lib/rites/rite_ef/precedence_ef.ml b/lib/rites/rite_ef/precedence_ef.ml index db7e708..750da8b 100644 --- a/lib/rites/rite_ef/precedence_ef.ml +++ b/lib/rites/rite_ef/precedence_ef.ml @@ -110,6 +110,7 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc int = let cel = c.Precedence.cel in let rank = cel.Celebration.rank in + let status = cel.Celebration.status in let subject = cel.Celebration.subject in let layer = cel.Celebration.layer in let slug = Slug.to_string cel.Celebration.slug in @@ -129,8 +130,48 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc binding, not a second literal, so the two can never drift apart. *) let entry_15_band = 15 in let open Vocab_ef in - (* 1: Nativity, Easter Sunday, Pentecost Sunday (I class w/ octave). *) - if is_temporal && rank = Class1 && ((m = 12 && d = 25) || off = 0 || off = 49) then 1 + (* CORRECTED (Task B fix round 1, ef-rg16a): a [Commemoration_only] + celebration has NO row in RG 91's table at all, checked FIRST, ahead of + every rank-keyed branch below -- RG 91's own text enumerates only "dies + liturgici" (entry 24's own wording, e.g., "Festa III classis, in + calendario Ecclesiae universae inscripta" -- FEASTS, inscribed in the + calendar), and the calendarium itself marks the difference in its own + notation: 22 September's row reads "S. Thomae de Villanova Ep. et + Conf., III classis. / Commemoratio Ss. Mauritii et Soc. Mm." -- Thomas + gets a class number (a "festum"); Maurice gets "Commemoratio" and NO + class number at all, because he never had a row in the table for that + occasion to begin with. Before this fix, [band] read [rank] alone, so + a [Commemoration_only] entry silently borrowed the SAME entry number + as a genuine [Feast] of its own rank (a Class3 Commemoration_only + entry banded to 24, indistinguishable from a real Class3 universal + feast) -- manufacturing a "tie" at {!compare_precedence}/RG 113's own + admission ordering that the primary text never creates: RG 113 does + not run out of instruction between two same-rank commemorations; + [band] ran out of fidelity, handing out a table row that does not + exist for one of them. [unclassified] (worse than every real entry) is + the same value already used for a candidate this table's 28 branches + otherwise fail to describe, which is exactly the right answer here + too: "not in this table" for a different reason, same table-position + consequence. Confirmed by the oracle: missalemeum's own commemoration + id embeds a rank that AGREES with the demoted status this represents + (e.g. sancti:09-22o:4:r for Maurice, rank 4, against Thomas's own + sancti:09-22:3:w, rank 3, on the day Thomas is observed -- test_oracle + .ml's own [test_identity_rank_corroboration]). Restricted to [status]; + [rank] itself is untouched, and stays load-bearing for a demoted feast: + RG 111(b)'s "scilicet de festo II classis" floor ({!admit} below) reads + [rank] directly, and it is exactly that floor which excludes these + Class3 entries from a II-class Sunday's single slot. Only ORDERING among + candidates already offered to {!admit} changes here. + NOTE, corrected: this comment previously cited {!Celebration.status}'s + own doc comment as saying a demoted feast retains its rank for RG 111's + admission-COUNT purposes. That misquotes it -- celebration.mli says RG + 111 "orders admitted commemorations by dignity", i.e. it names the + ORDERING use this guard removes, not a counting one. celebration.mli's + line is itself now stale: ordering moved from dignity to [band] in + ea22ad2. The guard is right; its former justification was not. *) + if status = Celebration.Commemoration_only then unclassified + (* 1: Nativity, Easter Sunday, Pentecost Sunday (I class w/ octave). *) + else if is_temporal && rank = Class1 && ((m = 12 && d = 25) || off = 0 || off = 49) then 1 (* 2: Sacred Triduum (Thu-Sat of Holy Week). *) else if is_temporal && rank = Class1 && off >= -3 && off <= -1 then 2 (* 3: Epiphany, Ascension, Holy Trinity, Corpus Christi, Sacred Heart, @@ -244,13 +285,14 @@ let band (ctx : Vocab_ef.season Precedence.context) (c : Vocab_ef.rank Precedenc (* Task 8: what happens to the day's LOSING candidate (docs/research/ rules-register.md §4, "Occurrence" RG 92-95 and "Vigils" RG 33, plus RG - 94). [band] above decides who wins; this decides the loser's fate, which - turns on the LOSER's own rank and status (RG 95), except RG 33's vigil - omission, which also has to read the winner. Nothing here ever returns - [Precedence.Repose]: that disposition denotes RG 100-102's *repositio* - (perpetual impediment from a proper/diocesan calendar), out of this - plan's scope -- see calendar.mli's own note that nothing in the EF - ruleset currently emits it. *) + 94; also §6.0/Caput III "De Dominicis" RG 16(a), below). [band] above + decides who wins; this decides the loser's fate, which turns on the + LOSER's own rank and status (RG 95), except RG 33's vigil omission and RG + 16(a)'s Sunday-suppression, which also have to read the winner. Nothing + here ever returns [Precedence.Repose]: that disposition denotes RG + 100-102's *repositio* (perpetual impediment from a proper/diocesan + calendar), out of this plan's scope -- see calendar.mli's own note that + nothing in the EF ruleset currently emits it. *) (* RG 33 -- CORRECTED 2026-08-12 (Task 16, primary-source-verified against docs/research/1962-06-23,_SS_Ioannes_XXIII,_Missale_Romanum,_LT.pdf, the @@ -605,6 +647,91 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate) register's own §4 "Vigils" entry states RG 32 only as "same pattern [as RG 31]", not verbatim -- now closed here). *) Precedence.Omit + else if + is_temporal + && cel.Celebration.rank = Class2 + && is_sunday_slug (Slug.to_string cel.Celebration.slug) + && (let wcel = winner.Precedence.cel in + (wcel.Celebration.rank = Class1 || wcel.Celebration.rank = Class2) + && wcel.Celebration.subject = Subject.Lord) + then + (* RG 16(a) (docs/research/rules-register.md §6.0, Caput III "De + Dominicis", primary text): "Dominica II classis, in occurrentia, + festis II classis praefertur. Attamen: a) festum Domini I aut II + classis, in dominica II classis occurrens, locum tenet ipsius + dominicae cum omnibus iuribus et privilegiis: de dominica, proinde, + NULLA FIT COMMEMORATIO" -- a Feast of the Lord, I or II class, + occurring on a II-class Sunday, takes the Sunday's own place with all + its rights and privileges: OF THE SUNDAY, THEREFORE, NO + COMMEMORATION IS MADE. {!band} entry 14 already ranks such a feast + above the Sunday (RG 91 entry 14 < entry 15), so the feast is + correctly [observed]; this is [disposition]'s own answer for what + becomes of the SUNDAY once it has lost -- [Omit], not the [Commemorate] + every other impeded II-class Sunday gets via RG 109(a)/RG 111(b) + below. This is the ONE place in this function that needs the WINNER's + [subject], not only the loser's own fields -- like RG 33's vigil + omission above, not a new kind of signature: [Precedence.rules.disposition] + already takes [~winner], this is simply its first other reader. + + Both winner-side conjuncts are load-bearing, proved by + [test_precedence_ef.ml]'s own paired rows (the brief's "one without + the other proves nothing"): + - [rank = Class1 || rank = Class2]: {!band} entries 11-13 admit ANY + I-class feast -- Lord or Saint alike, no subject test at all (entry + 14's own comment: unlike entry 16, entries 11-13 draw no such + line) -- ahead of a II-class Sunday. REACHABLE at Class1 on real + data: e.g. the Nativity of St John the Baptist (24 June, I class, + Saint) landing on a Time-after-Pentecost Sunday already wins the + day under {!band} alone; without this conjunct RG 16(a) would + wrongly fire for it too. (At Class2 this conjunct adds no further + cases beyond what the [subject = Lord] conjunct below already + requires -- entry 16's ordinary II-class feasts never outrank a + Sunday in {!band} in the first place, 16 > 15 -- so it is only + independently reachable at Class1.) + - [subject = Lord]: at Class2 this is what {!band} entry 14 already + requires of its own winners, so it adds no further restriction + there; at Class1 it is independently reachable and necessary, per + the St John Baptist example above -- dropping it would fire RG + 16(a) for any winning I-class feast at all, exactly the + over-wide branch the task brief warns against. + + The SUNDAY-side conjuncts: [rank = Class2] excludes a I-class Sunday + (Advent/Lent/Passiontide, Low Sunday, {!band} entry 6) -- RG 16(a)'s + own text says "Dominica II classis", not "any Sunday", and a I-class + Sunday can never actually reach here as a [loser] against a + Class1-or-2 Lord winner in the first place, for TWO DIFFERENT reasons + depending on the winner's shape (CORRECTED, fix round 1: the previous + version of this comment claimed "entry 6's own band value (6) is + lower than every entry [3, 11-14]" as a single numeric argument -- + WRONG on its face, 6 is not lower than 3, and the claim would in any + case prove the opposite of what it was cited for: if a band-3 + candidate really did contest a Class1 Sunday, the LOWER number (3) + would win, i.e. the Sunday would LOSE, not "always win outright" as + claimed): + - Against entries 11-14 (SANCTORAL-origin Lord feasts, e.g. the + Transfiguration): the numeric argument genuinely holds here -- + entry 6 (6) IS lower than 11-14, so a I-class Sunday always wins + outright against these. + - Against entry 3 (TEMPORAL-origin Lord feasts -- Epiphany, + Ascension, Trinity, Corpus Christi, Sacred Heart, Christ the King): + not a numeric argument at all, but a STRUCTURAL one -- every + band-3 celebration is [is_temporal], and {!Precedence.resolve} + takes exactly ONE temporal candidate per day ([~temporal], not a + list), so a band-3 Lord feast IS that date's own single temporal + candidate, never a SEPARATE candidate contesting an + independently-produced Sunday on the same date. There is no + collision to resolve by band comparison in the first place. + Either way, no I-class Sunday can reach here as a loser against a + Class1-or-2 Lord winner -- this is exactly why the rubric restricts + itself to II class. [is_sunday_slug] + (the same marker RG 33's [impedes_vigil] and RG 109(a)'s + [privilege_of] already use, with no [is_temporal] guard there either + -- no sanctoral slug this codebase's data produces contains + {!sunday_marker}) is the "Dominica" half; [is_temporal] is kept + alongside it anyway, the same explicit-but-not-load-bearing defence + the RG26 branch above gives its own [not is_vigil] guard, rather than + relying on that absence silently. *) + Precedence.Omit else (* RG 95's other branch: "aut commemorantur aut penitus omittuntur" -- commemorated or wholly omitted. Reached by every SANCTORAL loser @@ -642,42 +769,105 @@ let disposition ~(winner : Vocab_ef.rank Precedence.candidate) classis", "dominicis II classis", "aliis diebus II classis", "diebus III et IV classis") -- read here off [observed]'s own [rank] and, for the Sunday/non-Sunday II-class split, the same slug marker [privilege_of] and - RG 33's [impedes_vigil] already use ([is_sunday_slug]). No [context] - (date/season/weekday) is available to [admit] (see precedence.mli's - [rules.admit]) or needed: [observed] IS the day's own celebration, so its - rank and slug already carry everything RG 111's own four categories test. *) + RG 33's [impedes_vigil] already use ([is_sunday_slug]). + + CORRECTED (fix round 1, RG16(a) task): the previous version of this + comment claimed "[observed] IS the day's own celebration, so its rank and + slug already carry everything RG 111's own four categories test" -- + WRONG once RG 16(a) exists. RG 16(a)'s own text says the winning Feast of + the Lord holds the Sunday's place "cum omnibus iuribus et privilegiis" + (with ALL its rights and privileges) -- the day remains a "dominica II + classis" for RG 111(b)'s own purposes even though [observed] is now the + FEAST, not the Sunday, so [observed]'s own slug is no longer a reliable + signal of "is this a Sunday" once something can legitimately observe in + the Sunday's place. Confirmed wrong for real data by the oracle: 6 August + falling on a Sunday shows the Transfiguration observed and NO + commemoration (missalemeum: `commemorations: []`, Pope Sixtus II et al. + `displaced`); the pre-fix code, reading Sunday-ness off [observed]'s own + slug ("transfiguration-of-our-lord", no Sunday marker), wrongly took the + [Class2, false] "other II class: one" branch below and admitted Sixtus + (Class3) regardless of RG 111(b)'s own "de festo II classis" rank floor. + Control, also oracle-confirmed: 6 August on an ordinary WEEKDAY (no + Sunday collision) correctly admits Sixtus -- being a Sunday is exactly + what excludes him, and [observed]'s own identity cannot tell the two + cases apart on its own. + + Fixed by reading Sunday-ness off [temporal] instead -- {!Precedence.rules.admit}'s + own [~temporal] parameter, {!Precedence.resolve}'s [~temporal] argument + passed straight through, unaffected by whether it won the day. [context] + (date/season/weekday) is still not needed: [temporal]'s own slug already + carries everything this split needs, the same way [observed]'s used to + before a competing office could occupy the Sunday's place. *) -(* RG 8's four-class dignity order, Class1 highest. Deliberately NOT [band] - (RG 91's much finer 28-entry table): [band] needs a [context] [admit] - does not have (see above), and Celebration.mli's own comment on [status] - -- "RG 111 orders admitted commemorations by dignity" -- names [rank] - itself as that dignity, not the finer occurrence-table entry. *) -let dignity = function - | Vocab_ef.Class1 -> 1 - | Vocab_ef.Class2 -> 2 - | Vocab_ef.Class3 -> 3 - | Vocab_ef.Class4 -> 4 +(* RG 113 -- CORRECTED, Task B (branch ef-rg16a): docs/research/rules- + register.md §4's RG 113 entry previously quoted only its FIRST sentence + ("commemoratio de Tempore fit primo loco"); its SECOND, load-bearing + sentence, primary-source-verified against two independent scans, is the + real rule for this function: *"In admittendis et ordinandis aliis + commemorationibus, servetur ordo tabellae praecedentiae"* -- in ADMITTING + and ORDERING the other commemorations, the order of the table of + precedence (RG 91, {!band}'s own 28-entry table) is to be kept. -(* Deterministic selection order for RG 111: dignity first, then slug -- - the same tie-break {!Precedence.compare_by} uses for [band] itself (the - brief: "break ties on slug"), so which candidate wins a shared rank never - depends on the order [comms] arrives in. *) -let compare_dignity (a, _) (b, _) = - let da = dignity a.Precedence.cel.Celebration.rank - and db = dignity b.Precedence.cel.Celebration.rank in - if da <> db then Int.compare da db + This REPLACES a previous [compare_dignity], which sorted by RG 8's coarse + four-class [rank] ("dignity") and broke same-rank ties alphabetically by + slug -- an engineering convention with no rubrical warrant. Measured, + fix round 1 (2005-2050, a temporary pre-fix [git worktree]): a + same-[rank] tie existed on 599 days, most never reaching a real + decision; reversing the slug tie-break alone changed the ADMITTED SET on + 65 of them and the printed ORDER of an already-admitted pair on a + further 149 (docs/research/rules-register.md §6.1's full account, + correcting this comment's own earlier, unreproduced "66 days" claim). + + CORRECTED, fix round 1 (coordinator finding 1): checking every one of + those 65+149 real decisions against data/ef/sanctoral.sexp found the + SAME underlying shape in all of them, no exceptions -- one candidate is + always [Cel.Commemoration_only] (e.g. "maurice-and-companions-martyrs", + 22 September) and the other always a genuine [Cel.Feast] or a temporal + office of the SAME [rank] (e.g. "thomas-of-villanova", same day; or a + Lent feria, {!band} entry 22, against "paul", 22 February). That is + {!band}'s OWN fidelity bug, fixed separately at its source (see [band]'s + own top-of-branch guard, RG 91's table has no row for a bare + commemoration at all) -- NOT a case RG 113's table-order alone resolves, + since a [Commemoration_only] candidate never had a real table entry to + compare in the first place. With that fixed, none of these 599 days' + real decisions any longer depend on THIS function's own slug fallback: + {!band} alone (a real entry vs {!unclassified}) already decides every + one. What remains genuinely open -- two DIFFERENT candidates landing on + the IDENTICAL real table entry, e.g. two different Class3 universal + feasts both at entry 24 -- was checked and found EMPTY across + 2005-2050 (register §6.1): RG 113's own table-order, once {!band} is + accurate, already decides every real case this codebase's current data + produces; the slug fallback below is exercised only between two + [Commemoration_only] candidates tied at {!unclassified} (138 of the 599, + all order/count-invisible -- RG 91 has no table position for either of + them to compare, so there is nothing more specific RG 113 could supply + here either). {!band} needs a [context] this function itself does not + have (date/season/weekday) -- unlike [dignity], which read [rank] alone + -- so {!Precedence.resolve} now computes each candidate's own [band] + value once, generically, and hands it to [admit] as the trailing [int] + on each input triple (see {!Precedence.rules.admit}'s own doc). [comms] + below is [(candidate * privilege * int) list], not the pair it used to + be. *) +let compare_precedence (a, _, ba) (b, _, bb) = + if ba <> bb then Int.compare (ba : int) bb else Slug.compare a.Precedence.cel.Celebration.slug b.Precedence.cel.Celebration.slug let rec take n = function | [] -> [] | x :: xs -> if n <= 0 then [] else x :: take (n - 1) xs +(* [comms]'s own candidate/privilege pair, its [band] value dropped once a + selection has been made -- {!Precedence.rules.admit}'s return type is + still the pair, not the triple; only the INPUT carries [band]. *) +let drop_band (c, p, (_ : int)) = (c, p) + let admit ~(observed : Vocab_ef.rank Precedence.candidate) - (comms : (Vocab_ef.rank Precedence.candidate * Precedence.privilege) list) : + ~(temporal : Vocab_ef.rank Precedence.candidate) + (comms : (Vocab_ef.rank Precedence.candidate * Precedence.privilege * int) list) : (Vocab_ef.rank Precedence.candidate * Precedence.privilege) list = - (* Sorted once, by dignity then slug (see [compare_dignity]); every branch - below either takes a prefix of this list or filters it, so the RESULT - is always a sub-list of [comms] with its elements untouched -- never + (* Sorted once, by {!band} then slug (see [compare_precedence]); every + branch below either takes a prefix of this list or filters it, so the + RESULT is always built from [comms]'s own elements, untouched -- never rebuilt -- which matters beyond determinism: {!Precedence.resolve}'s own [dropped] computation tells an admitted candidate from a dropped one by physical equality (==) on the candidate value (Task 2's own @@ -689,21 +879,29 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate) 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 + crash to announce it, which is exactly why this comment exists. + [drop_band] only unwraps the pair back out of the triple -- it does not + rebuild [c] or [p] themselves, so this obligation still holds. *) + let sorted = List.stable_sort compare_precedence comms in + let is_privileged (_, p, _) = p = Precedence.Privileged in let observed_rank = observed.Precedence.cel.Celebration.rank in - let observed_is_sunday = - is_sunday_slug (Slug.to_string observed.Precedence.cel.Celebration.slug) + (* CORRECTED (fix round 1, RG16(a) task): read off [temporal], not + [observed] -- see this function's own doc comment above for the full + argument and the oracle evidence. [temporal] is the day's own + temporal-cycle candidate regardless of who is [observed]; RG 16(a) + makes that distinction live for the first time (a Feast of the Lord + can now be [observed] on a day whose [temporal] candidate is a Sunday). *) + let day_is_sunday = + is_sunday_slug (Slug.to_string temporal.Precedence.cel.Celebration.slug) in let open Vocab_ef in - match (observed_rank, observed_is_sunday) with + match (observed_rank, day_is_sunday) with | Class1, _ -> (* RG 111: "I class: none save one privileged." Ordinary commemorations never get a slot at all on a I-class day, no matter how many are - due; at most one privileged one does, the highest-dignity one if - several are. *) - (match List.filter is_privileged sorted with [] -> [] | best :: _ -> [ best ]) + due; at most one privileged one does, the highest-precedence one + (RG 113: {!band}'s own table order) if several are. *) + (match List.filter is_privileged sorted with [] -> [] | best :: _ -> [ drop_band best ]) | Class2, true -> (* RG 111(b), primary text, RE-VERIFIED word for word against the scan (final fix wave; this sentence is the sole textual basis for the @@ -717,17 +915,18 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate) dropped if a privileged commemoration is due." Two clauses, not one: (i) a privileged commemoration, whenever due, categorically takes the day's one slot - -- not by comparing its dignity against the ordinary contender's, + -- not by comparing its precedence against the ordinary contender's, so an ordinary commemoration that would otherwise win on raw - dignity is still dropped once any privileged one is also due (the - asymmetric clause the brief and task report flag as deliberate, not - present at "other II class" below); (ii) failing that, the slot is - reserved SPECIFICALLY for a [Class2] candidate -- "de festo II - classis" is a RANK restriction, not merely "whichever ordinary - candidate has the best dignity": a III- or IV-class ordinary loser - (a plain commemoration-only saint with no privilege of its own) has - NO standing for this slot at all and must be entirely omitted, even - when it is the only candidate present. + table order is still dropped once any privileged one is also due + (the asymmetric clause the brief and task report flag as + deliberate, not present at "other II class" below); (ii) failing + that, the slot is reserved SPECIFICALLY for a [Class2] candidate -- + "de festo II classis" is a RANK restriction, not merely "whichever + ordinary candidate has the best table position": a III- or + IV-class ordinary loser (a plain commemoration-only saint with no + privilege of its own) has NO standing for this slot at all and + must be entirely omitted, even when it is the only candidate + present. Fix, Task 16 (primary-source-verified + missalemeum-confirmed): previously this fell back to "the best of [sorted], whatever its @@ -739,21 +938,21 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate) shows him "displaced" (omitted), never commemorated; the pre-fix code admitted him regardless. *) (match List.filter is_privileged sorted with - | best :: _ -> [ best ] + | best :: _ -> [ drop_band best ] | [] -> ( - match List.filter (fun (c, _) -> c.Precedence.cel.Celebration.rank = Class2) sorted with + match List.filter (fun (c, _, _) -> c.Precedence.cel.Celebration.rank = Class2) sorted with | [] -> [] - | best :: _ -> [ best ])) + | best :: _ -> [ drop_band best ])) | Class2, false -> (* RG 111: "other II class: one" -- no privilege-override clause here, unlike the Sunday case immediately above, so the day's one slot - goes to whichever candidate outranks the rest by dignity alone, - privileged or not. *) - (match sorted with [] -> [] | best :: _ -> [ best ]) + goes to whichever candidate outranks the rest by RG 113's own + table-of-precedence order ({!band}), privileged or not. *) + (match sorted with [] -> [] | best :: _ -> [ drop_band best ]) | (Class3 | Class4), _ -> - (* RG 111: "III-IV class: at most two" -- by dignity, same as the - non-Sunday II-class case, just with room for two. *) - take 2 sorted + (* RG 111: "III-IV class: at most two" -- by RG 113's table order, same + as the non-Sunday II-class case, just with room for two. *) + List.map drop_band (take 2 sorted) (* Task 11: RG 96 -- where an impeded I-class feast lands (docs/research/ rules-register.md §4, "Transfer/translation"). [band] decides who is @@ -766,9 +965,11 @@ let admit ~(observed : Vocab_ef.rank Precedence.candidate) RG 96's own text, register-transcribed: "the next following day that is not I or II class." [is_blocking] reads that off [Vocab_ef.rank] -- - RG 96 speaks of the day's CLASS (RG 8's four-way dignity), not [band]'s - finer 28-entry occurrence-table row, the same distinction {!admit} above - already draws for RG 111 ({!dignity}, not [band]). *) + RG 96 speaks of the day's CLASS (RG 8's four-way "dignity"), not [band]'s + finer 28-entry occurrence-table row -- unlike {!admit} above, which (RG + 113, Task B/ef-rg16a) now DOES use [band] itself for its own selection + order; RG 96's own text has no such finer-table reading, so [is_blocking] + stays on [Vocab_ef.rank] alone. *) let is_blocking (rank : Vocab_ef.rank) = rank = Vocab_ef.Class1 || rank = Vocab_ef.Class2 (* RG 96's own named exception (docs/research/rules-register.md §4, |
