Files
fn_registry/docs/fn-registry-system-complete.md
egutierrez 54950af0eb docs: actualizar CLAUDE.md con apps/, proposals, assertions y bucle reactivo
Documenta la nueva estructura apps/ para aplicaciones ejecutables,
el sistema de proposals, executions/assertions, motor de evaluación SQL,
bucle reactivo (EJECUTAR→EVALUAR→REACCIONAR→PROPONER) y CLI completo
para fn ops assertion/execution y fn proposal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:14:35 +01:00

438 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` |