Proyecto independiente No afiliado, patrocinado ni avalado por la Watch Tower Bible and Tract Society o Jehovah's Witnesses.
jw-agent-toolkit
EN

Guía

Estudio personal y notas (Módulo 4 — Fase 14)

Cierra el ítem #4 de VISION.md: plan de lectura, notas personales con RAG, spaced-repetition, comparador entre traducciones, análisis de idiomas originales.

Componentes

MóduloArchivoFunción
Plan de lecturajw_core/study/reading_plan.py3 planes (año completo, NT 90 días, cronológico) + SQLite tracker
Notas personalesjw_core/study/personal_notes.pyPer-versículo, FTS5, export a RAG
Flashcards SM-2jw_core/study/flashcards.pySpaced repetition con SuperMemo-2
Idiomas originalesjw_core/study/originals.pyStrong’s catalog + carga dinámica de dumps
Agentejw_agents/personal_study.pyUne plan + notas + cards → AgentResult

Planes de lectura

from jw_core.study import ReadingPlanTracker, list_reading_plans

# Ver catálogo
for p in list_reading_plans("es"):
    print(p["key"], "—", p["title"], f"({p['days']} días)")

# Trackear progreso
with ReadingPlanTracker() as t:
    t.mark_done("nt_90", 1, note="Mateo terminado")
    print(t.status("nt_90"))
    print(t.upcoming("nt_90", count=3))

Default DB: ~/.jw-agent-toolkit/study.db (override JW_STUDY_DB).

Cobertura

  • whole_bible_year: 1189 capítulos / 365 días — ~3.26 capítulos/día.
  • nt_90: 27 libros del NT en 90 días.
  • chronological: Génesis + Éxodo + Job + resto AT + NT, en orden histórico aproximado.

Notas personales

from jw_core.study import PersonalNote, PersonalNoteStore

with PersonalNoteStore() as notes:
    notes.add(PersonalNote(
        book_num=43, chapter=3, verse=16,
        title="El amor de Dios", body="Notas sobre Juan 3:16...",
        tags=["amor", "salvación"], language="es",
    ))
    # Búsqueda FTS5 instantánea
    hits = notes.search("amor")
    # Filtro por anchor
    for_juan = notes.for_anchor(43, 3, 16)

Privacidad: SQLite local en ~/.jw-agent-toolkit/notes.db (override JW_NOTES_DB). Cero red.

Export a RAG:

from jw_core.study import notes_to_rag_chunks
from jw_rag import VectorStore, FakeEmbedder
from jw_rag.chunker import Chunk

store = VectorStore(".rag", FakeEmbedder(64))
with PersonalNoteStore() as notes:
    raw_chunks = notes_to_rag_chunks(notes.list_all())
    store.add([Chunk(**c) for c in raw_chunks])

Flashcards (SM-2)

Implementa el algoritmo SuperMemo-2: quality 0-5, EF inicial 2.5, intervalos 1 → 6 → interval × EF.

from jw_core.study import Flashcard, FlashcardDeck, review_card

with FlashcardDeck() as deck:
    card = deck.upsert(Flashcard(front="John 3:16", back="For God so loved..."))
    # Marca recall perfecto
    review_card(deck, card.card_id, quality=5)
    # Ver lo que toca hoy
    due_today = deck.due_today()

Quality scale:

  • 5 — recall perfecto
  • 4 — correcto con titubeo
  • 3 — correcto con dificultad seria
  • 2 — incorrecto, recordó al ver
  • 1 — incorrecto, costó recordar
  • 0 — blackout total

DB: ~/.jw-agent-toolkit/cards.db (override JW_CARDS_DB).

Idiomas originales (Strong’s)

Catálogo built-in con los términos más citados en apologética JW:

Strong’sTranslit.OriginalNotas
H3068YHWHיְהוָהJehová
H430elohimאֱלֹהִיםDios / dioses / jueces
H5315nepheshנֶפֶשׁAlma (criatura viviente, no separable)
H7585sheolשְׁאוֹלSepulcro común
G86hadēsᾅδηςSepulcro / lugar de los muertos
G2962kyriosκύριοςSeñor
G5590psychēψυχήAlma mortal
from jw_core.study import get_strong_entry, register_strong_dump, StrongEntry

e = get_strong_entry("G5590")
print(e.gloss_for("es"))  # ['aliento', 'vida', 'alma (mortal)']

# Carga un dump completo
register_strong_dump([
    StrongEntry(strong_number="G26", transliteration="agapē", original="ἀγάπη",
                glosses={"en": ["love (selfless)"], "es": ["amor (desinteresado)"]}),
    # ...
])

Comparador de traducciones (ya estaba en Fase 3)

La herramienta MCP compare_translations(book_num, chapter, verse, languages=...) ya existe. Para incluir traducciones no-NWT (Reina-Valera, etc.) en una próxima iteración se puede:

  1. Añadir un cliente BibleGatewayClient o usar dumps locales.
  2. Extender compare_translations para aceptar un campo bible_code=... por idioma.

Esto entra en el Módulo 4.5 cuando se decida priorizar apologética con interlocutores que solo aceptan su Biblia tradicional.

Agente compuesto

import asyncio
from jw_agents.personal_study import personal_study

result = asyncio.run(personal_study("whole_bible_year", language="es", max_chapters=2))
print(result.metadata["today"])
for f in result.findings:
    print(f.metadata.get("source"), "-", f.summary)

Output incluye: capítulo del día, notas guardadas para ese capítulo, flashcards due hoy.

Tests

packages/jw-core/tests/test_study_module.py — 17 tests:

  • Cobertura completa de planes (1189 capítulos, sólo NT, etc.).
  • Tracker upserts + status + upcoming.
  • Notas: add, search FTS, anchor filter, export RAG.
  • SM-2: quality<3 reset, intervalos 1→6, due_iso correcto, persistencia.
  • Strong’s: lookup built-in, multiidioma, register_dump, list.
uv run pytest packages/jw-core/tests/test_study_module.py -v

Pendiente

  • Web app de revisión (Fase 15 / Módulo 10).
  • Sync end-to-end-encryption (Módulo 11).
  • Strong’s dump completo desde dominio público (Brown-Driver-Briggs / Thayer’s) — añadir como dependencia opcional.

Editar esta página en docs/guias/estudio-personal.md