Skip to content

Remove vestigial Day.saints field; de-duplicate feast_name/DayCommemoration overlap - #165

Open
brianglass wants to merge 4 commits into
mainfrom
feast-name-day-commemoration-audit
Open

Remove vestigial Day.saints field; de-duplicate feast_name/DayCommemoration overlap#165
brianglass wants to merge 4 commits into
mainfrom
feast-name-day-commemoration-audit

Conversation

@brianglass

Copy link
Copy Markdown
Owner

Summary

  • Removes Day.saints (JSONField) -- fully unused since the saint-model-refactor project moved to DayCommemoration, already flagged as deferred cleanup. Migration 0009; fixture regenerated via dumpdata and verified identical apart from the dropped field.
  • Resolves 62 of 75 identified cases where Day.feast_name and DayCommemoration were redundantly encoding the same saint:
    • 41 where Slavic and Greek both elevate the saint (confirmed against data/antiochian_raw/'s multi-year harvested history) -- text moved into the existing DayCommemoration entry.
    • 18 where Slavic elevates a saint Greek doesn't (Herman of Alaska, Alexander Nevsky, Vladimir, Seraphim of Sarov, Boris & Gleb, etc.) -- genuine Slavic/Greek Day-row split, feast_level moves with the saint.
    • 3 ambiguous cases with a permanent co-occurring Dominical event (Basil the Great/Circumcision, Theodosius the Cenobiarch/Theophany-afterfeast, Symeon Stylites/New Year) -- resolved via individual research, no independent Greek demotion found.
    • Remaining 13 have no existing DayCommemoration row at all -- left alone; creating one is a data-entry task, not a reconciliation.
  • minimal_saints redesigned from a day_native-based grouping (broke down for "story-only" commemorations) to a plain length cap (MINIMAL_SAINTS_LIMIT=3), now also used by the monthly calendar grid, which previously rendered an unbounded list per cell.
  • Fixed a latent gap: test_ical.py's CalendarTest never loaded the commemorations.json fixture, so DayCommemoration was silently empty in that test's world.

Test plan

  • Full suite: 142 tests, only the pre-existing test_translation_changes_passage_content flake (confirmed unrelated, present on a clean main baseline).
  • Every fixture regeneration verified via dumpdata + semantic diff (field-by-field comparison) before being copied into place -- confirmed each diff matches exactly the intended change, nothing else.
  • Spot-checked rendered feasts/saints output across both traditions for representative dates in each tier, plus the Julian-calendar civil-date mechanism (issue Modern (post-1900) saints misplaced or missing in Julian-calendar mode #146) to confirm no regression.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3

brianglass and others added 4 commits August 7, 2026 13:53
…ration overlap

Drop Day.saints (JSONField) -- fully unused since the saint-model-refactor
project moved to DayCommemoration; no code read it, and it was already
flagged as deferred cleanup in docs/saint-model-refactor.md. Migration
0009 removes it; fixtures/calendarium.json regenerated via dumpdata and
verified identical apart from the dropped field.

Separately, an architecture review of Day vs. DayCommemoration (prompted
by noticing feast_name sometimes crams multiple names into one string,
e.g. "Leavetaking of Transfiguration; St Tikhon of Zadonsk") found that
164 Day.feast_name entries encode person-level facts that DayCommemoration
already models properly, with per-tradition granularity feast_name lacks.
Of these, 75 turned out to be real saints (vs. season/Forefeast/Leavetaking
labels, which correctly stay on Day). Resolved 62 of the 75:

- 41 where Slavic and Greek both elevate the same saint (confirmed via
  data/antiochian_raw/'s harvested history, sampling multiple years and
  discounting years where the date fell on a Sunday, since Antiochian's
  title field switches to the paschal-cycle Sunday name that year
  regardless of the saint's actual rank): text moved from feast_name into
  the existing (previously suppressed) DayCommemoration entry.
- 18 where Slavic elevates a saint Greek doesn't (Herman of Alaska,
  Alexander Nevsky, Vladimir, Seraphim of Sarov, Boris & Gleb, etc.): got
  a genuine Slavic/Greek Day-row split -- feast_level moves with the
  saint onto a slavic-tagged row, a new greek-tagged row keeps the day's
  other (non-elevated) content. One planned split (Aug 13, Tikhon of
  Zadonsk) turned out unnecessary once the data confirmed the elevation
  belongs to "Leavetaking of Transfiguration" itself, independent of Tikhon.
- 3 ambiguous cases where a Dominical/calendar event permanently
  co-occurs (Basil the Great/Circumcision on Jan 1, Theodosius the
  Cenobiarch/Theophany-afterfeast on Jan 11, Symeon Stylites/Ecclesiastical
  New Year on Sep 1), resolved via individual research: none showed
  independent Greek-specific demotion, so all three got the same
  no-split treatment as the 41.

The remaining 13 (7 fixed-date + 5 movable Lenten Sundays, plus one
Theotokos-icon edge case) have no existing DayCommemoration row at all --
left alone, since creating one is a data-entry task, not a
reconciliation.

Also fixed along the way:
- minimal_saints was a day_native-based grouping that broke down as soon
  as a "story-only" commemoration needed to be the thing shown (exactly
  this audit's use case). Replaced with a plain length cap
  (MINIMAL_SAINTS_LIMIT=3) on the full saints list, used both by
  summary_title's fallback and (newly) the monthly calendar grid, which
  previously rendered an unbounded saints list per cell.
- test_ical.py's CalendarTest never loaded the commemorations.json
  fixture, so DayCommemoration was silently empty in that test's world --
  a latent gap this audit's changes exposed.
- Several tests updated to check the new (correct) location of moved
  text rather than the old feast_name string, preserving each test's
  original intent (documented inline).

Full suite: 142 tests, only the pre-existing test_translation_changes_passage_content
flake (confirmed unrelated, present on a clean main baseline).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
…ints

Closes out the feast_name/DayCommemoration audit: these 12 person-type
feast_name entries had no existing DayCommemoration row at all, so they
couldn't be reconciled the way the other 62 were. Created a new Saint +
DayCommemoration for each, tagged by confirmed presence/absence in
data/antiochian_raw/:

- 3 confirmed present for Greek too (Theodosius of Chernigov, the Royal
  Martyrs of Russia, Juvenaly & Peter the Aleut of Alaska -- Antiochian's
  own harvested description text names all three explicitly) -- tagged
  'common'.
- 3 confirmed absent from Greek's commemorations on these specific dates
  (Innocent of Moscow, Tikhon of Moscow, John Kochurov) -- tagged
  'slavic'. feast_level on these dates was already correctly justified by
  something else independently confirmed tradition-invariant in the
  earlier tier-1 pass (Apostle Thomas, Apostle James son of Alphaeus), so
  no Day-row split was needed.
- 4 universal Triodion Sundays (Theodore Tyro, Gregory Palamas, John
  Climacus, Mary of Egypt) -- tagged 'common' without needing per-date
  verification, since these are canonically identical fixed points in the
  Lenten cycle across every Byzantine-rite jurisdiction, not a
  jurisdiction-specific commemoration.
- St Raphael of Brooklyn's movable (Antiochian's own "first Saturday of
  November") occasion reuses the same Saint identity already created for
  his fixed Feb 27 Slavic entry, rather than a new one -- same person, a
  different commemorated occasion.

Updated two tests whose assertions still pointed at the old feast_name
location for text this change (and tier 1/2) moved into the ordinary
saints list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
The feast_name/DayCommemoration de-duplication audit blanked feast_name
on ~62 dates where the text was redundant with a DayCommemoration entry
-- but for dates where that commemoration IS the day's whole identity
(Peter & Paul, the Beheading of the Forerunner, Nicholas, etc.), this
also silently dropped them from the page/API title, since day.feasts
(not day.saints) drives it. Restore the original feast_name text
(recovered from git history) on 52 of those dates and revert their
DayCommemoration.ordering back to -1 so each shows once, as the title,
rather than duplicating in the ordinary Commemorations list.

Three cases deliberately excluded:
- Aug 13 (Tikhon of Zadonsk) and Jul 5 (Sergius/Athanasius): the
  original text was a semicolon-joined combo of two distinct
  commemorations -- restoring it would reintroduce exactly the pattern
  this whole effort is meant to remove.
- Aug 9 (Herman's canonization) and May 7 (Alexis Toth): new_style
  (civil-date-anchored) facts. Day.feast_name has no new_style gating,
  so putting them there bled onto the Julian-shifted label date,
  reintroducing the #146 bug class. Left as ordinary saints-list
  entries.

Also simplify readings.html: merge the old standalone Feasts section
into the header (day.feasts now drives the title directly), and drop
the Commemorations-section-relabels-to-Feasts heuristic in favor of
always showing "Commemorations".

Verified corpus-wide: zero remaining feast_name values with semicolons.
142/142 tests pass; two golden JSON fixtures (last_bday.json,
january.json) regenerated and diffed field-by-field to confirm only the
intended feast_name/feasts/summary_title/saints fields changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
The previous commit's dumpdata regeneration used --indent 1 instead of
the repo's established --indent 2, reindenting every line in both files
and burying the actual 52-row content diff in ~99k lines of pure
whitespace churn. Recreated with --indent 2; content is byte-identical
to the previous commit (verified programmatically, zero field-level
differences) -- this is a pure formatting fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant