# Referencias cruzadas entre tablas

Todas las referencias son validadas al indexar. Una referencia a un ID inexistente es rechazada. El grafo de dependencias es siempre consistente.

---

## Mapa de referencias

| Campo origen | → | Campo 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` |

---

## Jerarquía de composición

```
types/                  → contratos de datos
  product: OHLCV, Tick, Order...
  sum:     Result, OrderResult, ParseError...

functions/
  pure/                 → transformaciones atómicas sin side effects
    filter_slice
    clamp
    map_ohlcv

  impure/               → bordes del sistema (IO, red, tiempo, estado)
    fetch_ticks
    write_csv
    get_bitcoin_price

  pipeline/             → composiciones orquestadas, siempre impuras
    tick_to_ohlcv
    build_market_feed

  component/            → UI React, pura si sin estado, impura si con estado
    DataTable
    PriceChart
    OrderForm
```

**Regla arquitectónica fundamental:**
- Las funciones **puras** nunca dependen de funciones **impuras**
- Los **pipelines** son el único lugar donde se orquesta IO
- Los **tipos** no tienen purity — son solo forma
- El agente compone puras libremente e **aísla** impuras en los bordes

---

## Grafo de dependencias

El grafo completo vive en las referencias cruzadas. Para cualquier función o pipeline el agente puede recorrer:

```
pipeline.uses_functions
  → function.uses_functions (recursivo)
  → function.uses_types
      → type.uses_types (recursivo)
  → function.returns
  → function.error_type
```

Esto permite al agente saber exactamente qué necesita para componer cualquier pipeline antes de escribir una sola línea de código.
