This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/src/scripture/meditation.py
Claude 63bbe2a288 feat: add sovereign biblical text integration module (scripture)
Implement the core scripture module for local-first ESV text storage,
verse retrieval, reference parsing, original language support,
cross-referencing, topical mapping, and automated meditation workflows.

Architecture:
- scripture/constants.py: 66-book Protestant canon with aliases and metadata
- scripture/models.py: Pydantic models with integer-encoded verse IDs
- scripture/parser.py: Regex-based reference extraction and formatting
- scripture/store.py: SQLite-backed verse/xref/topic/Strong's storage
- scripture/memory.py: Tripartite memory (working/long-term/associative)
- scripture/meditation.py: Sequential/thematic/lectionary meditation scheduler
- dashboard/routes/scripture.py: REST endpoints for all scripture operations
- config.py: scripture_enabled, translation, meditation settings
- 95 comprehensive tests covering all modules and routes

https://claude.ai/code/session_015wv7FM6BFsgZ35Us6WeY7H
2026-02-26 17:06:00 +00:00

212 lines
7.6 KiB
Python

"""Meditation scheduler — automated scripture engagement workflows.
Provides background meditation capabilities for the "always on its mind"
requirement. Supports three modes:
- **Sequential**: book-by-book progression through the Bible
- **Thematic**: topical exploration guided by Nave's-style index
- **Lectionary**: cyclical reading patterns following liturgical calendars
The scheduler integrates with the ScriptureMemory system to persist
progress and working memory state across restarts.
"""
from __future__ import annotations
import logging
import random
from datetime import datetime, timezone
from typing import Optional
from scripture.constants import BOOK_BY_ID, BOOKS
from scripture.memory import ScriptureMemory, scripture_memory
from scripture.models import MeditationState, Verse, decode_verse_id, encode_verse_id
from scripture.store import ScriptureStore, scripture_store
logger = logging.getLogger(__name__)
class MeditationScheduler:
"""Orchestrates automated meditation workflows.
Usage::
from scripture.meditation import meditation_scheduler
# Advance to the next verse in sequence
result = meditation_scheduler.next_meditation()
# Get the current meditation focus
current = meditation_scheduler.current_focus()
"""
def __init__(
self,
store: ScriptureStore | None = None,
memory: ScriptureMemory | None = None,
) -> None:
self._store = store or scripture_store
self._memory = memory or scripture_memory
@property
def state(self) -> MeditationState:
return self._memory.associative.get_meditation_state()
def set_mode(self, mode: str, theme: Optional[str] = None) -> MeditationState:
"""Change the meditation mode (sequential / thematic / lectionary)."""
state = self.state
if mode not in ("sequential", "thematic", "lectionary"):
raise ValueError(f"Unknown mode: {mode}")
state.mode = mode
state.theme = theme
self._memory.associative.save_meditation_state(state)
return state
def current_focus(self) -> Optional[Verse]:
"""Return the verse currently in meditation focus."""
state = self.state
return self._store.get_verse(
state.current_book, state.current_chapter, state.current_verse
)
def next_meditation(self) -> Optional[Verse]:
"""Advance to the next verse and return it.
Dispatches to the appropriate strategy based on current mode.
"""
state = self.state
if state.mode == "thematic":
return self._next_thematic(state)
if state.mode == "lectionary":
return self._next_lectionary(state)
return self._next_sequential(state)
def meditate_on(self, verse: Verse, notes: str = "") -> None:
"""Record meditation on a specific verse and bring into focus."""
self._memory.working.focus(verse)
self._memory.associative.log_meditation(
verse.verse_id, notes=notes, mode=self.state.mode
)
state = self.state
state.advance(verse.book, verse.chapter, verse.verse_num)
self._memory.associative.save_meditation_state(state)
def get_context(self, verse: Verse, before: int = 2, after: int = 2) -> list[Verse]:
"""Retrieve surrounding verses for contextual meditation."""
start_id = encode_verse_id(verse.book, verse.chapter, max(1, verse.verse_num - before))
end_id = encode_verse_id(verse.book, verse.chapter, verse.verse_num + after)
return self._store.get_range(start_id, end_id)
def get_cross_references(self, verse: Verse) -> list[Verse]:
"""Retrieve cross-referenced verses for expanded meditation."""
xrefs = self._store.get_cross_references(verse.verse_id)
results = []
for xref in xrefs:
target_id = (
xref.target_verse_id
if xref.source_verse_id == verse.verse_id
else xref.source_verse_id
)
target = self._store.get_verse_by_id(target_id)
if target:
results.append(target)
return results
def history(self, limit: int = 20) -> list[dict]:
"""Return recent meditation history."""
return self._memory.associative.get_meditation_history(limit=limit)
def status(self) -> dict:
"""Return meditation scheduler status."""
state = self.state
current = self.current_focus()
book_info = BOOK_BY_ID.get(state.current_book)
return {
"mode": state.mode,
"theme": state.theme,
"current_book": book_info.name if book_info else f"Book {state.current_book}",
"current_chapter": state.current_chapter,
"current_verse": state.current_verse,
"current_text": current.text if current else None,
"verses_meditated": state.verses_meditated,
"last_meditation": state.last_meditation,
}
# ── Private strategies ───────────────────────────────────────────────
def _next_sequential(self, state: MeditationState) -> Optional[Verse]:
"""Sequential mode: advance verse-by-verse through the Bible."""
book = state.current_book
chapter = state.current_chapter
verse_num = state.current_verse + 1
# Try next verse in same chapter
verse = self._store.get_verse(book, chapter, verse_num)
if verse:
self.meditate_on(verse)
return verse
# Try next chapter
chapter += 1
verse_num = 1
verse = self._store.get_verse(book, chapter, verse_num)
if verse:
self.meditate_on(verse)
return verse
# Try next book
book += 1
if book > 66:
book = 1 # Wrap around to Genesis
chapter = 1
verse_num = 1
verse = self._store.get_verse(book, chapter, verse_num)
if verse:
self.meditate_on(verse)
return verse
return None
def _next_thematic(self, state: MeditationState) -> Optional[Verse]:
"""Thematic mode: retrieve verses related to current theme."""
if not state.theme:
# Fall back to sequential if no theme set
return self._next_sequential(state)
topics = self._store.search_topics(state.theme, limit=1)
if not topics:
return self._next_sequential(state)
verses = self._store.get_verses_for_topic(topics[0].topic_id)
if not verses:
return self._next_sequential(state)
# Pick the next un-meditated verse (or random if all visited)
history_ids = {
e["verse_id"]
for e in self._memory.associative.get_meditation_history(limit=1000)
}
for v in verses:
if v.verse_id not in history_ids:
self.meditate_on(v)
return v
# All verses in topic visited; pick a random one
chosen = random.choice(verses)
self.meditate_on(chosen)
return chosen
def _next_lectionary(self, state: MeditationState) -> Optional[Verse]:
"""Lectionary mode: placeholder — rotates through key passages.
A full lectionary implementation would integrate the Revised Common
Lectionary or similar. This simplified version cycles through
thematically significant passages.
"""
# Simplified: just advance sequentially for now
return self._next_sequential(state)
# Module-level singleton
meditation_scheduler = MeditationScheduler()