# fn-registry — Sistema de conocimiento componible para agentes autónomos Schema completo · Bucle autónomo · Optimizaciones para agentes --- ## Visión general del sistema | | fn_registry | fn_operations | |---|---|---| | **Naturaleza** | Conocimiento estático | Conocimiento dinámico | | **Pregunta** | ¿Qué existe y qué puedo hacer? | ¿Qué ha ocurrido y cómo se conecta? | | **Tablas** | `functions` · `types` · `proposals` | `entities` · `relations` · `relation_inputs` · `types_snapshot` · `executions` · `assertions` · `assertion_results` | | **Scope** | Compartido entre todos los proyectos | Local a cada proyecto — un `.db` por proyecto | | **Ontología** | Intensional — define conceptos en abstracto | Extensional — instancias concretas con valores reales | --- ## REGISTRY ### Tabla: functions Almacena funciones atómicas, pipelines y componentes React. Un pipeline es `kind: pipeline`, siempre impuro, que orquesta otras funciones. Un componente es `kind: component` con campos adicionales para su API visual. | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | Formato: `{name}_{lang}_{domain}` ej: `filter_slice_go_core` | | `name` | string | Nombre de la función o pipeline. | Obligatorio. snake_case. | | `kind` | enum | Clasificación. | `function` \| `pipeline` \| `component` | | `lang` | enum | Lenguaje. | `go` \| `python` \| `sql` \| `typescript` \| ... | | `domain` | string | Namespace de dominio. | `finance`, `dsp`, `core`, `io`... | | `version` | string | Versión semántica. | Semver: `1.0.0` | | `purity` | enum | Side effects. | `pure` \| `impure` | | `signature` | string | Firma completa. | Con parámetros y tipos de retorno. | | `description` | text | Qué hace, por qué existe, cuándo usarla. | Obligatorio. | | `tags` | []string | Etiquetas de búsqueda. | | | `uses_functions` | []string | Funciones del registry que invoca. | IDs validados. | | `uses_types` | []string | Tipos que recibe como parámetros. | IDs validados. | | `returns` | []string | Tipos que emite. | IDs validados. | | `returns_optional` | bool | Si el retorno puede estar ausente. | Siempre `false` en puras. | | `error_type` | string | Tipo de error que puede emitir. | Obligatorio en impuras. | | `imports` | []string | Dependencias externas. | | | `example` | text | Ejemplo de uso. | Preferiblemente compilable. | | `tested` | bool | Si tiene test. | `true` → `test_file_path` obligatorio. | | `tests` | []string | Lista de tests aplicados. | | | `test_file_path` | string | Ruta al archivo de test. | Relativa a raíz del registry. | | `file_path` | string | Ruta al archivo de implementación. | Relativa a raíz del registry. | | `created_at` | datetime | Fecha de creación. | ISO 8601. Automático. | | `updated_at` | datetime | Fecha de última modificación. | ISO 8601. Automático. | #### Campos adicionales — kind: component | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `props` | []PropDef | API de entrada. | `{ name, type, required, description }` | | `emits` | []string | Eventos hacia el padre. | Ej: `[onClick, onChange]`. No son `returns`. | | `has_state` | bool | Gestiona estado interno. | `true` → `purity: impure` automáticamente. | | `framework` | enum | Framework de UI. | `react`. Obligatorio en `kind: component`. | | `variant` | []string | Variantes disponibles. | Ej: `[primary, ghost, danger]` | #### Reglas de integridad — functions | Condición | Regla | |---|---| | `kind: pipeline` | `purity` siempre `impure`. `uses_functions` no puede estar vacío. | | `kind: component` | `framework` obligatorio. `returns` vacío — usar `emits`. | | `purity: pure` | `returns_optional: false`. `error_type` vacío. Una pura que devuelve opcional debe modelarse como tipo suma. | | `purity: impure` | `error_type` obligatorio. | | `tested: true` | `test_file_path` y `tests` obligatorios. | | `uses_functions[]` | Todos los IDs deben existir en `functions`. | | `uses_types[]` | Todos los IDs deben existir en `types`. | | `has_state: true` | `purity: impure` automáticamente en componentes. | --- ### Tabla: types Los tipos son el contrato entre funciones. Permiten al agente razonar sobre composabilidad sin leer implementaciones. **Tipo producto** — todos los campos siempre presentes. Modela datos y entidades. Valores posibles = N₁ × N₂ × ... × Nₙ **Tipo suma** — un caso activo a la vez. Modela estados, resultados y alternativas. Valores posibles = N₁ + N₂ + ... + Nₙ | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | Formato: `{name}_{lang}_{domain}` ej: `ohlcv_go_finance` | | `name` | string | Nombre del tipo. | PascalCase recomendado. | | `lang` | enum | Lenguaje. | Mismo enum que `functions`. | | `domain` | string | Namespace de dominio. | | | `version` | string | Versión semántica. | Semver: `1.0.0` | | `algebraic` | enum | Categoría algebraica. | `product` \| `sum` | | `definition` | text | Definición completa. | Código real. | | `description` | text | Qué modela y cuándo usarlo. | Obligatorio. | | `tags` | []string | Etiquetas de búsqueda. | | | `uses_types` | []string | Tipos que compone internamente. | IDs validados. | | `file_path` | string | Ruta al archivo. | Relativa a raíz del registry. | | `created_at` | datetime | Fecha de creación. | ISO 8601. Automático. | | `updated_at` | datetime | Fecha de última modificación. | ISO 8601. Automático. | #### Reglas de integridad — types | Condición | Regla | |---|---| | `algebraic: product` | Todos los campos siempre presentes. Modela datos. | | `algebraic: sum` | Un caso activo a la vez. Modela estados y resultados. | | `uses_types[]` | Solo IDs existentes. Sin auto-referencias. | --- ### Tabla: proposals El agente escribe propuestas de mejora al registry cuando assertions fallan o métricas son pobres. El humano revisa y aprueba. El registry crece de forma controlada. Las proposals viven en **registry** — no en operations — porque su destino es el conocimiento estático compartido entre todos los proyectos. ``` operations → detecta el problema (assertions, assertion_results) registry → propuesta de solución (proposals) — beneficia a todos los proyectos ``` | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | | | `kind` | enum | Tipo de propuesta. | `new_function` \| `new_type` \| `improve_function` \| `improve_type` \| `new_pipeline` | | `target_id` | string | ID del elemento a mejorar si aplica. | Vacío para propuestas nuevas. Referencia a `functions.id` o `types.id`. | | `title` | string | Título corto. | Obligatorio. | | `description` | text | Qué propone y por qué. | El agente explica su razonamiento. | | `evidence` | json | Datos que justifican la propuesta. | Ej: `assertion_ids` que fallaron, métricas de `executions`. | | `status` | enum | Estado de revisión. | `pending` \| `approved` \| `rejected` \| `implemented` | | `created_by` | string | Quién propone. | Ej: `agent`, `human`. | | `reviewed_by` | string | Quién revisó. | Vacío si `pending`. | | `created_at` | datetime | Fecha de la propuesta. | ISO 8601. | | `updated_at` | datetime | Fecha de última modificación. | ISO 8601. | --- ## OPERATIONS ### Tabla: entities Una entity es una instancia concreta de un tipo del registry dentro del contexto de un proyecto. ``` type_ref → lo que la entidad ES (heredado del registry) metadata → valores concretos del tipo (la instancia real) ``` | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único en el proyecto. | Formato: `{name}_{context}` ej: `ticks_btcusdt_2024` | | `name` | string | Nombre semántico. | Obligatorio. snake_case. | | `type_ref` | string | ID del tipo del registry. | Referencia a `types.id`. Obligatorio. | | `status` | enum | Estado actual. | `active` \| `stale` \| `corrupted` \| `archived` | | `description` | text | Rol en el contexto del proyecto. | | | `domain` | string | Área de dominio. | Ej: `market_data`, `auth`. | | `tags` | []string | Etiquetas de búsqueda. | | | `source` | string | Origen del dato. | Obligatorio. Ej: `binance_api`, `pipeline_output`. | | `metadata` | json | Valores concretos de los campos del tipo. | Ej: si `type_ref` es `person_go_core` con campos `name` y `dni`, aquí va `{"name":"Juan","dni":"32435"}`. Es la instancia real del tipo. | | `notes` | text | Contexto extra libre. | Para el agente o para ti. | | `created_at` | datetime | Fecha de registro. | ISO 8601. Automático. | | `updated_at` | datetime | Fecha de modificación. | ISO 8601. Automático. | #### Valores de status — entities | Valor | Significado | |---|---| | `active` | Dato en uso, actualizado y fiable. | | `stale` | Puede estar desactualizado. El agente verifica antes de usar. | | `corrupted` | Problemas de integridad. El agente no lo usa como input en ningún pipeline activo. | | `archived` | Ya no se usa. Se conserva por trazabilidad histórica. | #### Reglas de integridad — entities | Condición | Regla | |---|---| | `type_ref` | Debe existir en `fn_registry.types.id` o en `types_snapshot.id`. | | `source` | Obligatorio. Todo dato tiene un origen conocido. | | `metadata` | JSON válido. Contiene los valores de los campos definidos por el tipo del registry. | | `status: corrupted` | El agente nunca usa esta entity como input de una relation activa. | --- ### Tabla: types_snapshot Copia local de los tipos del registry en el momento de su primer uso. Hace `operations.db` completamente autónomo — no necesita `registry.db` en runtime ni en producción. | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | ID original del tipo en el registry. | | | `version` | string | Versión en el momento del snapshot. | Semver. Inmutable tras el snapshot. | | `lang` | string | Lenguaje. | | | `algebraic` | enum | `product` \| `sum`. | | | `definition` | text | Definición copiada. | Inmutable. | | `description` | text | Descripción copiada. | Inmutable. | | `snapped_at` | datetime | Cuándo se hizo el snapshot. | ISO 8601. Automático. | --- ### Tabla: relations Describe cómo una entidad se conecta o transforma en otra. El campo `name` expresa el significado humano de la conexión. `via` es opcional — vacío para relaciones puramente semánticas. ``` juan (type: person) → CONOCE A → paula (type: person) ticks → AGREGA → ohlcv_1h (via: tick_to_ohlcv_go_finance) ``` Para relaciones que consumen múltiples entidades (joins, merges) se usa `relation_inputs` en lugar de `from_entity`. | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | Formato: `{from}__to__{to}__via__{fn}` | | `name` | string | Etiqueta semántica de la relación. | Ej: `CONOCE A`, `TRANSFORMA`, `PRODUCE`, `DEPENDE DE`. Obligatorio. | | `from_entity` | string | Entidad origen para relaciones 1-a-1. | Opcional si se usa `relation_inputs`. | | `to_entity` | string | Entidad destino. | Obligatorio. | | `via` | string | Función del registry que transforma. | Opcional — vacío si relación semántica. | | `description` | text | Qué ocurre en este contexto. | | | `purity` | enum | Naturaleza de la transformación. | `pure` \| `impure`. Consistente con `via.purity` si informado. | | `direction` | enum | Dirección semántica. | `unidirectional` \| `bidirectional` \| `inverse` | | `weight` | float | Ponderación opcional. | Rango `0.0 – 1.0`. | | `status` | enum | Estado del flujo. | `designed` \| `implemented` \| `tested` \| `running` \| `deprecated` | | `started_at` | datetime | Cuándo empezó el flujo realmente. | Distinto de `created_at`. | | `ended_at` | datetime | Cuándo terminó. | Vacío si sigue activo. | | `order` | int | Posición en secuencia. | Opcional. | | `tags` | []string | Etiquetas. | | | `notes` | text | Observaciones y contexto histórico. | El agente lee esto. | | `created_at` | datetime | Fecha de documentación. | ISO 8601. Automático. | | `updated_at` | datetime | Fecha de modificación. | ISO 8601. Automático. | #### Valores de direction | Valor | Significado | |---|---| | `unidirectional` | A → B. Un solo sentido. Valor por defecto. | | `bidirectional` | A ↔ B. Simétrica. Ej: `CONOCE A`. | | `inverse` | Documentada de B a A, lectura natural A a B. Para linaje inverso. | #### Valores de status — relations | Valor | Significado | |---|---| | `designed` | Planificado. En arquitectura pero sin código. | | `implemented` | Código escrito. No verificado aún. | | `tested` | Verificado. Los datos fluyen correctamente. | | `running` | Activo en producción. | | `deprecated` | Ya no se usa. Se mantiene por trazabilidad. | #### Reglas de integridad — relations | Condición | Regla | |---|---| | `name` | Obligatorio. | | `from_entity` o `relation_inputs` | Al menos uno presente. Una relation sin origen es inválida. | | `via` | Si informado, debe existir en `fn_registry.functions.id`. | | `weight` | Si informado, rango `0.0 – 1.0`. | | `started_at` / `ended_at` | Si ambos informados, `started_at` anterior a `ended_at`. | | **Sin ciclos causales** | El CLI valida ciclos solo en relations con `via` informado. Las relaciones semánticas sin `via` pueden ser bidireccionales libremente. | --- ### Tabla: relation_inputs Para relaciones que consumen múltiples entidades simultáneamente — joins, merges, agregaciones multi-fuente. Cuando se usa esta tabla, `from_entity` en `relations` se deja vacío. ``` join(ticks_btcusdt, metadata_binance) → ENRIQUECE → ohlcv_enriquecido ↑ role: "base" ↑ role: "lookup" ``` | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | Automático. | | `relation_id` | string | Relation a la que pertenece. | Referencia a `relations.id`. Obligatorio. | | `entity_id` | string | Entidad que actúa como input. | Referencia a `entities.id`. Obligatorio. | | `role` | string | Rol semántico en la relación. | Ej: `base`, `lookup`, `filter`, `left`, `right`. Obligatorio. | | `order` | int | Orden si la relación es sensible al orden. | Opcional. | #### Reglas de integridad — relation_inputs | Condición | Regla | |---|---| | `role` | Obligatorio. Sin rol el agente no puede razonar sobre cómo se usa el input. | | Mínimo 2 inputs | Si se usa esta tabla, al menos 2 entradas. Si hay una sola usar `from_entity`. | --- ### Tabla: executions Registra cada ejecución de un pipeline. Es la memoria de comportamiento del sistema — el agente consulta `executions` para detectar degradación, comparar rendimiento histórico y justificar `proposals`. | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | Automático. | | `pipeline_id` | string | Función/pipeline ejecutado. | Referencia a `functions.id` en registry. | | `relation_id` | string | Relation que disparó la ejecución. | Referencia a `relations.id`. | | `status` | enum | Resultado. | `success` \| `failure` \| `partial` | | `started_at` | datetime | Inicio real de la ejecución. | ISO 8601. | | `ended_at` | datetime | Fin de la ejecución. | ISO 8601. | | `duration_ms` | int | Duración en milisegundos. | | | `records_in` | int | Registros de entrada procesados. | | | `records_out` | int | Registros de salida producidos. | | | `error` | text | Mensaje de error si falló. | Vacío si `success`. | | `metrics` | json | Métricas clave del output. | Ej: `{"mean_close":42000,"nulls":0}` | | `created_at` | datetime | Fecha de registro. | ISO 8601. Automático. | --- ### Tabla: assertions Reglas de calidad formales sobre entities. Condiciones computables que el agente evalúa automáticamente tras cada ejecución. No texto libre — condiciones que devuelven `pass` o `fail`. | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | Ej: `ohlcv_close_positive` | | `entity_id` | string | Entity sobre la que aplica. | Referencia a `entities.id`. | | `name` | string | Nombre legible. | Ej: `close debe ser positivo` | | `kind` | enum | Tipo de assertion. | `range` \| `null` \| `statistical` \| `consistency` \| `freshness` | | `rule` | text | Condición formal evaluable. | SQL o expresión. Ej: `close > 0 AND close < open * 3` | | `severity` | enum | Qué ocurre si falla. | `critical` \| `warning` \| `info` | | `description` | text | Por qué existe esta regla. | Conocimiento de dominio que la justifica. | | `active` | bool | Si se evalúa en cada ejecución. | Permite desactivar sin borrar. | | `created_at` | datetime | Fecha de creación. | ISO 8601. | #### Tipos de assertion | Kind | Descripción y ejemplo | |---|---| | `range` | El valor debe estar dentro de un rango. Ej: `close BETWEEN 0 AND 1000000` | | `null` | El campo no puede ser nulo. Ej: `open IS NOT NULL` | | `statistical` | No debe desviarse más de N desviaciones estándar. Ej: `zscore(close) < 3` | | `consistency` | Relación entre campos del mismo registro. Ej: `low <= close AND close <= high` | | `freshness` | Los datos no pueden ser más antiguos de X. Ej: `max(ts) > now() - 1h` | #### Lógica de severidad | Severidad | Acción automática | |---|---| | `critical` | `entity.status = corrupted`. El agente no usa esta entity. Escribe en `proposals`. | | `warning` | `entity.status = stale`. El agente la usa con precaución y lo documenta. | | `info` | No cambia `status`. Solo registra en `assertion_results` para análisis histórico. | --- ### Tabla: assertion_results Historial de cada evaluación de assertion. Permite al agente detectar tendencias — "esta assertion falla el 20% de las veces en ejecuciones nocturnas". | Campo | Tipo | Descripción | Notas / Restricciones | |---|---|---|---| | `id` | string | Identificador único. | | | `assertion_id` | string | Assertion evaluada. | Referencia a `assertions.id`. | | `execution_id` | string | Ejecución que disparó la evaluación. | Referencia a `executions.id`. | | `status` | enum | Resultado. | `pass` \| `fail` \| `skip` | | `value` | json | Valor concreto evaluado. | Lo que tenía el dato cuando falló. | | `message` | text | Descripción del fallo. | Generado automáticamente. | | `evaluated_at` | datetime | Cuándo se evaluó. | ISO 8601. | --- ## El bucle autónomo El sistema completo habilita un ciclo de mejora continua donde el agente construye, ejecuta, analiza y propone mejoras sin intervención humana salvo en la aprobación final. ### 1. CONSTRUIR - Agente consulta registry → recupera funciones testeadas por FTS sobre `name`, `description`, `tags`. - Razona sobre composabilidad comparando `returns` con `uses_types`. - Prioriza funciones puras para el núcleo, aísla impuras en los bordes. - Registra el pipeline en operations como `status: designed → implemented`. ### 2. EJECUTAR - Pipeline corre → inserta registro en `executions` con `duration_ms`, `records_in`, `records_out`, `metrics`. - `operations.relations.status = running`. - Si falla → `execution.status = failure`, `error` capturado. ### 3. RECOPILAR - Entities se pueblan — `metadata` contiene los valores concretos de los campos del tipo. - `types_snapshot` garantiza que `operations.db` es autónomo sin `registry.db`. - El agente actualiza `entity.status` según los datos recibidos. ### 4. ANALIZAR - Agente evalúa todas las `assertions` activas sobre las entities producidas. - Compara `metrics` de la ejecución actual con `executions` históricas. - `critical` falla → `entity.status = corrupted`. - `warning` falla → `entity.status = stale`. - Resultados en `assertion_results` con `value` concreto para debugging. ### 5. MEJORAR - Si assertions fallan o métricas degradan → agente escribe en `proposals`. - `proposals.evidence` referencia los `assertion_ids` y `execution_ids` que lo justifican. - El humano revisa `proposals.status: pending → approved → implemented`. - El registry crece de forma controlada y trazable. ### 6. REPEAT - Con el registry mejorado el agente construye mejor en la siguiente iteración. - Cada ciclo acumula conocimiento — funciones más robustas, tipos más precisos, assertions más finas. - El sistema mejora continuamente sin resetear el contexto acumulado. --- ## Optimizaciones para el agente | Área | Mejora | Beneficio para el agente | |---|---|---| | Búsqueda en registry | Índice FTS5 sobre `name + description + tags + signature` | Recuperación en <5ms sin embeddings | | `types_snapshot` | Copiar tipo completo al primer uso | `operations.db` completamente autónomo sin `registry.db` | | Ciclos en grafo | Validar solo relations con `via` informado (causales) | Relaciones semánticas bidireccionales permitidas | | `assertions` | Evaluar automáticamente tras cada `execution` | Agente detecta degradación sin intervención humana | | `metadata` en entities | Almacenar instancia real del tipo como JSON | Agente lee valores sin acceder a ficheros externos | | `proposals.evidence` | Referenciar `assertion_ids` y `execution_ids` concretos | Trazabilidad completa del razonamiento del agente | | WAL mode SQLite | Activado por defecto en plantilla | Lectura simultánea mientras el agente escribe | | `version` en `functions` y `types` | Semver explícito | Detección automática de contratos rotos | | `direction` en relations | `unidirectional / bidirectional / inverse` | Agente recorre linaje hacia adelante y hacia atrás | | `proposals` en registry | No en operations | Un solo punto de revisión humana para todos los proyectos | --- ## Referencias cruzadas completas | Campo origen | → | Destino | |---|---|---| | `functions.uses_functions[]` | → | `functions.id` | | `functions.uses_types[]` | → | `types.id` | | `functions.returns[]` | → | `types.id` | | `functions.error_type` | → | `types.id` | | `types.uses_types[]` | → | `types.id` | | `proposals.target_id` | → | `functions.id` o `types.id` (opcional) | | `entities.type_ref` | → | `fn_registry → types.id` / `types_snapshot.id` | | `relations.from_entity` | → | `entities.id` (opcional) | | `relations.to_entity` | → | `entities.id` | | `relations.via` | → | `fn_registry → functions.id` (opcional) | | `relation_inputs.relation_id` | → | `relations.id` | | `relation_inputs.entity_id` | → | `entities.id` | | `executions.pipeline_id` | → | `fn_registry → functions.id` | | `executions.relation_id` | → | `relations.id` | | `assertions.entity_id` | → | `entities.id` | | `assertion_results.assertion_id` | → | `assertions.id` | | `assertion_results.execution_id` | → | `executions.id` |