Saint search page, DayCommemoration/Saint many-to-many, and extensive saint-identity data cleanup - #175
Merged
Merged
Conversation
Adds /saints/ (search by name/full_name/commemoration title) and /saints/<pk>/ (a saint's full commemoration history: every occasion it's listed under, with links down to whichever of them actually have story text -- reusing the empty-story detection from the _has_story() work in #172). Query matches Saint.name, Saint.full_name, or any of that saint's DayCommemoration.title values, deduplicated to one row per saint -- mirrors the search logic already proven in mcp_svc/tools.py's search_saints tool, just re-scoped from commemoration-level results to saint-level identities so "click a match" has one obvious destination. Moveable-feast occasions (pdist != 999) get a "Moveable (Pascha +/-N days)" label instead of a month/day, since there's no year-independent calendar date for those. Genuinely a mockup: no tests yet, and searching "Seraphim of Sarov" immediately surfaces a real, still-open data-quality gap (only one Saint identity comes back, when the repose/relics-uncovering split noted in docs/saint-model-refactor.md may still exist for other saints) -- exactly the kind of thing this page seems useful for finding. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
…identity investigation groundwork Break search queries into AND'd terms so "John Theologian" finds "St. John the Theologian"; prefer Saint.full_name for display since Saint.name is often occasion-specific; add slug-based URLs (disambiguated by earliest fixed-calendar date) via a backfill management command instead of exposing raw pks; clean up 10 fixture rows where name/full_name had drifted apart; drop the redundant commemorations list from the detail page and restyle the remaining story headings to match the readings page. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
…-identity saints and two abbamoses title/story mismatches Replace DayCommemoration.saint (FK) with a saints M2M through DayCommemorationSaint (order controls multi-saint display order), so a commemoration naming several people can link to each of their real solo Saint identities instead of a synthetic joint pseudo-identity. Use the new relationship to fix 7 fragmented saints where a joint or duplicate commemoration was hiding a real story on an otherwise-orphaned solo entry: Athanasius/Cyril, Basiliscus, Onesimus, Theodota (mother of Cosmas and Damian), St Innocent, Hermas of the Seventy, and Juvenaly of Alaska (spanning three dates). Also cross-checked two mismatched entries against the original abbamoses scrape and found the same root cause in both: a terse, independently sourced title had absorbed the wrong same-day story from an old matching pass. Moved Kyranna's story onto her existing (previously story-less) Greek-tradition entry, and added a missing commemoration for James the Confessor of the Studion whose story had been stranded under the unrelated "James the Confessor of Catania" title. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
Add Saint.normalized_name, derived from name/full_name by canonicalizing known Greek<->Latin transliteration substitutions (c/k, y/i, word-final os/us), so searching "Athanasios" finds "St Athanasius the Great" and similar cross-spelling pairs found during the earlier dedup pass (Dionysius/Dionysios, Sergius/Sergios, Cosmas/Kosmas, Isaac/Isaak). Backfilled via a management command rather than Saint.save(), since fixture loading bypasses custom save() the same way it does for slug -- confirmed by the test suite needing the same backfill call in setUp that production gets from the Dockerfile. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
Same fragmented-identity pattern as the earlier Athanasius/Cyril-era fixes -- a saint's full biographical entry and their "translation of the relics"/"finding of the head" entry existed as two unlinked Saint rows. These slipped past earlier dedup passes because those required an exact name match after stripping occasion prefixes, and these pairs all differ in trailing epithets (e.g. "Nicholas the Wonderworker" vs "Nicholas the Wonderworker, Archbishop of Myra"). Found via a token-overlap scan targeted at occasion-marked entries, each confirmed individually via story cross-reference or a highly specific shared epithet before merging: - Nicholas of Myra (Dec 6 repose <-> May 9 translation to Bari) - Nilus of Sora (Apr 7 repose <-> May 7 repose entry) - Matrona of Chios (Oct 20 <-> Jul 15 finding of the head) - Cyrus and John, Unmercenaries (Jan 31 <-> Jun 28, explicit "see January 31" cross-reference) - Nicephorus, Patriarch of Constantinople (Jun 2 <-> Mar 13, explicit "his main commemoration is on June 2") - Stephen the Protomartyr (Dec 27 <-> Aug 2 finding of relics) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
…tion leaks, and merge more fragmented identities Search improvements: - Exclude Saint results with no story on any commemoration -- a dead end that led nowhere useful on the detail page. - Fix title-based search matching leaking across saints sharing a joint commemoration (e.g. searching "Chrysostom" no longer also returns Basil and Gregory just because their shared "Synaxis of the Three Holy Hierarchs" title mentions him) -- refined so a term only counts as shared when no saint on the commemoration specifically owns it in their own name/full_name, so genuinely shared terms like "Hierarchs" still correctly match everyone in the group. - Remove inherited full-justification on search result text. - Extract the shared matching logic (term-splitting, transliteration, shared-title handling) into commemorations/search.py so the MCP server's search_saints tool uses the same logic as the web search instead of a separately-drifted, less capable implementation (it was missing multi-term matching, transliteration matching, and the joint-commemoration leak fix). Data fixes -- more fragmented saint identities found via search and merged following the same pattern as the Athanasius/Cyril case: - Theotokos: the one non-icon-specific "Synaxis" entry merged into the canonical Theotokos row; icon-specific Synaxis entries (Three Hands, Miasenae, Evangelistria, etc.) deliberately left separate. - John Chrysostom, Gregory the Theologian: each had an unlinked translation/removal-of-relics entry merged into their main entry; the "Synaxis of the Three Holy Hierarchs" now links directly to all three real saints (Basil, Gregory, Chrysostom) instead of a redundant joint stub. - St Xenia of St Petersburg: canonization entry merged into her main entry. - Archangel Gabriel: three unlinked entries (Leavetaking of Annunciation, the Mt Athos "Axion Estin" appearance, and the joint "Chief Captains" Synaxis with Michael) all merged/relinked into one canonical identity. CSS fixes: - body's overflow-x: hidden implicitly makes overflow-y compute as auto rather than visible, so on a short page (e.g. search with no results) body's box could end before the open hamburger dropdown's full height, clipping it. Added min-height: 100dvh so there's always room. - Widened the hamburger-menu breakpoint (1250px -> 1350px) -- adding "saints" to the nav shrank the safety margin between the measured wrap point and the breakpoint to ~35px, thin enough for real-browser font rendering to tip it into visible wrapping before the hamburger kicks in. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3
This was referenced Aug 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/saints/) and detail page, with search across name, full_name, transliteration-normalized spelling variants (e.g. "Athanasios" finds "Athanasius"), and linked commemoration titles.DayCommemoration.saint(a single FK) with asaintsmany-to-many throughDayCommemorationSaint(which carries a displayorder), so a commemoration naming multiple people can link to each of their real Saint identities instead of a synthetic joint pseudo-identity.search_saintstool up to parity with the web search by extracting the shared matching logic intocommemorations/search.py.Test plan
liturgics.Day(...)and the saint detail page before committing🤖 Generated with Claude Code
https://claude.ai/code/session_01Hf6j2xXQXywHVh3HAVRxB3