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

Importar un backup de organized-app

Esta guía cubre F81.0: cómo poblar el store del scheduler a partir de un backup JSON exportado desde la web app organized-app.

Requisitos

  • uv sync --all-packages corrido al menos una vez.
  • Backup JSON exportado de organized-app (Settings → Backup → Export).
  • (opcional) JW_PRIVACY_KEY exportada o --passphrase listo.

Comando

# Dry-run: muestra qué cambiaría sin tocar el store
uv run jw scheduler import \
  --backup ~/Downloads/organized-backup.json \
  --congregation kingdom-hall-central \
  --dry-run

# Import real
uv run jw scheduler import \
  --backup ~/Downloads/organized-backup.json \
  --congregation kingdom-hall-central \
  --passphrase "correct-horse-battery-staple"

Qué pasa por dentro

  1. Lee el JSON con jw_meeting_scheduler.importer.loader.load_backup.
  2. Por cada PersonType corre map_personPersonRecord.
  3. Calcula diff vs el store (compute_person_diff):
    • added: el slug no existía.
    • updated: el slug existía con last_updated anterior.
    • kept_local: el slug existía con last_updated posterior → no se sobrescribe (CRDT respect).
    • unchanged: timestamps iguales.
  4. Si no es dry-run, upserta personas y luego por cada SchedWeek ejecuta map_schedule_weekAssignmentHistoryEntry[] y los inserta con INSERT OR IGNORE (idempotente por entry_id).

Ubicación del store

~/.jw-agent-toolkit/congregations/<congregation_id>/scheduler.db.

Override con env var JW_MEETING_SCHED_HOME.

Cifrado

display_name_ciphered se cifra con jw_core.privacy.encryption.FieldEncryptor. Llave en orden:

  1. --passphrase → derivada vía PBKDF2-HMAC-SHA256 (200k iters) con salt "jw-meeting-scheduler/v1:<congregation_id>".
  2. JW_PRIVACY_KEY (urlsafe base64 32 bytes).
  3. Sin llave → no-op + warning (cleartext en disco).

Re-import

Repetir el comando es seguro. CRDT por last_updated y INSERT OR IGNORE por entry_id garantizan que no se duplica ni se machaca ediciones manuales.

F81.1 — Edición manual del roster

# Listar
uv run jw scheduler people list --congregation kingdom-hall-central

# Editar privilegios + asignaciones elegibles
uv run jw scheduler person edit juan-perez \
    --congregation kingdom-hall-central \
    --add-privilege ms \
    --add-eligible MM_TGWTalk \
    --add-eligible MM_BibleReading

# Quitar
uv run jw scheduler person edit juan-perez \
    --congregation kingdom-hall-central \
    --remove-privilege ms \
    --remove-eligible 100   # MM_BibleReading por código numérico

# Cambiar status
uv run jw scheduler person edit juan-perez \
    --congregation kingdom-hall-central \
    --set-status irregular

# Historial de asignaciones (most recent first)
uv run jw scheduler history --person juan-perez --congregation kingdom-hall-central

Cada edición toca last_updated con datetime.now(UTC) para respetar el CRDT: un re-import posterior de organized-app con last_updated anterior no machaca la edición manual.

F81.2 — YAML de restricciones por congregación

# Crear template comentado en ~/.jw-agent-toolkit/congregations/<id>/constraints.yaml
uv run jw scheduler constraints init --congregation kingdom-hall-central

# Reemplazar el existente
uv run jw scheduler constraints init --congregation kingdom-hall-central --force

# Validar tras editar a mano
uv run jw scheduler constraints lint --congregation kingdom-hall-central

# Mostrar en tablas Rich (key fields + gap_minimum_days + weights)
uv run jw scheduler constraints show --congregation kingdom-hall-central

AssignmentConstraints (Pydantic strict):

  • congregation_id: regex ^[a-z0-9_-]{3,64}$.
  • gap_minimum_days: dict[AssignmentCode, int] — rotación mínima por código (default 60 days bible_reading, 90 speaker, 45 student parts). Hard floor en el solver F81.3.
  • max_assignments_per_month: int ∈ [1, 10] (default 3).
  • pair_experienced_with_novice: bool (default true).
  • require_brother_for_reading: bool (default true).
  • allow_overlapping_assistant_in_aula: bool (default false).
  • languages_active: list[str] (≥1, default ["en"]).
  • aulas_active: list[str] (subset de main_hall/aux_class_1/aux_class_2).
  • weights: dict[str, float] — pesos del objective CP-SAT (no negativos).

Próximos pasos (F81.3+)

  • Solver CP-SAT con jw scheduler suggest --week ... (F81.3).
  • Agente assignment_generator con @fidelity_wrap (F81.4).
  • REST endpoints /api/v1/scheduler/{suggest,confirm} (F81.5).
  • Tauri UI con override slot por slot (F81.6).

Editar esta página en docs/guias/meeting-scheduler-import.md