From c7df092eb8aa361a275957c20a4a3f08862618d3 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Sat, 28 Mar 2026 03:58:03 +0100 Subject: [PATCH] =?UTF-8?q?docs:=20a=C3=B1adir=20spec=20fn=5Foperations=20?= =?UTF-8?q?con=20entities,=20relations=20y=20types=5Fsnapshot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- docs/fn_operations.md | 256 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 docs/fn_operations.md diff --git a/docs/fn_operations.md b/docs/fn_operations.md new file mode 100644 index 00000000..ea246ac2 --- /dev/null +++ b/docs/fn_operations.md @@ -0,0 +1,256 @@ +# 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 |