(* RG 475-476 (docs/research/LT.txt, grep "dicitur symbolum"; scan1.txt line ~3872-3888), quoted here in full so every branch below can cite its own letter without re-quoting the whole rubric: "475. Post Evangelium aut homiliam, dicitur symbolum: a) in qualibet dominica, etsi eius Officium alicui festo locum cedat, vel Missa votiva II classis celebretur; b) in festis I classis et in Missis votivis I classis; c) in festis II classis Domini et B. Mariae Virg.; d) per octavas Nativitatis Domini, Paschatis et Pentecostes, etiam in festis occurrentibus et in Missis votivis; e) in festis nataliciis Apostolorum et Evangelistarum, necnon in festis Cathedrae S. Petri et S. Barnabae Ap. 476. Non dicitur symbolum: a) in Missis sive chrismatis sive in Cena Domini, feria V Hebdomadae sanctae, et in Missa Vigiliae paschalis; b) in festis II classis, iis exceptis quae supra, n. 475 c et e, recensentur; c) in Missis votivis II classis; d) in Missis festivis et votivis III et IV classis; e) ratione alicuius commemorationis in Missa occurrentis; f) in Missis defunctorum." SCOPE NOTE, checked once here rather than at every clause below: this engine resolves ONE observed office and ONE Mass per civil day (see Rite.t.readings' own doc comment) -- it has no separate "which votive Mass is said" dimension. So the "vel/et...votivis" halves of 475(a)/(b), 476(c) entirely, and 476(d)'s "et votivis" half are genuinely inapplicable to this implementation -- a documented scope limit, not a defect. 476(e) needs no branch at all: [creed] below reads only [observed], never a day's admitted commemorations, so a commemoration can never change its answer by construction. 476(f) ("in Missis defunctorum") is DIFFERENT: this file used to carry it in the same "not modelled" list above, on the reasoning that [creed]'s inputs (temporal/observed/date) have no notion of "this Mass is a Requiem". That reasoning was wrong, found by the LMS Ordo layer (test_lms_ordo.ml, allow-list entry L1, now closed -- see expected-divergences-lms.sexp) on 2025-11-03, All Souls' Day: colitur said the Creed where the Ordo, correctly, does not. [observed] DOES carry a usable signal -- RG 117 assigns black to Masses of the dead, and {!Colour.Black} is used by exactly TWO celebrations in this whole engine, verified by grepping every [colour Black]/[Colour.Black] site in lib/ and data/: [commemoration-of-all-souls] in data/ef/sanctoral.sexp, and Good Friday in temporal_ef.ml (which is a Holy Week FERIA, RG 23(b), already excluded by the [n >= -6 && n <= -1] branch below regardless of colour, and has no Mass at all in the 1955-restored Holy Week). So on every day this engine can actually construct, [colour = Black] if and only if the Mass is a Requiem -- a citable implication ON THIS DATA, not a heuristic guess. [creed] below uses it as 476(f)'s own guard. This is a PROXY, not a general "is this a Requiem Mass" field, and it is only as good as that two-member population: {!test_rubrics_ef}'s own [test_colour_black_population_is_exactly_two] fails loudly the day a third [Colour.Black] celebration is added anywhere, so the proxy cannot silently rot into covering (or missing) a non-Requiem black Mass. If that ever happens, this guard needs re-deriving, not merely re-approving. *) open Colitur_kernel (* RG 475(e): "in festis nataliciis Apostolorum et Evangelistarum, necnon in festis Cathedrae S. Petri et S. Barnabae Ap." NATALICIUM means the feast of the saint's own death (dies natalis) -- not every feast that merely names him. That is precisely why the clause has to name the Chair of St Peter and St Barnabas EXPLICITLY: neither is a natalicium (Peter's own is 29 June, shared with Paul; Barnabas's is his own day, 11 June, but the clause names him anyway, redundantly with the natalicium reading, rather than leave it to inference), so neither would be covered without the explicit "necnon". DERIVED, not copied from any list supplied with this task: grepped data/ef/sanctoral.sexp directly for every entry whose English or Polish name mentions "Apostle"/"Evangelist"/"Aposto{l/ł}a", then each candidate's own date, rank and status checked against the calendarium and against whether it is that saint's own dies natalis. Every entry below was cross-checked against the shipped data, not assumed: andrew (30 Nov, Class2) -- his natalicium. barnabas (11 June, Class3) -- named explicitly; also his own natalicium. bartholomew (24 Aug, Class2) -- his natalicium. chair-of-st-peter (22 Feb, Class2) -- named explicitly ("Cathedrae S. Petri"); NOT a natalicium (Peter's own is 29 June, shared with Paul) -- exactly why the clause has to name it. james-the-greater (25 July, Class2) -- his natalicium. john-the-evangelist (27 Dec, Class2) -- his natalicium (the one Apostle traditionally held to have died a natural death; "natalicium" still names his own feast day, not only a martyr's). luke-the-evangelist (18 Oct, Class2) -- his natalicium. mark (25 April, Class2) -- the Evangelist ("Marka Ewangelisty" in the data's own Polish name); NOT "mark-i" (7 Oct), a different saint (a Pope), excluded. matthew (21 Sep, Class2) -- Apostle and Evangelist, his natalicium. matthias (24 Feb, Class2) -- his natalicium. sts-peter-paul (29 June, Class1) -- the natalicium of both. sts-philip-james (11 May, Class2) -- the natalicium of both (James the Less; there is no separate "james-the-less" entry in the data). sts-simon-jude (28 Oct, Class2) -- the natalicium of both. thomas (21 Dec, Class2) -- his natalicium. Checked and DELIBERATELY EXCLUDED (the Trap this clause is built around): conversion-of-st-paul (25 Jan, Class3) -- not a natalicium: it commemorates an EVENT of his life, not his death. in-commemoratione-sancti-pauli-apostoli (30 June, Class3, status Feast, so it CAN be observed, unlike the two entries below) -- a secondary commemoration of Paul, not his dies natalis (his own is 29 June, with Peter); its own name says so ("In Commemoratione", not a feast of his martyrdom). "peter" (25 Jan) and "paul" (22 Feb) -- both status [Commemoration_only] (RG 110's own Peter/Paul companions, on the Conversion and Chair days respectively: {!Precedence_ef.disposition}'s own citation), so neither can ever be [observed]; moot either way, but neither is a natalicium regardless. mark-i (7 Oct) -- a different saint (Pope St Mark), not the Evangelist. *) let creed_apostle_slugs = [ "andrew"; "barnabas"; "bartholomew"; "chair-of-st-peter"; "james-the-greater"; "john-the-evangelist"; "luke-the-evangelist"; "mark"; "matthew"; "matthias"; "sts-peter-paul"; "sts-philip-james"; "sts-simon-jude"; "thomas" ] let creed ~(temporal : (Vocab_ef.season, Vocab_ef.rank) Temporal.t) ~(observed : Vocab_ef.rank Celebration.t) ~(date : Date.t) : bool = let easter = Computus.gregorian_easter (Date.year date) in let n = Date.to_rata date - Date.to_rata easter in let m = Date.month date and dd = Date.day date in let slug = Slug.to_string observed.Celebration.slug in if (* RG 475(d): "per octavas Nativitatis Domini, Paschatis et Pentecostes, etiam in festis occurrentibus et in Missis votivis" -- an unconditional window override, checked first: EVEN a saint's feast that wins the day within one of the three octaves (St Stephen, 26 December, is the live witness -- RG 67's own "Com. octavae Nativitatis" note, quoted in full in temporal_ef.ml's [named]) still says the Creed. Pure date/Easter-offset arithmetic, not season or rank: Ascension (Easter+39) and the Pentecost Vigil (Easter+48) are both [Class1] and both fall inside the Paschaltide SEASON but outside either 8-day OCTAVE, so a rank- or season-based test here would wrongly include them -- checked and rejected for exactly this reason. Nativity: 25-31 December (its own day plus 7) + 1 January (RG 91 entry 5's own "Octave Day of the Nativity", the identical table entry as 24 December's vigil -- temporal_ef.ml's [named]). Easter: Easter Sunday (offset 0) through Low Sunday (offset 7) -- RG 11's own "dominicae Paschatis et Pentecostes sunt pariter festa I classis CUM OCTAVA". Pentecost: Pentecost (offset 49) through Trinity Sunday (offset 56), the RG 91-entry-14-adjacent "octave day" Trinity Sunday itself names in temporal_ef.ml. *) (m = 12 && dd >= 25 && dd <= 31) || (m = 1 && dd = 1) || (n >= 0 && n <= 7) || (n >= 49 && n <= 56) then true else if (* RG 475(a): "in qualibet dominica, ETSI EIUS OFFICIUM ALICUI FESTO LOCUM CEDAT" -- the Creed is said on any Sunday even when a feast displaces the Sunday's own office (RG 16(a): a Feast of the Lord I or II class occurring on a II-class Sunday takes its place "cum omnibus iuribus et privilegiis"). Read off [temporal]'s own weekday -- the day's calendar fact, independent of whatever [observed] turns out to be -- never off [observed]'s slug or rank, which is exactly what would go silently wrong the day such an impeding feast wins: see {!Colitur_kernel.Precedence.rules.admit}'s own [~temporal] parameter (precedence.mli) for the identical argument, made there for RG 111(b) rather than RG 475(a). *) temporal.Temporal.weekday = Date.Sun then true else if (* RG 23 (Caput IV, "De Feriis"): "Feriae I classis sunt: a) feria IV cinerum; b) omnes feriae Hebdomadae sanctae." Ash Wednesday and every feria of Holy Week (Monday through Saturday -- RG 91 entry 2's Sacred Triduum, Thursday-Saturday, is a THIRD sub-case of this same "feria", not a "festum": RG 35, immediately below in Caput VI, defines "festum" as a distinct liturgical-day category from "feria", RG 21-27) are FERIAE, never FESTA, however high their RG 91 rank -- so 475(b)/(c)'s "in festis" never reaches them, regardless of rank. This single structural check subsumes 476(a)'s own explicit naming of the Chrism Mass, the Mass of the Lord's Supper (both Holy Thursday) and the Easter Vigil Mass (Holy Saturday's date): both are already excluded here as Holy Week feriae, so 476(a) needs no separate branch. (Good Friday needs no rubric at all -- RG 28's own closing sentence on the Paschal Vigil aside, Good Friday's own liturgical action has no Mass in the 1955-restored Holy Week to begin with, so the question is moot there independent of this check -- but this structural test correctly excludes it too, since it is also named in RG 23(b).) RG 24-25 (immediately following, same Caput IV) name TWO MORE ferial classes this branch does not reach: feriae II classis (RG 24 -- the Advent ferias 17-23 December, and the Quatuor Temporum sets of Advent, Lent and September) and feriae III classis (RG 25 -- the numbered Lenten/Passiontide ferias from the Thursday after Ash Wednesday to the Saturday before Passion Sunday II, and the un-Embered Advent ferias to 16 December). NEITHER is excluded by a check anywhere in this module -- this branch and RG 33's vigil branch immediately below are the whole of what [creed] tests before falling through to 475(b)/(c)/(e)'s own rank/subject/slug guards. They do not need an explicit exclusion of their own for 475(b): temporal_ef.ml's own [ferial_rank] never returns [Class1] for them (only Ash Wednesday and Holy Week do, RG 23's own population, already excluded above), so that branch is unreachable for them regardless of anything checked here. But RG 24's own II-class set DOES reach 475(c)'s [Class2] guard below, and 475(e)'s apostle-slug guard carries no rank floor at all, so both classes genuinely reach a live branch of this function. Getting [false] there is NOT established by this exclusion, or by any check in this file: it rests on an unstated property of {!Temporal_ef} -- every ferial-origin office it builds carries [subject = Temporal] and an "ef-"-prefixed slug, never [Lord]/[Bvm] or a name on {!creed_apostle_slugs}. Verified directly in temporal_ef.ml: the Ember/Rogation/generic-ferial branches all go through [build]'s own default [subject = Temporal], with exactly two documented exceptions, neither able to reach a live branch below -- the Sacred Triduum ([subject = Lord], but [Class1], already excluded above) and the votive Office of the BVM on Saturday, RG 91 entry 27 ([subject = Bvm], but [Class4], never satisfying 475(c)'s own [Class2] guard). (CORRECTED, review fix: this comment, and 475(b)'s own immediately below, previously read as though "the two exclusions immediately above" disposed of ferias in general -- they dispose of feria I classis only. RG 24/25's own higher classes were excluded by NO check, an unstated-invariant gap now named here rather than silently relied on: test/test_rubrics_ef.ml's own ferial-invariant sweep now asserts the Temporal_ef property above directly against real output, so a future change that broke it would fail that test rather than silently changing the Creed.) *) n = -46 || (n >= -6 && n <= -1) then false else if (* RG 28-34 (Caput V, "De Vigiliis"): a vigil is its OWN liturgical-day category, distinct from "festum" (RG 35, Caput VI) the same way a feria is (immediately above) -- so 475(b)/(c)'s "in festis" does not reach a vigil either, regardless of its own RG 91 rank. This is also why 476(a) has to name the Easter Vigil explicitly: RG 28's own closing sentence says the Paschal Vigil, uniquely, "non sit dies liturgicus" [is not a liturgical day] at all, so it is not even a "vigilia" in RG 29-32's numbered sense -- nothing else in this taxonomy would have excluded it without that explicit clause, unlike every OTHER vigil, which is excluded merely by being one. {!Precedence_ef.is_vigil} already tests both slug conventions this codebase's data uses (the temporal cycle's "-vigil" suffix and the sanctoral bootstrap's "vigil-of-" prefix) for the identical RG 33 question; reused here rather than re-derived, on the same footing as {!Precedence_ef.marian_slugs} just below. *) Precedence_ef.is_vigil slug then false else if (* RG 476(f): "in Missis defunctorum" -- the Creed is never said at a Requiem Mass, checked here, ahead of 475(b)'s rank branch, the same "category excludes regardless of rank" position as the feria and vigil checks immediately above (All Souls' Day is [Class1], so without this guard 475(b) would grant it [true] unopposed, which is exactly the defect this guard fixes -- see this file's own header for the two-member [Colour.Black] population this proxy rests on, and {!Colour.Black}'s own citation, RG 117, for why colour is the Requiem signal. Placed before, not after, 475(b)/(c)/(e) so a black Class1 or Class2 day can never reach them; nothing above this point (the Nativity/Easter/Pentecost octave override, the Sunday rule, the feria and vigil exclusions) is ever reachable by a Requiem Mass on the shipped data either -- a Requiem is never kept on a Sunday or inside a privileged octave -- so this guard's own position relative to THOSE branches is moot on real data, checked, not merely assumed: {!creed_apostle_slugs} and [marian_slugs] contain no Black-coloured entry, and 2 November can never fall inside any of the three octaves 475(d) names. *) observed.Celebration.colour = Colour.Black then false else if (* RG 475(b): "in festis I classis". Genuine feasts only, by construction of the two exclusions immediately above (feria I classis -- Ash Wednesday and Holy Week, the only feriae that are ever [Class1]; RG 24/25's II- and III-class feriae are a different population and never reach this rank at all, see the RG 23 comment's own note above -- and vigils) -- every remaining [Class1] candidate reaching this branch is a real festum: the Nativity, Epiphany, Ascension, Corpus Christi, the Sacred Heart, Christ the King, a I-class sanctoral feast (the Assumption, the Immaculate Conception...), or a I-class Sunday (already [true] above via 475(a), so this branch is never the FIRST to grant those a [true], only ever redundant with it). *) observed.Celebration.rank = Vocab_ef.Class1 then true else if (* RG 475(c): "in festis II classis Domini et B. Mariae Virg." -- [subject = Lord] is reliably set on genuine II-class sanctoral feasts of the Lord (Exaltation of the Holy Cross, the Purification, the Transfiguration, the Commemoration of the Baptism of the Lord, the Dedication of the Lateran Archbasilica -- checked directly against data/ef/sanctoral.sexp: six [subject = Lord] entries ship, none a vigil or feria) and on the two temporal-cycle Class2 Lord feasts (Holy Family, Holy Name of Jesus). [subject = Bvm], by contrast, is NOT reliable for the BVM half: checked directly against the data, almost every Marian sanctoral entry (the Assumption, the Annunciation, the Immaculate Heart, the Nativity of the BVM...) ships [subject = Saint] instead -- {!Precedence_ef.marian_slugs} is the list built (and, here, reused rather than re-derived) precisely because the [subject] field cannot be trusted alone for this question; see its own citation in precedence_ef.mli. This [Class2] guard is also the one live branch RG 24's own II-class feriae (Advent 17-23, the Advent/Lent/September Ember sets) genuinely reach -- the RG 23 comment above (this file, the [n = -46 ...] branch) has the full account of why they still come out [false] here: an unstated Temporal_ef property, checked by a test, not a guard in this file. *) observed.Celebration.rank = Vocab_ef.Class2 && (observed.Celebration.subject = Subject.Lord || observed.Celebration.subject = Subject.Bvm || List.mem slug Precedence_ef.marian_slugs) then true else (* RG 475(e): see {!creed_apostle_slugs}'s own citation. Checked last and without a rank guard, on purpose -- Barnabas is only [Class3] and the Chair of St Peter's own [subject] is [Saint], so neither would ever be reached by the two branches above; every [Class1] entry on the list (Sts Peter & Paul) is already [true] via 475(b), so this branch is redundant, never wrong, for those. *) List.mem slug creed_apostle_slugs