""" categories.py Single source of truth for the book's 10 occasion categories, plus the BONEYARD holding pen. Imported by classify_occasions.py, generate_petitions1.py, generate_petitions2.py, generate_latex.py, and coverage.py so the list only ever needs to change in one place. Note: MIL (Milestones) is organized by occasion/event rather than by emotional register, unlike the other categories -- that's intentional. A reader looking for "wedding" or "new grandchild" is thinking in terms of the event, not a feeling, so mixing organizing principles across categories serves findability better than forcing every category onto one axis. TMP and DRY, and WON and GRA, are deliberately close cousins -- each pair was split out of what used to be one overloaded category. TMP is about the reader's own conduct and character (sin, confession, self-control); DRY is about the *felt experience* of faith itself going flat, distant, or restless, without a specific fault attached. WON is cosmic/nature wonder and awe; GRA is plain, personal, everyday thankfulness. When an occasion could plausibly sit in either half of a pair, ask: is this about something the reader DID (TMP) or something they're FEELING (DRY)? Is this about the world at large (WON) or this reader's own day (GRA)? Each category is (code, display_name, scope) -- scope is the guidance given to the model when drafting or classifying occasions for that category; keep it concrete and a little generous, since it's easier to cull an over-broad match by hand later than to miss a good one. """ from collections import OrderedDict CATEGORIES = OrderedDict([ ("WON", ( "Wonder & Thanksgiving", "Cosmic and natural wonder: creation, the night sky, being " "rescued from danger, the sheer scale of the world -- awe at " "something outside the reader's ordinary day. Compare GRA for " "plainer, more personal thankfulness.", )), ("WWF", ( "Weariness, Worry & Fear", "Everyday burnout, anxiety, sleeplessness, money worry, fear of " "what's coming, ordinary overload -- ongoing and diffuse, not a " "single acute event.", )), ("GUI", ( "Guidance & Decisions", "Discernment, a big choice, not knowing what to do next, needing " "direction rather than comfort.", )), ("CRI", ( "Crisis & Emergency", "Acute, in-progress trouble: a hospital stay, a deathbed, sudden " "bad news, holding on hour to hour. Something is actively " "happening right now, not a lingering state.", )), ("LOS", ( "Loss", "Death, funerals, absence, the aftermath of losing someone or " "something -- the empty-chair, empty-room register, not the " "crisis of the event itself.", )), ("MIL", ( "Milestones", "A specific life passage or event, organized by OCCASION rather " "than by emotional register: wedding, the arrival of a new child, " "a new grandchild, graduation, retirement, a new job, a new home, " "an anniversary. Even a milestone that carries mixed feelings " "(retirement, a new job) belongs here if the occasion itself is " "the organizing fact, not the feeling.", )), ("TMP", ( "Temptation & Self-Examination", "Pride, envy, broken self-control, confession, disappointment in " "oneself, mixed motives -- the reader examining their own " "conduct and character. Something they did, or are tempted to " "do, not simply a mood. Compare DRY.", )), ("DRY", ( "Spiritual Dryness & Discontent", "Restlessness, drifting, discouragement in the life of faith, " "feeling distant from God, inner turmoil that isn't rooted in a " "specific fault -- the ache of a faith, or a day, that feels " "flat or far away. Compare TMP: this is a felt state, not a " "moral failure to confess.", )), ("REL", ( "Relationships", "Positive interactions between two or more people", )), ("CON", ( "Conflicts ", "Mistreatment, a hard conversation, having said the wrong thing, " "caring for someone else who is struggling, the ongoing work of " "a relationship or a community's repair -- unpleasant " "interactions between people.", )), ("GRA", ( "Gratitude", "Plain, personal thanksgiving: answered prayer, contentment, " "ordinary blessings, gratitude that's hard to access, remembering " "past help. This exists alongside WON so a simple 'thank you' " "for today's coffee isn't crowded out by cosmic awe -- favor " "inclusion here when an occasion is small and personal rather " "than vast.", )), ]) BONEYARD = "BONEYARD" VALID_CODES = list(CATEGORIES.keys()) def category_name(code: str) -> str: if code == BONEYARD: return "Boneyard (uncategorized)" return CATEGORIES[code][0] def scope_block() -> str: """Formatted for dropping into an LLM prompt.""" lines = [] for code, (name, scope) in CATEGORIES.items(): lines.append(f"{code} -- {name}: {scope}") return "\n".join(lines)