Skip to content

refactor(core)!: separar acceso destructivo, mover el umbral a la aplicación y añadir CI - #19

Merged
FullFran merged 4 commits into
dev-franfrom
refactor/limites-repositorio-y-ci
Aug 8, 2026
Merged

refactor(core)!: separar acceso destructivo, mover el umbral a la aplicación y añadir CI#19
FullFran merged 4 commits into
dev-franfrom
refactor/limites-repositorio-y-ci

Conversation

@FullFran

@FullFran FullFran commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Closes #12
Closes #14
Closes #18

Resumen

Cierra las tres issues abiertas del repositorio, añade la licencia y el CI que faltaban, y sube la cobertura de 22 a 35 tests.

#12clean_all() colgaba de IRepository

Cualquier consumidor que solo necesitara leer o guardar recibía además la capacidad de borrar la base de datos entera. IAdminRepository ya existía en el repositorio pero no se estaba usando.

  • IRepository pierde clean_all().
  • Los adaptadores concretos implementan ambos puertos; los consumidores dependen del estrecho.
  • IngestService recibe admin_repository de forma opcional, y clean() falla con un mensaje claro si no se inyectó. La ingesta no necesita permisos destructivos para hacer su trabajo, así que no se le conceden por defecto.

#14 — el umbral vivía en infraestructura

SupabaseRepository guardaba el umbral como estado y lo aplicaba por encima de lo que pidiera quien llamaba, en silencio. Además RAGService nunca lo pasaba, así que SearchOptions.threshold existía sin usarse.

Ahora el umbral viaja en SearchOptions desde la capa de aplicación hasta el adaptador. El mismo repositorio puede atender una consulta estricta y otra permisiva sin reconfigurarse. El adaptador conserva solo DEFAULT_SEMANTIC_THRESHOLD como constante de último recurso, no como política.

#18 — el extra ingestion no era opcional

docling_chunker importaba docling y transformers en la cabecera del módulo, de modo que importar el paquete fallaba sin el extra instalado. Las importaciones pasan a __init__, con un ImportError que dice qué instalar.

Extra: un except: desnudo que era un fallo real

En mongo_repository, la conversión de document_id a ObjectId estaba envuelta en except: pass. Se tragaba cualquier excepción —incluida KeyboardInterrupt— y convertía un fallo de serialización en un document_id mal tipado que solo se manifestaba mucho más tarde, como un join que no casaba nada. Ahora captura InvalidId y TypeError, y avisa.

Cambios de infraestructura

Área Cambio
LICENSE MIT. Sin ella el código no se podía reutilizar legalmente
.github/workflows/ci.yml ruff + pytest en Python 3.10 y 3.12
pyproject.toml Conjunto de reglas de ruff explícito, en vez de depender del que trae por defecto
debug_db.py Eliminado: script de depuración suelto en la raíz
Lint 140 avisos → 0

El CI instala sin el extra ingestion a propósito: así verifica de forma continua que el proyecto se importa y se testea sin las dependencias pesadas, que es justo lo que pide la #18.

Plan de prueba

  • ruff check src/ tests/All checks passed!
  • ruff format --check — 37 archivos ya formateados
  • pytest -q35 pasados (antes 22)
  • 13 tests nuevos en tests/test_repository_boundaries.py, que fallan si alguien devuelve clean_all a IRepository, si el umbral deja de llegar al adaptador, o si docling vuelve a importarse en la cabecera

BREAKING CHANGE

IRepository ya no expone clean_all(): quien la necesite debe depender de IAdminRepository. SupabaseRepository ya no acepta threshold en el constructor.

Ruff se estaba ejecutando con su conjunto por defecto, que cambia entre
versiones: un CI que dependa de él se rompe solo el día que alguien
actualiza la herramienta. Se fija un select explícito (E, F, I, UP, PIE,
SIM) en pyproject.

Con esas reglas había 140 avisos. Este commit corrige los mecánicos:
anotaciones PEP 585/604, orden de imports, placeholders innecesarios e
imports sin usar.

Los prompts quedan exentos de E501 mediante per-file-ignores: son datos,
y partir una línea de prompt para que quepa en 88 columnas cambia el
texto que recibe el modelo.
…licación

Cierra tres problemas de diseño abiertos en el propio repositorio.

#12 — clean_all() colgaba de IRepository, así que cualquier consumidor
que solo necesitara leer o guardar recibía además la capacidad de borrar
la base de datos entera. Se extrae a IAdminRepository, que ya existía
pero no se estaba usando. Los adaptadores concretos implementan ambos
puertos; los consumidores dependen del estrecho. IngestService recibe el
puerto de administración de forma opcional y clean() falla con un
mensaje claro si no se le inyectó: la ingesta no necesita permisos
destructivos para hacer su trabajo.

#14 — el umbral de similitud vivía como estado del adaptador de
Supabase, que lo aplicaba en silencio por encima de lo que pidiera quien
llamaba. Pasa a viajar en SearchOptions desde la capa de aplicación, de
modo que el mismo repositorio puede atender una consulta estricta y otra
permisiva sin reconfigurarse. El adaptador conserva solo una constante
de último recurso, no una política.

#18 — docling_chunker importaba docling y transformers en la cabecera
del módulo, así que el extra opcional 'ingestion' dejaba de serlo en
cuanto algo importaba el paquete. Las importaciones pasan a __init__,
con un ImportError explicativo.

Se corrige además un 'except:' desnudo en mongo_repository que se tragaba
cualquier excepción, incluida KeyboardInterrupt, y convertía un fallo de
serialización en un document_id mal tipado que solo se manifestaba más
tarde como un join que no casaba nada.

13 tests nuevos cubren los tres límites.

BREAKING CHANGE: IRepository ya no expone clean_all(). Quien la necesite
debe depender de IAdminRepository. SupabaseRepository ya no acepta
'threshold' en el constructor.
- LICENSE (MIT): sin ella nadie podía reutilizar legalmente el código de
  un repositorio cuyo propósito declarado es enseñar el patrón.
- CI con ruff y pytest sobre Python 3.10 y 3.12. Se instala sin el extra
  'ingestion' a propósito, para que el CI verifique que el proyecto se
  importa y se testea sin las dependencias pesadas.
- Se elimina debug_db.py, un script de depuración suelto en la raíz.
- Insignias de CI y licencia en el README.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

El filtro apuntaba a 'main', pero la rama por defecto de este
repositorio es 'dev-fran', así que el workflow no llegaba a ejecutarse
en ninguna PR. El disparador de pull_request pasa a no filtrar por rama:
una PR debe validarse apunte a donde apunte.
@FullFran
FullFran merged commit a31348f into dev-fran Aug 8, 2026
2 checks passed
@FullFran
FullFran deleted the refactor/limites-repositorio-y-ci branch August 8, 2026 11:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant