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

Release F57-F66 · 13 fases en una sesión continua

Diez paquetes, 2.6k tests, 110 MCP tools

Trece fases que pasan de "jw-core multilingüe completo" a "toolkit con dos nuevos paquetes y reunión-en-vivo entregada". F57 entrega jw-meeting-media clean-room (parser HTML del WOL desde DevTools + presenter Tauri). F58 añade Bible Knowledge Graph JW-puro (607 a.E.C., NO 587/586) en jw-brain. F61 mete memoria persistente opt-in con Fernet. F62 loaders externos (Atalayas históricas con marker, Office docs con markitdown). F64 whisperX con diarización + speaker names mapping opt-in. F66 expone el brain vía MCP + fix drift. Más 7 follow-ups MVP+1 (drag-drop, monitor externo, multi-congregación, geocoords, headwords, auto-recap).

Fases

13

Tests nuevos

237+

Commits

72+

Fase 57

jw-meeting-media (clean-room)

Reunión-en-vivo, parser HTML del WOL diseñado desde DevTools

✅ Entregada 🧪 48 tests ⊜ 13 commits T1 Nueva capa + KG bíblico
Guía técnica →

Nuevo subpaquete que entrega la capa 'reunión-en-vivo' ausente: descubrimiento automático del programa semanal mwb/w + descarga de media + presenter Tauri. Implementación clean-room estricta: cero archivos .ts/.vue de M³ (AGPL-3.0) abiertos. Parser HTML diseñado inspeccionando DOM real del WOL.

Qué se entregó

  • MeetingProgramClient + parser BeautifulSoup sobre HTML semántico del WOL.
  • MediaResolver wrappea PubMediaClient para video/audio refs.
  • Downloader idempotente por sha256 con cache <root>/<lang>/<year>/<week>/.
  • MeetingStorage sqlite + Thumbnailer (Pillow + ffmpeg).
  • PresenterManager FSM con multi-session in-memory.
  • CLI: jw meeting {discover, download, list}.
  • REST: /presenter/sessions/{sid}/{state, play, pause, next, prev, stop}.
  • Tauri 2.x window 'presenter' vanilla JS con keyboard shortcuts.
  • 4 MCP tools meeting_*.

Fase 58

bible-knowledge-graph (JW-puro)

KG bíblico desde Insight + NWT, NO theographic académico

✅ Entregada 🧪 39 tests ⊜ 12 commits T1 Nueva capa + KG bíblico
Guía técnica →

Construye un knowledge graph bíblico en jw-brain desde fuentes JW puras (Estudio Perspicaz + NWT/NWTsty). Schema extendido con Period y Passage. Cronología JW estricta: 607 a.E.C. para destrucción de Jerusalén triple-anclada en código, comentarios y guía. Atribución Watch Tower visible en la guía.

Qué se entregó

  • Schema TJ extendido: Period + Passage nodes + 5 edges temporales.
  • 10 periodos JW chronology (607 a.E.C. para Jerusalén, NO 587/586).
  • BibleLoader procedural (NO LLM): import_periods + import_insight(jwpub).
  • PERSON_HEADWORDS (28) + PLACE_HEADWORDS (16) MVP iniciales.
  • Port BibleRef.from_wol_url a Python (paridad jw-core-js F56.5).
  • Fixture sintético it_mini.jwpub reusando JwpubBuilder (F50).
  • CLI: jw brain import-bible --insight <jwpub> --symbol it --meps-language.
  • Helper DuckDBBackend.query_persons_in_book (E2E: Abraham en Génesis ✓).
  • Atribución Watch Tower Bible and Tract Society of Pennsylvania.

Fase 61

letta-memory (opt-in)

Memoria persistente conversacional con Fernet opt-in

✅ Entregada 🧪 31 tests ⊜ 7 commits T2 Memoria, loaders, ASR diarizado
Guía técnica →

Módulo jw_agents.memory con MemoryStore Protocol + 3 backends (FakeMemoryStore, SqliteMemoryStore default con Fernet opt-in via JW_MEMORY_KEY, LettaMemoryStore opt-in para multi-device). Wire-up en conversation_assistant preserva compatibility (memory=None → comportamiento legacy). Patrón heredado de RevisitStore F25.

Qué se entregó

  • MemoryStore Protocol + MemoryRecord frozen dataclass.
  • FakeMemoryStore in-memory (default tests).
  • SqliteMemoryStore en ~/.jw-agent-toolkit/memory.db.
  • Fernet opt-in via env JW_MEMORY_KEY (precedente F25).
  • LettaMemoryStore opt-in con letta-client (memory-letta extra).
  • build_memory_store() factory env-driven.
  • Wire-up conversation_assistant con memory: MemoryStore | None.
  • MCP tools: memory_record, memory_recall, memory_forget_session.

Fase 62

marker-markitdown (loaders)

OCR Atalayas históricas + Office docs hermanos

✅ Entregada 🧪 9 tests ⊜ 8 commits T2 Memoria, loaders, ASR diarizado
Guía técnica →

Dos loaders nuevos en jw-rag: marker para PDFs históricos (Atalayas/Awake pre-EPUB escaneadas) y markitdown para Office docs compartidos en hermandad (.docx/.pptx/.xlsx). Ambos opt-in via extras. sha256 idempotency + detección automática de firmas JW (Watch Tower, jw.org, Atalaya).

Qué se entregó

  • pdf_marker.ingest_pdf con marker-pdf (Apache-2.0).
  • docs_markitdown.ingest_office_doc para .docx/.pptx/.xlsx (MIT).
  • Idempotencia sha256: source_id pdf:<hash8> y doc:<ext>:<hash8>.
  • JW signature regex: watch tower|jw.org|atalaya|kingdom hall|...
  • metadata.is_jw=True cuando matches signature.
  • GPU/LLM opt-in: env JW_MARKER_USE_GPU + JW_MARKER_USE_LLM.
  • Extras pyproject: [pdf-marker], [doc-markitdown], [loaders-all].
  • MCP tools ingest_pdf + ingest_office_doc; CLI jw rag ingest-pdf|ingest-office.

Fase 64

whisperX-asr (diarización)

Word-level timestamps + speaker diarization

✅ Entregada 🧪 16 tests ⊜ 6 commits T2 Memoria, loaders, ASR diarizado
Guía técnica →

Provider whisperX (BSD-4) opt-in con extras [asr-whisperx]. NO se añade a DEFAULT_ASR_CHAIN (3 GB modelos), seleccionable explícito via JW_ASR_PROVIDER=whisperx o name='whisperx'. transcribe_diarized devuelve DiarizedResult (extiende TranscriptionResult) con speaker_id por segmento + enrich_with_bible_refs opcional usando parse_reference. Requiere HF_TOKEN para pyannote diarization model.

Qué se entregó

  • DiarizedSegment(speaker_id, bible_refs) extiende TranscriptionSegment.
  • DiarizedResult(speaker_count) extiende TranscriptionResult.
  • WhisperXProvider con is_available + transcribe + transcribe_diarized.
  • BibleRef enrichment vía parse_all_references por segmento.
  • WhisperXDiarizationError si falta HF_TOKEN.
  • Cache lazy de modelos (_asr_model, _align_model, _diarize_model).
  • CLI: jw audio transcribe --diarize --bible-refs.
  • MCP tool: transcribe_audio_diarized.

Fase 66

mcp-jw-brain

Brain expuesto vía MCP + fix drift _EXPECTED_TOOLS

✅ Entregada 🧪 5 tests ⊜ 5 commits T3 MCP brain + drift fix
Guía técnica →

Exposición de operaciones del second-brain como tools MCP. F49 ya había metido los wrappers (second_brain_status/compile/query/lint/snapshot con firma brain_path: str); F66 cubre solo Task 4 (tests E2E) y Task 5 (docs). Plus fix de drift pre-existente del _EXPECTED_TOOLS (faltaban get_trace de F43 + translate_preserving_refs de F54).

Qué se entregó

  • Audit: las 5 tools second_brain_* ya estaban registradas (F49).
  • Tests E2E con DuckDB temp brain + monkeypatch sandbox del registry.
  • Fix _EXPECTED_TOOLS drift: get_trace + translate_preserving_refs.
  • Doc 'Fase 66 — Second Brain tools' en docs/referencia/jw-mcp.md.
  • Modo degraded: dict {'error': '...'} si brain no configurado.

Fase 57.14

F57.14 · drag-and-drop UI

Sidebar con cola + reorder + dropzone

✅ Entregada 🧪 17 tests ⊜ 4 commits T4 Follow-ups MVP+1
Guía técnica →

Ventana presenter Tauri con UI lateral: sidebar lista todos los items de la cola con thumbnails. Drag-drop nativo HTML5 para reordering (cursor follow inteligente: si arrastras el item activo, el cursor lo sigue; si shifteas el rango, ajusta). Dropzone para añadir archivos externos del sistema. Vanilla JS sin librerías.

Qué se entregó

  • PresenterManager: reorder(from, to), add_item(item), jump_to(index).
  • REST endpoints /presenter/sessions/{sid}/{reorder, add, jump}.
  • Sidebar HTML/CSS: queue-panel con queue-list draggable + dropzone.
  • JS handlers: dragstart/dragover/drop + cursor follow logic.
  • renderQueue() con hash para evitar rebuild del DOM en cada poll.

Fase 57.15

F57.15 · monitor externo automático

Tauri commands list_monitors + move_presenter_to_monitor

✅ Entregada ⊜ 3 commits T4 Follow-ups MVP+1
Guía técnica →

Detección de monitores externos disponibles y move-to-monitor + fullscreen vía Tauri 2.x Windows API. UI selector con dropdown (icono 🖥) en sidebar; fullscreen checkbox; click outside cierra menu. Fallback gracioso: si solo 1 monitor o detection falla, los botones quedan grises sin crash.

Qué se entregó

  • Rust: list_monitors() → Vec<MonitorInfo> con name/width/height/x/y/scale/is_primary.
  • Rust: move_presenter_to_monitor(name, fullscreen) repositions + fullscreen + focus.
  • JS: refreshMonitorList() invoca tauri.core.invoke('list_monitors').
  • UI: dropdown #monitor-menu con #monitor-list + #fullscreen-checkbox.
  • Hide selector si !window.__TAURI__ (vite dev mode).

Fase 57.16

F57.16 · multi-congregación

TOML registry + CLI subcommands + --congregation flag

✅ Entregada 🧪 22 tests ⊜ 4 commits T4 Follow-ups MVP+1
Guía técnica →

Soporte para múltiples congregaciones simultáneas. Registry ~/.jw-agent-toolkit/meetings/congregations.toml. Cada cong tiene su propio storage namespaced bajo <root>/<name>/. Resolution rules: name → lookup; sin name + 1 entry → auto; sin name + multiple → ValueError. Backwards-compat: 'default' usa legacy cache root sin migration.

Qué se entregó

  • Congregation dataclass + load_registry + save_congregation + remove.
  • resolve_congregation con 4 rules incluyendo backwards-compat.
  • CLI: jw meeting congregation {add, list, remove}.
  • Flag --congregation/-c en discover/download/list.
  • _cache_root_for(name) factorizado.
  • MCP tools meeting_list_congregations + meeting_add_congregation.
  • Param congregation opcional en meeting_* tools existentes.

Fase 58.13

F58.13 · place geocoords

16 lugares curados con lat/lon + region + modern_name + eras

✅ Entregada 🧪 7 tests ⊜ 2 commits T4 Follow-ups MVP+1
Guía técnica →

Catálogo curado análogo a period_catalog. PlaceGeoData con slug/region/modern_name/latitude/longitude/eras_active. 16 lugares principales: Jerusalem (31.78N, 35.24E, Judea, modern='Jerusalem/Al-Quds'), Babylon (32.54N, 44.42E, modern='Hillah, Iraq'), Rome, Athens, Ephesus, Bethlehem, Nazareth, etc. BibleLoader.import_insight enriquece automáticamente.

Qué se entregó

  • PlaceGeoData frozen dataclass.
  • ALL_PLACES tuple con 16 entries.
  • get_place_geodata(slug) → PlaceGeoData | None.
  • BibleLoader._process_entry place branch enriquece con geodata.

Fase 58.14

F58.14 · headwords expansion

250 personas + 150 lugares canon × ES+EN + audit CLI

✅ Entregada 🧪 27 tests ⊜ 3 commits T4 Follow-ups MVP+1
Guía técnica →

Catálogo built-in expandido a 475 person entries (~250 figuras canon × ES+EN variants) y 259 place entries (~150 lugares × ES+EN). headword_extractor para audit-only: el comando jw brain learn-headwords --insight <jwpub> extrae cabezales del JWPUB del usuario y los persiste LOCALMENTE en <brain>/extracted_headwords.json — NO se redistribuyen. Reporta % cobertura del built-in.

Qué se entregó

  • EXPANDED_PERSON_HEADWORDS frozenset 475 entries.
  • EXPANDED_PLACE_HEADWORDS frozenset 259 entries.
  • Zero overlap persona/lugar verified (amón rey vs ammon tierra).
  • classify_entry_kind: union built-in + expanded.
  • extract_headwords_from_jwpub + persist_to_brain + load_extracted_headwords.
  • CLI jw brain learn-headwords con coverage stats.
  • Catálogo legal: solo nombres factuales públicos del canon bíblico.

Fase 61.8

F61.8 · auto-recap

Cross-session memory summarization procedural

✅ Entregada 🧪 5 tests ⊜ 3 commits T4 Follow-ups MVP+1
Guía técnica →

Agente nuevo recap_previous_session NO usa LLM (decisión arquitectónica). Agrupa records de MemoryStore por session_id, ordena por timestamp desc, devuelve findings con summary corto + excerpts_by_kind en metadata. Útil al iniciar una nueva conversación: 'continuemos con la sesión X de ayer'.

Qué se entregó

  • Agente procedural recap_session.recap_previous_session().
  • Filtra sesión actual; ordena por last_timestamp desc.
  • max_excerpts_per_kind configurable.
  • MCP tool recap_previous_session.

Fase 64.7

F64.7 · speaker names mapping

Voiceprint sqlite + Fernet opt-in + cosine similarity

✅ Entregada 🧪 11 tests ⊜ 2 commits T4 Follow-ups MVP+1
Guía técnica →

Mapeo opt-in speaker_id → nombre real. VoiceprintStore sqlite con embeddings de voz (numpy float32 192-dim típico). Opt-in Fernet via JW_VOICEPRINT_KEY (precedente F61). SpeakerNameMapper con cosine similarity y similarity_threshold default 0.75. DiarizedSegment extendido con speaker_name opcional sin breaking. Integración con whisperx pyannote queda para F64.8.

Qué se entregó

  • VoiceprintStore en ~/.jw-agent-toolkit/voiceprints.db.
  • Fernet opt-in via env JW_VOICEPRINT_KEY.
  • Voiceprint(name, embedding, enrolled_at_iso).
  • SpeakerNameMapper.identify(embedding) → name | None.
  • DiarizedSegment.speaker_name backward-compatible.