Files
fn_registry/docs/fn_operations.md
egutierrez c7df092eb8 docs: añadir spec fn_operations con entities, relations y types_snapshot
Schema de inteligencia operacional para proyectos. Define tablas entities,
relations, relation_inputs y types_snapshot con reglas de integridad,
referencias cruzadas al registry central y ejemplos de uso.
2026-03-28 03:58:03 +01:00

257 lines
13 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_operations — Schema de inteligencia operacional
Base de datos local por proyecto. Cada proyecto tiene su propio archivo `.db` independiente.
Referencia IDs del registry central (`fn_registry`) pero no los duplica — solo apunta a ellos.
---
## Propósito
El registry almacena **lo que sabes hacer**.
fn_operations almacena **lo que has hecho y cómo fluye** en un proyecto concreto.
| | fn_registry | fn_operations |
|---|---|---|
| **Naturaleza** | Conocimiento estático | Conocimiento dinámico |
| **Contenido** | Lo que sabes hacer | Lo que has hecho y cómo fluye |
| **Scope** | Compartida entre todos los proyectos | Local a cada proyecto — un `.db` por proyecto |
| **Tablas** | `functions`, `types` | `entities`, `relations`, `relation_inputs` |
| **Cuándo cambia** | Al añadir código al registry | En cada proyecto activo |
---
## Estructura de directorios
```
fn-registry/
fn_operations/
fn_operations.md ← este archivo
project_template/
operations.db ← plantilla vacía con schema y WAL mode aplicados
migrations/
001_init.sql ← script de creación de tablas
```
---
## Tabla: entities
Una entity es una instancia concreta de un tipo del registry dentro del contexto de un proyecto.
No es el tipo en abstracto — es el dato real que fluye: `ticks_btcusdt_2024`, `ohlcv_1h_binance`, `user_session_web`.
El tipo del registry (`type_ref`) aporta conocimiento heredado — campos, estructura, semántica algebraica.
La entity aporta conocimiento contextual — qué rol juega aquí, de dónde viene, qué propiedades específicas tiene.
```
type_ref → lo que la entidad ES (heredado del registry)
metadata → lo que la entidad TIENE (específico de este contexto)
```
| Campo | Tipo | Descripción | Notas / Restricciones |
|---|---|---|---|
| `id` | string | Identificador único de la entidad en el proyecto. | Formato: `{name}_{context}` ej: `ticks_btcusdt_2024`. Único dentro del proyecto. |
| `name` | string | Nombre semántico de la entidad. | Descriptivo y específico al dominio del proyecto. Obligatorio. |
| `type_ref` | string | ID del tipo del registry que modela esta entidad. | Referencia a `types.id` en `fn_registry`. Obligatorio. |
| `status` | enum | Estado actual de la entidad. | `active` \| `stale` \| `corrupted` \| `archived` |
| `description` | text | Qué representa esta entidad en el contexto del proyecto. | No qué es el tipo en abstracto, sino qué rol juega aquí. |
| `domain` | string | Área de dominio dentro del proyecto. | Ej: `market_data`, `auth`, `reporting`. |
| `tags` | []string | Etiquetas libres para búsqueda y agrupación. | |
| `source` | string | Origen del dato. | Obligatorio. Ej: `binance_api`, `csv_upload`, `user_input`, `pipeline_output`. |
| `metadata` | json | Propiedades específicas del contexto no capturadas por el tipo. | Valores concretos de los campos del tipo. Ej: `{"pair":"BTCUSDT","exchange":"binance"}`. |
| `notes` | text | Contexto extra libre sobre la entidad. | Para el agente o para ti. Decisiones, observaciones, advertencias, historial informal. |
| `created_at` | datetime | Fecha de registro de la entidad. | ISO 8601. Generado automáticamente. |
| `updated_at` | datetime | Fecha de última modificación. | ISO 8601. Actualizado automáticamente. |
### Valores de status — entities
| Valor | Significado |
|---|---|
| `active` | Dato en uso, actualizado y fiable. |
| `stale` | Existe pero puede estar desactualizado. El agente debe verificar antes de usar. |
| `corrupted` | Se sabe que tiene problemas de integridad. No usar en pipelines. |
| `archived` | Ya no se usa activamente. Se conserva por trazabilidad histórica. |
### Reglas de integridad — entities
| Condición | Regla |
|---|---|
| `type_ref` | Debe existir en `fn_registry.types.id`. Sin referencias huérfanas. |
| `id` | Único dentro del proyecto. Formato `{name}_{context}`. |
| `source` | Obligatorio. Todo dato tiene un origen conocido. |
| `name` | Obligatorio. Sin espacios, snake_case. |
| `metadata` | JSON válido. Debe contener los valores de los campos definidos por el tipo del registry. |
| `status: corrupted` | El agente nunca debe usar esta entidad como input de una relation activa. |
---
## Tabla: relations
Una relation describe cómo una entidad se conecta o transforma en otra. Puede documentar una
transformación técnica a través de una función del registry, o una relación puramente semántica
sin función asociada. El campo `name` expresa el significado humano de la conexión.
```
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, agregaciones multi-fuente),
se usa la tabla `relation_inputs` en lugar de `from_entity`. Ver sección correspondiente.
| Campo | Tipo | Descripción | Notas / Restricciones |
|---|---|---|---|
| `id` | string | Identificador único de la relación. | Formato: `{from}__to__{to}__via__{fn}`. Legible sin joins. |
| `name` | string | Etiqueta semántica de la relación. | El verbo o concepto que describe la conexión. Ej: `CONOCE A`, `TRANSFORMA`, `PRODUCE`, `DEPENDE DE`. Obligatorio. |
| `from_entity` | string | ID de la entidad origen para relaciones simples (1-a-1). | Referencia a `entities.id`. Opcional si se usa `relation_inputs`. |
| `to_entity` | string | ID de la entidad destino. | Referencia a `entities.id`. Obligatorio. |
| `via` | string | ID de la función o pipeline del registry que realiza la transformación. | Referencia a `functions.id` en `fn_registry`. Opcional — vacío si la relación es puramente semántica. |
| `description` | text | Qué ocurre en esta conexión en el contexto del proyecto. | No qué hace la función en abstracto, sino qué significa aquí. |
| `purity` | enum | Naturaleza de la transformación. | `pure` \| `impure`. Si `via` está informado, debe ser consistente con `via.purity` en el registry. |
| `direction` | enum | Dirección semántica de la relación. | `unidirectional` \| `bidirectional` \| `inverse`. Ver valores abajo. |
| `weight` | float | Ponderación opcional de la relación. | Rango `0.0 1.0`. Permite queryar "relaciones con peso > 0.8". Opcional. |
| `status` | enum | Estado del flujo. | `designed` \| `implemented` \| `tested` \| `running` \| `deprecated` |
| `started_at` | datetime | Cuándo empezó el flujo realmente. | ISO 8601. Distinto de `created_at` — ese es cuándo lo documentaste. |
| `ended_at` | datetime | Cuándo terminó o dejó de ejecutarse el flujo. | ISO 8601. Vacío si sigue activo. |
| `order` | int | Posición en el pipeline si forma parte de una secuencia ordenada. | Opcional. Permite reconstruir el grafo en orden de ejecución. |
| `tags` | []string | Etiquetas libres. | |
| `notes` | text | Observaciones, decisiones de diseño, problemas conocidos. | Libre. El agente lee esto para entender contexto histórico del flujo. |
| `created_at` | datetime | Fecha de registro de la relación. | ISO 8601. Generado automáticamente. |
| `updated_at` | datetime | Fecha de última modificación. | ISO 8601. Actualizado automáticamente. |
### Valores de direction
| Valor | Significado |
|---|---|
| `unidirectional` | A → B. La relación fluye en un solo sentido. Valor por defecto. |
| `bidirectional` | A ↔ B. La relación es simétrica — vale en ambos sentidos. Ej: `CONOCE A`. |
| `inverse` | La relación se documenta de B a A pero su lectura natural es de A a B. Útil para linaje inverso. |
### Valores de status — relations
| Valor | Significado |
|---|---|
| `designed` | Flujo planificado. Existe en el grafo de arquitectura pero no hay código todavía. |
| `implemented` | Código escrito. No verificado en este contexto de proyecto aún. |
| `tested` | Verificado en este proyecto. Los datos fluyen correctamente. |
| `running` | Activo en producción o en uso continuo. |
| `deprecated` | Ya no se usa. Se mantiene por trazabilidad histórica. |
### Reglas de integridad — relations
| Condición | Regla |
|---|---|
| `name` | Obligatorio. Describe el verbo semántico de la relación. |
| `from_entity` | Si informado, debe existir en `entities.id`. Vacío si se usa `relation_inputs`. |
| `from_entity` o `relation_inputs` | Al menos uno de los dos debe estar presente. Una relation sin origen es inválida. |
| `to_entity` | Debe existir en `entities.id`. Obligatorio. |
| `via` | Si informado, debe existir en `fn_registry.functions.id`. |
| `purity` | Si `via` está informado, debe ser consistente con `via.purity` en el registry. |
| `weight` | Si informado, debe estar en el rango `0.0 1.0`. |
| `from_entity != to_entity` | Una entidad no puede relacionarse consigo misma. |
| `started_at` / `ended_at` | Si ambos informados, `started_at` debe ser anterior a `ended_at`. |
| `id` | Único dentro del proyecto. |
| **Sin ciclos** | El CLI valida al insertar que la nueva relation no crea un ciclo en el grafo. Si lo crea, la inserción se rechaza. SQLite no detecta ciclos — esta validación ocurre en la capa de aplicación. |
---
## Tabla: relation_inputs
Tabla intermedia para relaciones que consumen **múltiples entidades simultáneamente** — joins,
merges, agregaciones multi-fuente. Cuando una relation usa `relation_inputs`, el campo
`from_entity` en `relations` se deja vacío.
```
join(ticks_btcusdt, metadata_binance) → ENRIQUECE → ohlcv_enriquecido
↑ input role: "base" ↑ to_entity
↑ input role: "lookup"
```
| Campo | Tipo | Descripción | Notas / Restricciones |
|---|---|---|---|
| `id` | string | Identificador único del input. | Generado automáticamente. |
| `relation_id` | string | ID de la relation a la que pertenece este input. | Referencia a `relations.id`. Obligatorio. |
| `entity_id` | string | ID de la entidad que actúa como input. | Referencia a `entities.id`. Obligatorio. |
| `role` | string | Rol semántico de este input en la relación. | Ej: `base`, `lookup`, `filter`, `left`, `right`. Obligatorio. Permite al agente entender cómo se usa cada input. |
| `order` | int | Orden del input si la relación es sensible al orden. | Opcional. Ej: en un join `left`/`right` el orden importa. |
### Reglas de integridad — relation_inputs
| Condición | Regla |
|---|---|
| `relation_id` | Debe existir en `relations.id`. |
| `entity_id` | Debe existir en `entities.id`. |
| `role` | Obligatorio. Sin rol el agente no puede razonar sobre cómo se usa el input. |
| Mínimo 2 inputs | Una relation con `relation_inputs` debe tener al menos 2 entradas. Si solo hay una, usar `from_entity` en su lugar. |
---
## Referencias cruzadas completas
| Campo origen | → | Destino |
|---|---|---|
| `entities.type_ref` | → | `fn_registry → types.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` |
---
## Ejemplo — pipeline de market data
### Entities
| id | type_ref | status | source | metadata |
|---|---|---|---|---|
| `ticks_btcusdt_2024` | `tick_go_finance` | `active` | `binance_api` | `{"pair":"BTCUSDT","exchange":"binance"}` |
| `metadata_binance` | `exchange_meta_go_finance` | `active` | `binance_api` | `{"version":"v3"}` |
| `ohlcv_1h_btcusdt` | `ohlcv_go_finance` | `active` | `pipeline_output` | `{"interval":"1h","pair":"BTCUSDT"}` |
| `sma_20_btcusdt` | `float64_slice_go_core` | `active` | `pipeline_output` | `{"period":20,"field":"close"}` |
### Relations simples
| name | from_entity | to_entity | via | direction | status | weight |
|---|---|---|---|---|---|---|
| `CALCULA` | `ohlcv_1h_btcusdt` | `sma_20_btcusdt` | `sma_go_finance` | `unidirectional` | `tested` | 1.0 |
### Relation con múltiples inputs (relation_inputs)
**Relation:** `id: ticks_y_meta__to__ohlcv__via__enrich`, `name: ENRIQUECE`, `to_entity: ohlcv_1h_btcusdt`
| relation_id | entity_id | role | order |
|---|---|---|---|
| `ticks_y_meta__to__ohlcv__via__enrich` | `ticks_btcusdt_2024` | `base` | 1 |
| `ticks_y_meta__to__ohlcv__via__enrich` | `metadata_binance` | `lookup` | 2 |
### Grafo resultante
```
[ticks_btcusdt_2024] ──┐
├─ ENRIQUECE (impure · running) ──→ [ohlcv_1h_btcusdt]
[metadata_binance] ──┘ ↓
CALCULA (pure · tested)
[sma_20_btcusdt]
```
---
## Ejemplo — relaciones semánticas puras (sin via)
```
[juan] (type: person) → CONOCE A (bidirectional, weight: 0.9) → [paula]
[servicio_auth] → DEPENDE DE (unidirectional, weight: 1.0) → [bbdd_usuarios]
[modelo_riesgo] → ALIMENTA (unidirectional, weight: 0.7) → [dashboard_trading]
```
---
## Escalabilidad
| Fase | BBDD | Cuándo migrar |
|---|---|---|
| Inicial | SQLite + WAL mode | Proyectos personales, un agente escribiendo |
| Crecimiento | PostgreSQL | Múltiples agentes escribiendo concurrentemente |
| Analítico | ClickHouse | Millones de operaciones, dashboards de uso |