0038 — Destino de los 5 verbos huérfanos del 0037 y parámetros de implementación: el conteo "10 verbos" se vuelve real¶
- Estado: Aceptada
- Fecha: 2026-06-27
- Decidido por: Product Owner humano (decisión tomada 2026-06-27). El destino de cada verbo
huérfano (
gui/enrich/restore/thesaurus/resolve) y los tres parámetros de implementación (versión de cierre de la ventana de deprecación, default debuild --scope, dónde se fija la forma del bloquematurity) son decisiones del PO. El encuadre —"el conteo de 10 verbos del 0037 era contable hasta despachar los huérfanos; este ADR lo vuelve real"— es síntesis de la IA (architect) validada por el PO. - Enmienda a: 0037 (Superficie CLI 0.10.0: 10 verbos
agents-first). Este ADR completa el 0037: el 0037 consolidó a 10 verbos los solapamientos que
catalogó la Discussion #127, pero
no nombró cinco subcomandos que la superficie real tenía por acreción (
gui,enrich,restore,thesaurus,resolve). Sin despacharlos, el "10" del 0037 era ficción contable: el CLI exponía más verbos de los que el ADR declaraba. Este ADR fija el destino de cada uno y cierra los parámetros que el 0037 dejó abiertos (criterio de cierre de la ventana de deprecación (d), default debuild --scope, y dónde vive la forma estable delmaturity(f)). No revierte el 0037 ni el contrato: el envelopeschema="1", los exit codes y el FSM del lazo se preservan (ADR 0021 §C/§D/§F). - Relacionada con: 0021 (contrato del CLI: este ADR sigue
consolidando su superficie sin tocar el envelope), 0027
/0028 (
guise rige por estos ADR y queda fuera del set de 10, como excepción explícita), 0035 (seed --resolvecomo ruta única de resolución DOI→OpenAlex; retiraresolvesuelto), 0030 (donderestorenació como verbo plano; pasa asnapshot restore), 0031 (dondethesaurusquedó como "único paso explícito"; este ADR revisa esa parte — ver Consecuencias), 0011 (thesaurus de keywords), 0025 (Enricher opt-in:enrichse absorbe enchain/build), 0029 (resolución por ambiente; el alias de entry-pointbib2graph→b2gentra a la ventana de deprecación). - No introduce IA (coherente con 0022): es reorganización de superficie y fijación de parámetros; sin modelo generativo.
- Origen: revisión post-merge del 0037 (PR #150/#153): al inventariar la superficie real contra los 10 verbos declarados, quedaron 5 subcomandos sin asignar. Decisión del PO 2026-06-27.
- Issues: #149 ("thesaurus.py no
implementa un tesauro", cerrada como invalid) — contexto del retiro de
thesaurus.
Contexto¶
El 0037 declaró una superficie 0.10.0 de 10 verbos que
mapean el ciclo de investigación, absorbiendo los seis solapamientos del
#127 (networks→build --spec,
inspect→status/read, accept/reject/filter→curate …, monitor→chain --since,
"doctor"→campos de status). Pero el 0037 razonó sobre los solapamientos catalogados, no sobre
el inventario completo del CLI. La superficie real —que el propio 0037 describe como "~20
subcomandos por acreción"— incluía cinco verbos que el ADR no nombró:
gui— lanza la GUI local (ADR 0027 /0028), gateada por #34.enrich— enriquecimiento opt-in (refs→DOI + co-citación) del Enricher, ADR 0025.restore— restaura un corpus curado (sin red) desde snapshot, ADR 0030.thesaurus— paso de normalización de keywords, marcado en 0031 como "único paso explícito (18° subcomando, transversal)".resolve— resolución DOI→OpenAlex como verbo suelto (la otra ruta,seed --resolve, ya existe por ADR 0035).
Mientras estos cinco sigan vivos como verbos planos, "10 verbos" es un número que el código
desmiente: un agente que lista --help ve más superficie de la que el contrato declara, y vuelve
el mismo problema que el 0037 quería cerrar (superficie ilegible, puertas paralelas). La pregunta de
este ADR no es de diseño nuevo, sino de higiene del contrato: ¿dónde va cada huérfano para que
el conteo del 0037 sea verdad? — y, de paso, cerrar los tres parámetros que el 0037 dejó
abiertos.
Decisión¶
Cada uno de los 5 verbos huérfanos se reabsorbe, se reparenta o se retira, de modo que la
superficie del ciclo quede en los 10 verbos del 0037 más gui como excepción explícita y
gobernada por su propio ADR. Es reorganización semántica; el contrato de salida
(envelope/exit/FSM) no cambia.
Destino de los 5 huérfanos¶
| Verbo | Destino | Por qué |
|---|---|---|
gui |
SE MANTIENE, fuera del set de 10. No entra al ciclo CLI agents-first; no se retira. | Tiene su propio gobierno: ADR 0027 (pivote GUI) y 0028 (arquitectura GUI/API), gateado por #34. Es una superficie distinta (lanzador de la GUI local), no un paso del ciclo agents-first; excluirla del conteo es honesto, no omitirla. |
enrich |
Se absorbe en build/chain (deja de ser verbo suelto). |
El enriquecimiento (refs→DOI + co-citación, ADR 0025) es parte del forrajeo (chain) y de la materialización de redes (build), no un paso aparte del ciclo. Un verbo independiente duplica superficie para lo que el paso correspondiente ya hace. |
restore |
Pasa a snapshot restore (noun-verb del grupo snapshot). |
restore es la operación inversa de snapshot: ambos son reproducibilidad de corpus. Agruparlos bajo el sustantivo snapshot (mismo patrón noun-verb que curate …/read … del 0037) hace legible que pertenecen al mismo paso EXPORT/SNAPSHOT. Conserva la capacidad que fijó el ADR 0030; solo cambia el nombre. |
thesaurus |
Se retira (verbo eliminado). | La issue #149 (cerrada invalid) constató que thesaurus.py "no implementa un tesauro". Como verbo explícito carga una promesa que el código no cumple. Revisa la parte del 0031 que lo nombró "único paso explícito" (ver Consecuencias). |
resolve |
Se retira como verbo suelto. Su ruta única es seed --resolve. |
El ADR 0035 ya definió la resolución DOI→OpenAlex como servicio compartido expuesto vía seed --resolve (ya implementado). Un resolve plano es una segunda puerta para lo mismo: exactamente el tipo de solapamiento que el 0037 retira. |
Resultado: la superficie del ciclo queda en los 10 verbos del 0037
(init, seed, chain, curate, build, read, export/snapshot, status, validate), con
snapshot restore como noun-verb dentro de snapshot, más gui como excepción explícita
gobernada por 0027/0028. El número "10" del 0037 deja de ser contable y pasa a ser verificable
contra --help.
Parámetros de implementación fijados por el PO¶
- (P1) La ventana de deprecación cierra en la versión
0.11.0(criterio por versión). Los aliases de retrocompat introducidos por el 0037 (d) —networks,accept,reject,inspect,monitor— másresolve(retirado aquí) y el alias de entry-pointbib2graph→b2g— siguen funcionando con aviso de deprecación durante 0.10.x y se eliminan en 0.11.0. Esto cierra el cabo suelto del 0037 (d), que dejó "fecha/criterio de cierre a fijar". Criterio = versión**, no fecha calendario. - (P2) El default de
build --scopeesall. Coherente con la historia one-shot del 0037 (el default corre sin curar) y con el ejemplo dematuritydel propio 0037 (scope:"all"). - (P3) La forma estable del bloque
maturity(0037 (f)) la fija el architect como apéndice endocs/API.mddurante la implementación —no en este ADR—. Aquí solo se registra dónde vive esa especificación; su schema concreto (campos, tipos) es trabajo del hito de implementación, como campo aditivo que preservaschema="1".
Invariantes preservados¶
- Envelope
schema="1", exit codes y FSM del lazo intactos (ADR 0021, 0016, 0010). Mover/retirar verbos no cambia la forma de la salida ni el mapeo de errores. - Ninguna capacidad de dominio se pierde: el enriquecimiento sigue (dentro de
chain/build, 0025), el restore sigue (snapshot restore, 0030), la resolución DOI sigue (seed --resolve, 0035). Solothesaurusse retira como verbo (su lugar como paso de normalización se resuelve en la implementación — ver Consecuencias).
Consecuencias¶
Lo que se gana
- El conteo del 0037 se vuelve verdad. Lo que
--helplista coincide con lo que el contrato declara: 10 verbos del ciclo +gui(excepción documentada). Desaparece la brecha entre el ADR y la superficie real que motivó este ADR. - Menos puertas paralelas.
enrich/resolvedejan de duplicar lo quechain/buildyseed --resolveya hacen;restorese vuelve legible como parte desnapshot. - La ventana de deprecación tiene fin cierto (P1): los aliases no quedan vivos indefinidamente; 0.11.0 es el corte.
Lo que cuesta
docs/API.mda actualizar en la implementación (trabajo delcoder, no de este ADR): retirarenrich/thesaurus/resolvedel contrato, moverrestore→snapshot restore, documentarguicomo excepción al set de 10, fijar el defaultbuild --scope=all(P2) y sumar el apéndicematurity(P3). Recomendación: revisar las menciones a estos verbos en el contrato actual y en los golden tests--json.- Tests de contrato y aliases a ajustar: sumar el aviso de deprecación de
resolvey del entry-pointbib2graph, y el corte programado para 0.11.0.
Tensiones que hay que mirar (drift honesto)
thesaurusvs ADR 0031. El 0031 declaróthesauruscomo "único paso explícito (18° subcomando, transversal)" del preprocesamiento. Retirarlo como verbo revisa esa parte del 0031 (no la revierte entera: el 0031 ya volvió normalize + dedup automáticos en la ingesta; lo que cae es el único paso que había quedado explícito). Pregunta abierta para elcoder/PO: ¿la normalización de keywords se pliega a la ingesta automática (coherente con el espíritu del 0031) o se elimina junto con el verbo? La issue #149 (invalid) sugiere que la implementación actual no era un tesauro real; conviene confirmar el destino de la funcionalidad, no solo del verbo, en el hito de implementación. Este ADR retira el verbo; el destino del paso de normalización debe quedar explícito endocs/API.md. Relacionada: ADR 0011.restorevs ADR 0030. El 0030 (AS-BUILT) nombrórestorecomo verbo plano.snapshot restorees renombre semántico, no pérdida de capacidad; aun así, es un cambio de superficie pública quedocs/API.mdy la guía de usuario deben reflejar.
Alternativas¶
- Dejar los 5 huérfanos como verbos sueltos. Rechazada: vuelve el "10" del 0037 una ficción contable —el problema exacto que el 0037 quería cerrar (superficie ilegible, puertas paralelas) reaparece por la puerta de atrás—. La higiene del contrato exige despacharlos.
- Meter
guidentro del set de 10. Rechazada:guino es un paso del ciclo agents-first; es una superficie distinta con su propio gobierno (0027/0028) y gate (#34). Forzarla al set mezcla dos contratos. Excluirla explícitamente es más honesto que disimularla en el conteo. - Retirar
enrichpor completo (no absorberlo). Rechazada: el enriquecimiento es capacidad de dominio viva (ADR 0025); lo que sobra es el verbo, no la función. Se absorbe enchain/build. - Mantener
resolvecomo verbo y deprecarseed --resolve. Rechazada: contradice el ADR 0035, que fijó la resolución como servicio compartido conseed --resolvecomo ruta de ingesta. Se conserva la ruta del 0035; se retira el verbo suelto. - Cerrar la ventana de deprecación por fecha calendario en vez de por versión. Rechazada (P1): el criterio por versión (0.11.0) es verificable, reproducible y no depende del calendario de release; es coherente con cómo el proyecto versiona (release-please).
Enmienda 2026-06-27 (append-only) — corrige el gap de P1: filter también entra a la ventana (#155)¶
Anotación append-only (no revierte nada de arriba). Surge de la implementación del grupo
curatenoun-verb (sub-issue #155): al absorberfilterencurate filterse constató que P1 omitiófilterde la lista de aliases en deprecación.
El parámetro (P1) enumeró los aliases que cierran en 0.11.0 como "networks, accept,
reject, inspect, monitor —más resolve y el entry-point bib2graph". Pero el ADR
0037 (decisión (b)) absorbió accept/reject/filter
en el grupo curate: los tres verbos planos quedan como alias deprecados. P1 listó accept y
reject pero omitió filter —un gap, no una decisión—.
Corrección: el verbo suelto filter se suma a la ventana de deprecación, con el mismo
criterio que accept/reject: sigue funcionando con aviso durante 0.10.x y se elimina en
0.11.0, como alias deprecado del nuevo curate filter. (filter y curate filter comparten la
lógica de servicio filter_corpus, fuente única; el suelto es un shim que delega.) El resto de P1 no
cambia. AS-BUILT del grupo curate en ../API.md §curate.
Enmienda 2026-06-27 (append-only) — fija el detalle de restore→snapshot restore: snapshot se vuelve grupo noun-verb y el plano → snapshot create [BREAKING] (#163)¶
Anotación append-only (gemela de las enmiendas D1 (#159) / #155; no revierte nada de arriba). Surge de la implementación del sub-issue #163. La Decisión de arriba ya fijó que
restorepasa asnapshot restore(tabla de huérfanos + Consecuencias §restorevs 0030, líneas ~85/154-157), pero no explicitó qué pasa con el verbosnapshotmismo. La implementación lo resuelve: para alojarsnapshot restore,snapshotdeja de ser verbo plano y se vuelve grupo noun-verb —y eso obliga a renombrar elsnapshotplano—.
El ADR decidió el destino de restore (→ snapshot restore) pero no el detalle del grupo.
Concretamente, al volverse snapshot un grupo:
- (a)
snapshotes ahora grupo noun-verb{create, restore}—el 3er grupo del CLI, mismo patrón queread(1°, #156/#157) ycurate(2°, #155):snapshotsin subcomando imprime la ayuda y sale exit 0; elcommanddel envelope usa la ruta completa ("snapshot create"/"snapshot restore"). - (b) El
snapshotplano →snapshot create—BREAKING, sin alias, mismo criterio que el BREAKING decurate(decisión (b) del 0037, forma-flag eliminada sin alias).snapshot createes el exsnapshotplano sin cambios de semántica: sella la foto reproducible (parquet +manifest.json, ADR 0017), NO transiciona elCycleStatey lleva el bloquematuritydel one-shot (AS-BUILT #160, coherente conbuild/read top). - (c)
snapshot restorees el exrestore(mergea+dedup, preserva la curación, transiciona aFILTEREDreusando la transición permisivafilter, ADR 0016/0030). El verbo sueltorestorequeda INTACTO como alias deprecado (shim que delega; su envelope llevacommand="restore"por backward-compat). Su retiro se agenda en #165 (junto coninspect), no en este hito. - (d) Fuente única en
service/snapshot.py(run_snapshot/run_restore, servicio neutral con relojdecided_atinyectado en la frontera, ADR 0017):snapshot create,snapshot restorey el shimrestoresuelto delegan en ella.run_snapshotlleva el bloquematurity(de #160).
Invariantes intactos: envelope schema="1", exit codes y la forma del FSM no cambian; create
NO transiciona, restore→FILTERED (igual que antes). Esta enmienda solo fija el detalle del
grupo y el BREAKING que la Decisión no explicitó. AS-BUILT en ../API.md §snapshot.
Follow-up (BAJO, #175): la implementación dejó
normalize_and_dedupduplicado enservice/snapshot.pyrespecto del helper decli/_ingest.py. Es deuda de DRY, no afecta el contrato; se trata en su propio issue, no aquí.
Enmienda 2026-06-28 (append-only) — corrige el gap de P1: enrich también entra a la ventana, y consolida los 9 aliases (#162/#165)¶
Anotación append-only (gemela de la enmienda
filterde 2026-06-27; no revierte nada de arriba). Surge de absorberenrichenchain/build(#162) y de la implementación de la capa de deprecación (#165).
El parámetro (P1) enumeró los aliases que cierran en 0.11.0 como "networks, accept,
reject, inspect, monitor —más resolve y el entry-point bib2graph". Pero la tabla de
huérfanos de la Decisión de arriba absorbe enrich en chain/build: el verbo plano queda
como alias deprecado. P1 omitió enrich —el mismo gap que ya se corrigió para filter (#155)
y que aplica también a restore (→ snapshot restore, #163)—; no es una decisión, es una omisión.
Corrección: el verbo suelto enrich se suma a la ventana de deprecación, con el mismo criterio
que accept/reject/filter/restore: sigue funcionando con aviso durante 0.10.x y se elimina
en 0.11.0, como alias que delega en la misma lógica (cli/_enrich.py::enrich_corpus, fuente única;
ver nota append-only del ADR 0025).
Lista completa de los 9 aliases deprecados (alias vivo con aviso a stderr hasta 0.11.0), tal como
los registra cli/_deprecation.py (#165):
| Alias deprecado | Forma canónica |
|---|---|
b2g accept |
b2g curate accept |
b2g reject |
b2g curate reject |
b2g filter |
b2g curate filter |
b2g inspect |
b2g read show / b2g status |
b2g monitor |
b2g chain --since |
b2g networks |
b2g build --spec |
b2g enrich |
b2g chain (+ b2g build) |
b2g restore |
b2g snapshot restore |
b2g resolve |
b2g seed --resolve |
Más el entry-point bib2graph → b2g y la opción build --corpus-scope → build --scope
(mismo corte 0.11.0). thesaurus no está en esta lista: se retira por completo (sin alias);
su capacidad vive como build --thesaurus (#164; nota append-only del ADR
0031). AS-BUILT de la capa de avisos en
../API.md §Avisos de deprecación.