0032 — La capa de servicios es dueña del loop bibliográfico completo (extiende 0028)¶
- Estado: Propuesta
- Fecha: 2026-06-18
- Extiende a: 0028 (capa de servicios neutral +
adaptadores). 0028 subió a
service/el contrato (envelope/errores/mapeo) + 6 lecturas + curación; este ADR amplía el alcance deservice/al loop bibliográfico entero. - Relacionada con: 0010/0021 (CLI = adaptador), 0027/ 0033 (posicionamiento library-centric), 0035 (ingesta multi-puerta + resolución DOI→ID son operaciones de servicio).
- Encuadre: Nota 18 (flujo canónico paso a paso).
- Epic: GUI local #34 (iterada post-MVP).
Contexto¶
El ADR 0028 invirtió la dependencia (ports & adapters): CLI y API son adaptadores delgados de una
capa de servicios neutral src/bib2graph/service/. Pero el alcance que 0028 subió fue acotado: el
contrato (envelope schema="1", B2GError, code_for), las 6 lecturas de la SPA
(service/reads.py) y la curación (service/curate.py). El resto de la orquestación
—ingesta (run_seed/run_seed_from_bib), forrajeo (run_chain), enriquecimiento (run_enrich),
construcción de redes (run_build/run_networks), snapshot (run_snapshot)— sigue viviendo en
cli/commands/. El propio ARCHITECTURE.md lo marca: "La migración del resto de la orquestación
run_<cmd> sigue TARGET."
El reencuadre library-centric (Notas 16/17, ADR 0033) exige que la GUI ejerza el loop bibliográfico
completo (ingestar → buscar → etiquetar → curar → forrajear → proyectar), no solo leer y curar. Con
la orquestación a medio subir, cada operación nueva que la API/GUI necesita obliga a elegir entre
importar de cli/ (rompe la hoja) o reimplementar (drift) — exactamente el problema que 0028
resolvió para el contrato, pero todavía abierto para la orquestación de escritura/lazo.
Decisión¶
La capa de servicios src/bib2graph/service/ es la dueña ÚNICA del loop bibliográfico completo.
Toda operación de dominio (ingesta por ambas puertas, resolución DOI→OpenAlex ID, enriquecimiento,
dedup ya automático, curación, etiquetado, forrajeo, proyección a redes, snapshot/diff) vive en
service/ como operación neutral de transporte (sin print, sys.exit, Click ni FastAPI). CLI,
API y GUI son adaptadores finos sobre la misma operación.
-
Migración de la orquestación restante a
service/. Las funcionesrun_<cmd>decli/commands/que contienen lógica de dominio se mueven a módulos deservice/(service.ingest,service.forage,service.enrich,service.networks,service.snapshot,service.tags,service.resolve,service.reads.search_papers). El módulocli/commands/<cmd>.pyqueda como adaptador: parsea Click, resuelve workspace, llama al servicio, formatea el envelope. El patrón ya probado en G3 (run_accept/run_rejectson shims que delegan aservice.curate) se generaliza. -
Sin cambio de contrato externo. El envelope
schema="1", los exit codes (0–5) y el mapeo código→HTTP no cambian. Los payloadsdatade cada operación se preservan (los tests de contrato--jsonlos guardan). -
Migración POR DEMANDA, no big-bang. El orden lo fija el ROADMAP, guiado por lo que la iterada GUI necesita primero: ingesta de archivo + resolución DOI (Puerta B, ADR 0035),
search_papers(vista de Biblioteca),tags(ADR 0034),build/get_network(grafo). Las operaciones que hoy solo usa el CLI (validate,inspect) se difieren sin romper coherencia: el TARGET es claro, la secuencia es incremental. No se bloquea la GUI esperando un refactor total. -
Lecturas nuevas que el CLI nunca expuso (
search_papers,papers_by_tag) viven enservice/aunque no tengan subcomando CLI. La convergencia es en servicios, no en comandos (mismo principio que 0028 §Contexto). Exponerlas como subcomando CLI es opcional/diferido (sub-fork del PO, Nota 18 §2).
Consecuencias¶
- (+) Una sola verdad de orquestación de extremo a extremo. La GUI ejerce el loop completo sin que
api/importe decli/ni reimplemente lógica. Cierra el TARGET pendiente de 0028. - (+)
cli/vuelve a ser hoja de verdad (hoy es hoja para el contrato pero aún dueño de la orquestación de escritura). Todos los frontends cuelgan deservice/. - (+) La iterada GUI agrega vistas, no lógica duplicada: ingesta/búsqueda/tags/proyección son operaciones de servicio reusadas por CLI y GUI.
- (−) Refactor amplio (toca casi todos los
cli/commands/y sus tests). Mitigado por: lasrun_<cmd>ya están aisladas del I/O; el contrato externo no cambia; la migración es por demanda. - (−) Riesgo de over-engineering si se hace big-bang. Por eso la decisión 3 (por demanda): se sube lo que la GUI consume; lo demás espera evidencia de necesidad.
- (−) Doble residencia temporal: durante la migración incremental, algunas operaciones viven en
service/y otras encli/commands/. Aceptable y acotado por el ROADMAP; el shim-que-delega mantiene el contrato estable mientras tanto.