0040 — Retirar la GUI local de la librería: el core es CLI/agente-native sobre la biblioteca viva¶
- Estado: Aceptada
- Fecha: 2026-06-28
- Decidido por: Product Owner humano (decisión tomada 2026-06-28). El retiro de la GUI local
(subcomando
b2g gui, API local FastAPI, SPAfrontend/, extra[gui], vendoreo del frontend en el wheel) y su carácter BREAKING son decisiones del PO. El encuadre —"la GUI no es el foco; el core es CLI/agente-native sobre la biblioteca viva, y el camino de adopción es la skill (ADR 0039), no una SPA local"— es síntesis de la IA (architect) validada por el PO. - Supersede a: 0027 (pivote de posicionamiento: GUI
local opt-in) y 0028 (arquitectura GUI/API/frontend +
empaquetado
[gui]). Ambos quedan como historia inmutable (no se reescriben ni se borran): este ADR revierte la dirección que fijaron, no su registro. El pivote del 0027 (GUI como 4º frontend) y la arquitectura de tres frontends del 0028 dejan de ser el TARGET del proyecto. - Enmienda a: 0038 (destino de los verbos huérfanos del
0037). El 0038 fijó que
gui"se mantiene, fuera del set de 10" como excepción meta gobernada por su propio ADR (0027/0028). Este ADR retira esa excepción:guideja de existir como verbo. El conteo del 0037 no se debilita —los 10 verbos del ciclo siguen siendo verdad—; la superficie pasa a leerse como "10 verbos del ciclo +skill(meta/distribución)", singui. - No revierte el contrato del lazo: el envelope
schema="1", los exit codes y el FSM se preservan (ADR 0021 §C/§D/§F). La capa de servicios neutralservice/—que el 0028 introdujo y elevó al contrato (envelope/errores/exit-code)— se conserva: es la fuente única que usa el CLI. Lo que se retira es el adaptador de transporte HTTP (la API) y su frontend, no la capa neutral. - Relacionada con: 0010/0021
(CLI agente-native como columna primaria: queda como la única frontera),
0037 (la superficie ES el ciclo de 10 verbos),
0039 (la skill de Claude Code es el camino de adopción
que reemplaza el rol que el 0027 daba a la GUI; tras este ADR,
skillqueda como la única excepción meta, no la "2.ª junto agui"), 0005 (matriz de extras: el extra[gui]=fastapi+uvicornse elimina, como antes[llm]/[dedup]), 0032/0033 /0034 (propuestas library-centric que colgaban de la GUI: quedan fuera del alcance de la librería; viven en el producto separado, no en bib2graph). - No introduce IA (coherente con 0022): es retiro de superficie; no toca el núcleo determinista.
- Origen: issue #190 ("retirar la GUI local (BREAKING) — fuera del foco"). Encuadre de frontera bib2graph (motor determinista) vs. producto (Zotero/Mendeley + IA-asiste). La limpieza profunda de la documentación (los ~53 marcadores AS-BUILT de la epic GUI) se trata aparte en #191.
Contexto¶
El ADR 0027 (firmado 2026-06-18) pivoteó el
posicionamiento: una GUI local "tool for thought" opt-in para el investigador semi-técnico, como
4º frontend sobre la biblioteca viva. El ADR 0028
bajó la arquitectura: una capa de servicios neutral (service/) con tres frontends de
frontera —CLI, API local FastAPI (src/bib2graph/api/) y SPA (frontend/)— más el
empaquetado del frontend en el wheel (extra [gui], force-include de gui/static/). La epic
#34 llegó a AS-BUILT G1–G5 (API + SPA +
empaquetado), gateada por la validación de un tercero sobre el caso real.
Esa validación no llegó, y el foco del proyecto se aclaró por otro lado. El posicionamiento de 0.10.0 es agents-first: la superficie CLI de 10 verbos (ADR 0037) mapea el ciclo de investigación para que un agente lo corra one-shot, y la skill de Claude Code (ADR 0039) es la puerta de adopción —"la mejor forma de usar bib2graph es pedirle a Claude que lo use"—. En ese marco, la GUI local:
- Compite por foco con el core CLI/agente-native sin un caso validado que la justifique.
- Carga superficie pesada: una API HTTP de larga vida (que tensiona el single-writer del ADR
0019), un subárbol JS (
frontend/, único Node del monorepo, con su toolchainpnpm/Vite/CI propio) y un empaquetado especial (force-includedel frontend gitignored, jobs de build de Node enci.yml/publish-*.yml). - Pertenece al otro lado de la frontera de producto. bib2graph es el motor determinista sin IA; la experiencia visual library-centric (las propuestas 0032/0033/0034 que colgaban de la GUI) es del producto separado (Zotero/Mendeley + IA-asiste), no de la librería.
La pregunta de este ADR no es de diseño: es de alcance. ¿La GUI local es parte de la librería bib2graph? La respuesta del PO es no.
Decisión¶
bib2graph retira la GUI local de la librería. Se eliminan el subcomando b2g gui, la API local
FastAPI (src/bib2graph/api/), la SPA frontend/, el extra [gui] y el vendoreo del frontend en el
wheel. El core de bib2graph es la CLI/agente-native b2g (ADR 0010/0021/0037) sobre la
biblioteca viva DuckDB. Es retiro de superficie; el contrato de salida (envelope schema="1" /
exit codes / FSM) y la capa de servicios neutral service/ no cambian.
Qué se retira (BREAKING, pre-1.0 → bump minor)¶
- El subcomando
b2g gui(cli/commands/gui.py) — sin alias de retrocompat (no es un renombre, es un retiro de capacidad). - La API local FastAPI (
src/bib2graph/api/**:app,deps,security,envelopes,routers/). - La SPA
frontend/**(subárbol JS) y el prototipoapp/**. - El extra
[gui](fastapi+uvicorn) y todo su andamiaje de empaquetado:force-includedegui/static/, el directoriosrc/bib2graph/gui/, losper-file-ignoresdeapi/y el override de mypyuvicorn.*enpyproject.toml. - El job
frontenddeci.ymly los pasos de build de Node depublish-pypi.yml/publish-testpypi.yml(el wheel pasa a ser Python puro, construible conuv buildsin Node).
Qué se conserva (NO es GUI; lo usa el CLI)¶
- La capa de servicios neutral
service/completa:envelope.py,errors.py,resolve.py,curate.py,maturity.py,snapshot.pyyreads.py. El 0028 la introdujo como contrato compartido; el CLI (read/curate/snapshot/…) depende de ella.service/reads.pyno es exclusiva de la API —el gruporead(#156/#157) la consume (list_papers/corpus_stats/get_paper/get_top)—, así que se queda. - El entry point
b2gy los 10 verbos del ciclo +skillintactos.
El conteo de superficie tras el retiro¶
La superficie 0.10.0 pasa de "10 verbos del ciclo + gui + skill" (estado del ADR 0039) a
"10 verbos del ciclo + skill (meta/distribución)". skill queda como la única excepción
meta, ya no "la 2.ª junto a gui". El conteo de 10 verbos del 0037 sigue siendo verificable
contra b2g --help.
Consecuencias¶
Lo que se gana
- Foco. El core vuelve a ser una sola frontera: la CLI/agente-native. Menos superficie que documentar, testear y mantener; el camino de adopción es la skill (0039), no una SPA local.
- Wheel Python puro. Sin Node en el build:
uv buildproduce el wheel sinpnpm, sinforce-include, sin jobs de frontend en CI/publish. Empaquetado más simple y reproducible. - Sin la tensión de concurrencia del 0019. Desaparece el server HTTP de larga vida; el modelo single-writer (1 archivo = 1 escritor) deja de estar tensionado por la API.
- Frontera de producto nítida (memoria del PO): bib2graph = motor determinista sin IA; la experiencia visual library-centric vive en el producto separado, no en la librería.
Lo que cuesta
- BREAKING para quien usaba
b2g guio instalababib2graph[gui]. Pre-1.0, se absorbe como bump minor; release-please lo corta desde el commit BREAKING (feat!/footerBREAKING CHANGE). No hay ruta de migración: la capacidad se retira. - Documentación a depurar. Este ADR limpia los docs activos mínimos para que el retiro sea
coherente (AGENTS, API §0.1/§0.2/
gui, ARCHITECTURE §4.4, PRD, ROADMAP/05-gui banner). La limpieza profunda —los ~53 marcadores AS-BUILT de la epic GUI repartidos por API/ARCHITECTURE/AGENTS— se trata en #191, no aquí. - Trabajo descartado. G1–G5 estaban AS-BUILT. Se retira código que funcionaba. El registro (Notas 07/08/10/12/16/17, ADR 0027/0028) queda como historia: el porqué de haberlo construido y el porqué de retirarlo conviven.
- Las propuestas 0032/0033/0034 quedan sin destino en la librería. Colgaban de la GUI
(library-centric, tags, flujo canónico vía
service/). No se revierten —siguen como Propuesta histórica— pero su materialización ya no es de bib2graph: es del producto separado.
Alternativas¶
- Mantener la GUI como extra opt-in dormido (código presente, sin promocionar). Descartada: el
código vivo carga mantenimiento (deps
fastapi/uvicorn, toolchain Node, CI, empaquetado especial) aunque nadie lo use, y mantiene la ambigüedad de alcance que este ADR quiere cerrar. Un extra "dormido" sigue siendo superficie pública que el contrato declara. - Mover la GUI a un repo/paquete aparte ahora. Descartada como parte de este issue: el foco es retirarla de la librería, no relanzarla. Si el producto separado la necesita, partirá de cero con su propio gobierno; la historia (0027/0028 + Notas) queda disponible como referencia. Extraer y mantener un paquete espejo hoy es trabajo que nadie pidió.
- Borrar también
service/reads.py(como sugería el inventario inicial, asumiéndola API-only). Descartada: es incorrecto —el gruporeaddel CLI la usa (list_papers/corpus_stats/get_paper/get_top)—. Borrarla romperíab2g read. Las funciones dereads.pyque solo usaba la API (get_workspace/list_rounds/get_scent/get_network/compare_rounds) quedan como código inerte; su poda es opcional y se difiere a la limpieza profunda (#191), no a este retiro. - No marcarlo BREAKING (retiro silencioso). Descartada: retira capacidad pública
(
b2g gui, extra[gui]); el contrato exige señalarlo. Pre-1.0 = minor, pero BREAKING explícito en el commit para que release-please y el CHANGELOG lo registren.