open Colitur_kernel (* Step 1: the observed celebration's own proper. Step 2: the day's own temporal slug. Step 3: a weekday whose own slug has no entry says the preceding Sunday's Mass -- see the implementation comment on that branch in [readings] for the termination argument and why it is the Sunday's TEMPORAL, not observed, identity. Nothing here encodes "Lent has daily propers": the presence of an entry in [lectionary] is the sole discriminator -- this function does not branch on season, rank, or any other field to decide whether a temporal slug "ought" to have its own Mass. The WARRANT for that shape is lectio's own observed behaviour only, not a confirmed Missal citation: Lent 1 Monday returns its own Ezech 34:11-16, while Advent, Christmas and post-Pentecost Mondays return their Sunday's Mass, in both streams. docs/research/rules-register.md records this openly as unconfirmed against the primary source ("EF reading-selection rules ... Have lectio's behaviour; confirm against the Missal's ferial-Mass rubrics when coding") -- that confirmation has not been done; do not read this comment as citing RG/the Missal for the SELECTION rule itself, only [Lectionary.find]'s presence-or-absence as the mechanism. *) (* Days from a given weekday back to the preceding Sunday. Sunday itself yields 0, which is why step 3 must guard on it -- see [readings] below. *) let days_since_sunday : Date.weekday -> int = function | Date.Sun -> 0 | Date.Mon -> 1 | Date.Tue -> 2 | Date.Wed -> 3 | Date.Thu -> 4 | Date.Fri -> 5 | Date.Sat -> 6 let readings ~lectionary ~observed ~temporal ~date ~temporal_at = match observed.Celebration.citations with | _ :: _ as cs -> cs | [] -> ( match Lectionary.find lectionary temporal.Temporal.office.Celebration.slug with | Some cs -> cs | None -> ( (* Step 3: a feria with no proper of its own says the preceding Sunday's Mass. WARRANT is the same as step 2's -- lectio's own observed behaviour, not a confirmed Missal citation: this is the rule lectio hard-codes as data on the four Advent ferias (Advent II's readings copied verbatim onto the following Monday-Saturday) and leaves absent on the other slugs this step now also reaches; docs/research/rules-register.md already records the ferial-Mass selection rule itself as unconfirmed against the primary source. Guarded on weekday, but NOT because a Sunday reaching this branch would loop (fix round 1, coordinator review: the original comment here claimed exactly that, and it was wrong). [readings] is not recursive -- step 3's fallback is one flat [Lectionary.find], never a re-entrant call into [readings] -- so without the guard, [days_since_sunday Sun = 0] would just repeat the SAME [Lectionary.find] step 2 already ran and already got [None] from (same pure inputs, same date), and return [] once, normally. The chain as a whole terminates because every step either consults data (a lookup) or, here, a strictly EARLIER date via [temporal_at] -- no step ever calls back into [readings] itself, so there is no recursion anywhere in this function for a cycle to form in the first place. The real reason for the guard is simpler: a Sunday has no PRECEDING Sunday to resume -- consulting itself would be meaningless (it would re-ask the question step 2 just answered), not dangerous, so the guard exists to make that intent explicit rather than to prevent a runaway loop that was never actually possible. The preceding Sunday's TEMPORAL slug, never its observed one: the rubric is the preceding Sunday's Mass even in a year when a feast displaced that Sunday from being observed (see test_step3_uses_temporal_not_observed). [temporal_at] gives the temporal identity of any date, so the Sunday is reached by date arithmetic and a fresh call to the temporal cycle -- never by string surgery on [own_slug]: the slug shapes are genuinely inconsistent across seasons (e.g. [ef-advent-sunday-1] versus [ef-advent-1-monday], the week number on opposite sides of the season name), so deriving one from the other textually would be a latent bug the moment a season's naming convention differs. *) let offset = days_since_sunday temporal.Temporal.weekday in if offset = 0 then [] else let sunday = Date.add_days date (-offset) in let sunday_temporal = temporal_at sunday in match Lectionary.find lectionary sunday_temporal.Temporal.office.Celebration.slug with | Some cs -> cs | None -> []))