summaryrefslogtreecommitdiff
path: root/scripts/gen-sanctoral-ef.go
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gen-sanctoral-ef.go')
-rw-r--r--scripts/gen-sanctoral-ef.go101
1 files changed, 79 insertions, 22 deletions
diff --git a/scripts/gen-sanctoral-ef.go b/scripts/gen-sanctoral-ef.go
index 0812472..0a43869 100644
--- a/scripts/gen-sanctoral-ef.go
+++ b/scripts/gen-sanctoral-ef.go
@@ -233,6 +233,19 @@ type mmDay struct {
} `json:"sections"`
}
+// fetchOnce fetches one date's proper. KNOWN LIMITATION: missalemeum
+// returns one array element PER MASS on a date with more than one (25
+// December: three, ids ...m1/...m2/...m3) and this reads only `data[0]`,
+// the first -- so a commemoration attached specifically to a second or
+// third Mass (the calendarium's own "In secunda Missa: Commemoratio..."
+// pattern, e.g. St Anastasia on Christmas Day) is structurally invisible
+// to every caller of this function, not just harvestDate's own use of it.
+// See the PRIMARY-SOURCE NOTE above harvestDate for the fuller account --
+// in Anastasia's specific case this is moot (missalemeum's own
+// "commemorations" list is empty on all three of the date's records, not
+// just the first, so fixing this would not by itself recover her), but the
+// limitation is real and would matter for any date whose SECOND or third
+// Mass genuinely does carry a commemoration missalemeum's API records.
func fetchOnce(date string) (*mmDay, error) {
req, _ := http.NewRequest("GET", "https://www.missalemeum.com/en/api/v5/proper/"+date, nil)
req.Header.Set("User-Agent", ua)
@@ -350,6 +363,28 @@ func readingsFrom(d *mmDay) (first, gospel string) {
// wins. (14 August's "St. Eusebius, Conf." and 16 December's "St. Eusebius,
// Ep. et Mart." are two different people, both genuinely in the calendarium
// -- see slugOverride below, not a reason to drop either.)
+//
+// Of the four confirming examples above, three (Donatus, Romanus, Eusebius)
+// are fixed by this generator as of this note. **25 December's Anastasia is
+// NOT, and cannot be from this data source alone** -- a different, NOT
+// generator-fixable limitation, recorded so the next person does not
+// mistake her continued absence for an oversight of the fix above (she was
+// also missing at the branch point, so this is not a regression either):
+// the photographic scan places her "In secunda Missa: Commemoratio S.
+// Anastasiae Mart." -- specifically the SECOND of Christmas Day's three
+// Masses (missalemeum's own "2026-12-25" query independently confirmed to
+// return exactly three records, ids ...m1/...m2/...m3). Two compounding
+// problems, not one: fetchOnce (below) reads only `data[0]`, the FIRST
+// Mass, so this harvester cannot structurally see a commemoration attached
+// to a date's second or third Mass at all, for ANY date, not just this
+// one -- but ALSO, checked directly (not merely inferred from the
+// symptom), missalemeum's OWN "commemorations" list is empty on all THREE
+// of the 25 December records, not just the first -- so even a fetchOnce
+// rewritten to merge all of a date's Masses would still not recover her:
+// missalemeum's own data lacks her here, the same "transcription-shaped"
+// gap as Donatus/Romanus/Eusebius, just in the live API rather than the
+// static PDF this time. Not fixed: no source this generator reads carries
+// her.
// slugOverride gives a proper, distinct slug to a small number of
// commemorations whose title slugifies IDENTICALLY to an unrelated feast on
@@ -388,27 +423,48 @@ var slugOverride = map[string]string{
// lower, per the calendarium), but the function does not itself enforce
// it, so a future entry could reach it.
// - It is a proxy for "why was this saint never observed", not a citation.
-// 6-31 December is excluded from ever trusting the id-derived rank
-// below, REGARDLESS of what this heuristic would otherwise say, because
-// RG 68(d)/(e) settles two specific cases (Thomas Becket, 29 December;
-// Silvester, 31 December) directly: the calendarium's own row names
-// each a bare "Commemoratio" with NO class of its own, even though the
-// DAY they fall on is II class (a day within the Nativity Octave). A
-// rank-blind heuristic reading the day's own class here would (and,
-// before this exclusion, did) wrongly conclude "the day was strong
-// enough to explain the demotion, so the id's rank is trustworthy" --
-// right about the day, wrong about what the rubric actually says about
-// THESE two named commemorations specifically.
+// 17-31 December is excluded from ever trusting the id-derived rank
+// below, REGARDLESS of what this heuristic would otherwise say --
+// covering BOTH of round 1's own late-Advent/Christmas-octave rank
+// promotions, on two DIFFERENT strengths of evidence, recorded
+// separately because they are not the same case:
+// -- 26-31 December (RG 68(d)/(e), a positive citation): "die 29
+// decembris, fit commemoratio S. Thomae Episcopi et Mart.; die 31
+// decembris, fit commemoratio S. Silvestri I Papae et Conf." -- the
+// calendarium names each a bare "Commemoratio" with NO class of its
+// own, even though the DAY they fall on is II class (within the
+// Nativity Octave). Two REAL entries (Thomas Becket, Silvester) are
+// live here; see the call site's own comment.
+// -- 17-23 December (RG 91 entry 18, a PRECAUTIONARY exclusion, not a
+// positive citation): round 1 also promoted these late-Advent
+// ferias from class-3 to class-2 (same lineage, same coupling
+// shape as 26-31 December's own promotion). No live entry tests
+// this range today -- the sole sanctoral entry there, `thomas`
+// (21 December), is an OBSERVED class-2 feast reached via the
+// harvestDate `obs` path, not this function's id-rank-trust path
+// at all -- but unlike 26-31 December, there is no RG citation
+// stating that a saint commemorated here has NO independent class;
+// RG 91 entry 18 only ranks the FERIA, and (per defect 2's own
+// finding) a genuine class-2 FEAST commemorated here would
+// actually WIN against it (entry 16 above entry 18), so "the day
+// is class-2" does not reliably explain a class-2 saint's absence
+// the way it does for 26-31 December's own two named cases.
+// Excluded anyway, on the side of the KNOWN-safe default
+// (RankCommemoration) rather than risk repeating the identical
+// failure shape the day this range's own first real entry arrives.
//
-// The 6-31 December exclusion is also a warning about a structural hazard,
-// not just a one-off fix: this function calls calendar.Compute, i.e. it
-// reads the ENGINE's OWN computed temporal ranks to decide what DATA to
-// generate. A change to temporal_ef.go's ranking (e.g. promoting 26-31
-// December from class-4 to class-2, RG 67/68, landed in this same lineage)
-// can silently flip this function's verdict and rewrite generated data with
-// no code change to this file at all. Any future temporal_ef.go rank change
-// should re-check this function's own boundary cases, not just its own
-// tests.
+// This is also a warning about a structural hazard, not just a boundary
+// fix: this function calls calendar.Compute, i.e. it reads the ENGINE's OWN
+// computed temporal ranks to decide what DATA to generate. A change to
+// temporal_ef.go's ranking (e.g. round 1's own 17-23/26-31 December
+// promotions, RG 91 entry 18 / RG 67-68) can silently flip this function's
+// verdict and rewrite generated data with no code change to this file at
+// all -- confirmed by direct measurement, not just reasoned about: running
+// this function's body against the branch-point engine versus the current
+// one over the six reference years flips the verdict on 50 dates across
+// exactly these 13 MM-DD values (12-17 through 12-23, 12-26 through
+// 12-31), no others. Any future temporal_ef.go rank change should re-check
+// this function's own boundary cases, not just its own tests.
//
// harvestDate keeps a saint's commemoration id rank ONLY if every reference
// year in which it was seen returned true here -- a single false (an
@@ -418,8 +474,9 @@ var slugOverride = map[string]string{
// RankCommemoration, proving the id's rank is a candidate, not a verdict --
// see the call site's own comment).
func refYearExplainsAbsence(date time.Time) bool {
- if date.Month() == time.December && date.Day() >= 26 && date.Day() <= 31 {
- // RG 68(d)/(e): "die 29 decembris, fit commemoratio S. Thomae
+ if date.Month() == time.December && date.Day() >= 17 && date.Day() <= 31 {
+ // RG 68(d)/(e) (26-31 Dec) and RG 91 entry 18 (17-23 Dec,
+ // precautionary): "die 29 decembris, fit commemoratio S. Thomae
// Episcopi et Mart.; die 31 decembris, fit commemoratio S.
// Silvestri I Papae et Conf." -- both named as a bare
// "Commemoratio", no class. See this function's own doc comment.