Files
fn_registry/.claude/CLAUDE.md
T
egutierrez dce725e69f feat(infra): auto-commit con 8 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 14:38:16 +02:00

29 KiB

fn-registry

Registry personal de codigo reutilizable con busqueda FTS. Diseñado para composicion funcional y agentes.

Objetivos del registry (Norte) — Issues 0086 + 0087

4 metricas optimizadas por el bucle reactivo (visibles en Monitor tab del registry_dashboard):

  1. MAXIMIZAR Reg % — porcentaje de calls del agente que golpean una funcion del registry (function_id != ''). Cada bash inline o heredoc que reescribe logica baja el ratio. Target: subir cada semana.
  2. MEJORAR uso del registry por Claude — el agente debe encontrar y usar funciones existentes antes de escribir codigo. Indicadores: MCP (mcp/heredoc/fn run) sube; violations baja. Si Claude no encuentra una funcion por busqueda mediocre, mejorar description/tags/params_schema de esa funcion.
  3. ACELERAR tareas comunes via funciones nuevas — patrones inline repetidos >2 veces -> fn-constructor crea la funcion, Claude la usa el siguiente turno. Velocidad medida en pasos (turnos) por tarea. Pattern detection: tab Monitor + mcp__registry__fn_proposal action="list".
  4. PROMOVER COMPOSICIONES A PIPELINES (issue 0087) — el registry no crece inflando funciones, crece promoviendo secuencias A→B(→C) que se repiten con exito a pipelines one-shot. Hoy bank_login + bank_make_transfer (2 calls). Manana bank_transfer_oneshot (1 call). Misma capacidad, mitad de pasos. Detectado por telemetria de secuencias en call_monitor. Una funcion que hace bien UNA cosa NO necesita crecer — lo que crece es el catalogo de composiciones probadas.

Auto-discovery zero-second-lookup: cada .md debe ser autosuficiente — ## Ejemplo lanzable + ## Cuando usarla + ## Gotchas (impuras). Descubrir = lanzar, sin segunda lectura. Ver .claude/rules/function_growth_and_self_docs.md.

Cualquier decision tecnica que choque con estos objetivos esta mal priorizada. Ejemplo: un bash heredoc rapido hoy que reinventa logica = penaliza objetivos 1 y 3 manana.

Dos bases de datos SQLite:

  • registry.db (raiz) — funciones, tipos, proposals, apps, projects, analysis, vaults, pc_locations. Regenerable con fn index (excepto proposals y pc_locations).
  • operations.db (por app en apps/*/) — entities, relations, executions, assertions. Datos vivos.

Sync entre PCs: fn sync sincroniza datos no regenerables (proposals, apps, projects, analysis, vaults, pc_locations) contra registry_api en https://registry.organic-machine.com. Config: ~/.fn_pc (identidad del PC), FN_REGISTRY_API (URL con basicAuth), REGISTRY_API_TOKEN (token).

Sub-repos: cada app y cada analysis es su propio repo Gitea en dataforge/<basename> con branch master (ver ADR 0002). apps/* y analysis/* estan en el .gitignore del repo padre — el codigo de cada app vive en apps/<name>/.git/. Los slash commands /full-git-push y /full-git-pull orquestan push/pull/clone de fn_registry + todos los sub-repos + fn sync. /full-git-push auto-inicializa apps/analyses sin .git via ensure_repo_synced_bash_infra. Los vaults/ y subrepos/ NO entran en este flujo. Gotcha worktrees: si creas una app nueva dentro de un git worktree del repo padre, haz git init dentro de apps/<name>/ ANTES de limpiar el worktree, sino el codigo se pierde (apps/* gitignored). Ver .claude/rules/apps_subrepo.md.

Artefactos: termino paraguas para apps, analysis, vaults, projects y playgrounds — todo lo que NO es codigo reutilizable. Usa "artefacto" cuando una afirmacion aplica a varios tipos a la vez para no repetir la lista. Ver .claude/rules/artefactos.md y .claude/rules/playgrounds.md.

Reglas y convenciones: ver .claude/rules/INDEX.md

Slash commands: /commands lista todos los slash commands del repo agrupados por namespace (global + projects). Project commands viven en projects/<p>/.claude/commands/ y se exponen como /<project>:<cmd> via symlink. Ver .claude/rules/project_commands.md.

Migraciones SQLite obligatorias: todo cambio de schema en cualquier .db (apps, operations.db, registry.db) va en migrations/NNN_*.sql numerado. Aditivo, idempotente, aplicado al arrancar via embed.FS. Nunca borrar .db ni modificar migraciones existentes. Aplica retroactivamente. Ver .claude/rules/db_migrations.md.


Delegacion + Capability Groups (REGLA DURA — issue 0086)

Claude multiplica capacidades delegando creacion de funciones a fn-constructor y reusandolas inmediatamente. NO escribir logica reutilizable inline.

Flujo obligatorio (mismo turno)

  1. Detectar gap. Si vas a escribir >=5 lineas de logica reutilizable inline -> STOP.
  2. Spawn fn-constructor via Agent(subagent_type="fn-constructor", ...). Sin preguntar al usuario.
  3. Paralelo: si hay >1 funcion independiente -> una sola llamada al Agent tool con N tool_use blocks paralelos en mismo mensaje. NO serializar.
  4. Tag de grupo obligatorio (notebook, metabase, deploy, etc.). Ver docs/capabilities/INDEX.md.
  5. fn index + importar + invocar en mismo turno. No dejar funcion huerfana recien creada.
  6. Auto-verificar: fn doctor uses-functions + fn doctor unused si tocas >=3 funciones nuevas.

Capability groups

Cluster de >=3 funciones que comparten dominio operativo. Cada grupo tiene tag plano + pagina madre docs/capabilities/<grupo>.md con: lista de funciones, ejemplo canonico end-to-end, fronteras.

Antes de buscar funciones sueltas en una tarea de dominio conocido: lee docs/capabilities/<grupo>.md para cargar el cluster entero en un solo read. Filtro MCP: mcp__registry__fn_search query="" tag="<grupo>".

Reglas completas: .claude/rules/delegation.md + .claude/rules/capability_groups.md.

Telemetria CAPABILITY-GROWTH

Cada turno el hook UserPromptSubmit inyecta CAPABILITY-GROWTH: created_this_session=X used=Y orphan=Z. Si orphan>0 -> integra la funcion antes de cerrar turno o documenta por que.


Explorar el registry (OBLIGATORIO)

SIEMPRE consulta registry.db antes de escribir codigo, crear funciones, o responder sobre el registry. No uses grep/glob sobre archivos .go/.md — la BD es la fuente de verdad.

Usa SIEMPRE el MCP registry (regla por defecto)

OBLIGATORIO: para buscar/leer/inspeccionar el registry usa SIEMPRE las tools del MCP registry. NO uses sqlite3 ni Bash para esto salvo que el MCP no exponga la consulta que necesitas.

Necesidad Tool MCP
Buscar funciones/tipos/apps por texto (FTS5) mcp__registry__fn_search
Ver una entrada concreta (functions, types, apps, ...) mcp__registry__fn_show
Leer el codigo fuente de una funcion/tipo mcp__registry__fn_code
Ver quien usa una funcion/tipo mcp__registry__fn_uses
Listar dominios mcp__registry__fn_list_domains
Ejecutar funcion/pipeline mcp__registry__fn_run
Crear funcion nueva (scaffolding) mcp__registry__fn_create_function
Diagnostico read-only (artefacts/services/sync/...) mcp__registry__fn_doctor

Razones: menos tokens, output estructurado, FTS5 escapado bien (sin gotchas de column:"valor"), permisos pre-aprobados, no requiere cd ni paths absolutos a registry.db.

La BD contiene el codigo y la documentacion completa de cada funcion y tipo en los campos code, documentation y notes. Tambien indexados en FTS5 — buscas dentro del codigo directamente. Para leer codigo: mcp__registry__fn_code <id>.

Ejemplos MCP (usa estos, NO sqlite3)

Cada llamada MCP se registra en call_monitor (issue 0085). Cada sqlite3 registry.db "SELECT ..." queda fuera del bucle reactivo y dispara el hook PreToolUse.

# Busqueda basica por nombre/descripcion (FTS5 detras)
mcp__registry__fn_search query="slice"

# Filtros: kind, purity, domain, lang
mcp__registry__fn_search query="filter" kind="function" purity="pure" domain="core"

# Prefijo FTS5 — encuentra slice/slicing/sliced
mcp__registry__fn_search query="slic*"

# Buscar tipos
mcp__registry__fn_search query="result" entity="types"

# Apps
mcp__registry__fn_search query="kanban" entity="apps"

# Listar dominios
mcp__registry__fn_list_domains

# Ver una entrada concreta (functions, types, apps, analysis, proposals...)
mcp__registry__fn_show id="filter_slice_go_core"

# Codigo fuente de una funcion/tipo
mcp__registry__fn_code id="filter_slice_go_core"

# Quien consume una funcion (consumidores indexados via uses_functions)
mcp__registry__fn_uses id="filter_slice_go_core"

# Proposals (pending, approved, ...)
mcp__registry__fn_proposal action="list" status="pending"
mcp__registry__fn_proposal action="show" id="<proposal_id>"

# Diagnostico read-only del registry (artefacts/services/sync/uses-functions/unused/cpp-apps)
mcp__registry__fn_doctor subcommand="artefacts"
mcp__registry__fn_doctor subcommand="sync"

Escapado FTS5 (gotcha cuando pasas query libre): valores con -, ., :, espacios rompen el parser FTS5 si los expones como column:valor. El MCP escapa por defecto, pero si construyes una query con sintaxis FTS5 explicita, encierra el valor en comillas dobles:

# MAL: query="description:single-page"     -> "no such column: page"
# BIEN
mcp__registry__fn_search query='description:"single-page" OR description:"embed.FS"'
mcp__registry__fn_search query='description:"react router"'

Excepciones autorizadas para sqlite3 directo

sqlite3 registry.db SOLO es legitimo si el MCP no expone la consulta:

  • Introspeccion de schema: .schema, .tables, PRAGMA table_info(...), PRAGMA index_list(...).
  • Agregaciones: COUNT(*), GROUP BY, SUM(...), AVG(...).
  • JOINs custom entre tablas (ej. functions JOIN unit_tests ON ...) no expuestos por el MCP.

Cualquier SELECT ... FROM functions/types/apps/proposals WHERE ... plano se hace via MCP. El hook PreToolUse avisa si ve sqlite3 registry.db "SELECT ...".

Schema rapido

functions — columnas: id, name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, example, tested, tests, test_file_path, file_path, created_at, updated_at, props, emits, has_state, framework, variant, notes, documentation, code, content_hash, source_repo, source_license, source_file, params_schema

  • params_schema: JSON con semántica de inputs/outputs. Formato: {"params":[{"name":"x","desc":"..."}],"output":"..."}. Buscable via FTS5.
  • Enums: kind(function|pipeline|component) purity(pure|impure) lang(go|py|bash|ps)
  • Dominios: core, infra, finance, datascience, cybersecurity, shell, tui, pipelines, browser

types — columnas: id, name, lang, domain, version, algebraic, definition, description, tags, uses_types, file_path, created_at, updated_at, examples, notes, documentation, code, content_hash, source_repo, source_license, source_file

  • Enums: algebraic(product|sum)

unit_tests — columnas: id, function_id, name, code, file_path, lang, created_at, updated_at

  • Extraidos automaticamente por fn index desde los archivos de test
  • FK: function_idfunctions.id

pc_locations — columnas: id, entity_type, entity_id, pc_id, dir_path, status, notes, created_at, updated_at

  • Mapa de ubicaciones por PC: donde esta cada app/analysis/project/vault en cada maquina
  • entity_type: app, analysis, project, vault
  • status: active, missing, archived
  • Se puebla con fn sync, NO con fn index
  • Consultas: mcp__registry__fn_doctor subcommand="sync" (drift PC vs disco) o sqlite3 registry.db "SELECT ... GROUP BY pc_id" SOLO para agregaciones que el MCP no expone

FTS5 (columnas buscables):

  • functions_fts: id, name, description, tags, signature, domain, example, notes, documentation, code, params_schema
  • types_fts: id, name, description, tags, domain, examples, notes, documentation, code
  • unit_tests_fts: id, name, code, function_id, lang

Como invocar funciones del registry (CANONICO)

Tres patrones, uno por caso de uso. Toda invocacion del agente se loguea en projects/fn_monitoring/apps/call_monitor/operations.db para alimentar el bucle reactivo (issue 0085).

Caso de uso Patron canonico Cuando usar
Inspeccionar registro (buscar, leer codigo, ver dependencias, dominios) mcp__registry__fn_search / fn_show / fn_code / fn_uses / fn_list_domains SIEMPRE para descubrimiento. Reemplaza sqlite3 registry.db "SELECT ..." inline.
Ejecutar UNA funcion o pipeline con sus args mcp__registry__fn_run <id> [args] (preferido) o ./fn run <id> [args] (fallback CLI) Cuando hay UN id conocido a lanzar. Despacho automatico por lenguaje. Salida estructurada.
Componer ad-hoc varias funciones con logica intermedia Heredoc python/.venv/bin/python3 - <<'PYEOF' ... PYEOF IMPORTANDO funciones del registry Solo cuando hay loops/conditionals/dispatch entre N funciones. Las funciones del registry se importan, no se reescriben.

Regla decisiva: antes de cada bloque de codigo, decide caso. Si dudas entre 2 y 3, casi siempre es 2 (un MCP run con args). Si el caso 3 se repite con el mismo shape >5 veces entre sesiones, es candidato a pipeline en python/functions/pipelines/.

Antipatrones prohibidos

Patron Por que es malo Sustituir por
sqlite3 registry.db "SELECT ..." para buscar funciones/tipos Salta MCP, FTS5 gotchas, sin trazabilidad. Hook PreToolUse ya avisa. mcp__registry__fn_search
python -c "import metabase; print(dir(metabase))" o help(metabase) para descubrir helpers La fuente de verdad es el registry, no el __init__.py mcp__registry__fn_search "metabase" + mcp__registry__fn_show <id>
Heredoc que reescribe logica que ya existe como funcion del registry Reinvento + perdida de capitalizacion Buscar primero; si falta, delegar a fn-constructor (no escribir inline)
client._http.request(...) directo cuando hay wrapper en el registry Salta validacion del wrapper y telemetria Usar wrapper; si la firma no cubre el caso, proponer extension via fn proposal add
Scripts en temp/ para composiciones que se repiten Codigo se pierde y no se monitoriza Pipeline en python/functions/pipelines/ o pipeline Bash en bash/functions/pipelines/
Imports from <pkg> import * en heredoc Imposible saber que funcion del registry se uso Imports explicitos from <domain> import <name1>, <name2>

Excepciones autorizadas para sqlite3 directo (no requieren MCP): .schema, .tables, PRAGMA table_info, COUNT(*) GROUP BY, JOINs custom entre tablas que el MCP no expone.

Trazabilidad y bucle reactivo

Hook PostToolUse en .claude/settings.local.json parsea cada comando Bash + cada mcp__registry__* y escribe en la operations.db del call_monitor. Datos consumidos por:

  1. Tab "Claude usage" en registry_dashboard — top funciones, latencias, error rate, huerfanas con calls_90d=0.
  2. Fase MEJORAR del bucle reactivo — patrones inline repetidos generan proposals new_function con evidencia (session_ids + snippets). Funciones con error_rate alto y muchas llamadas suben en prioridad de bugfix.
  3. Auditoria de reglas — assertions sobre violation_count, mcp_ratio, heredoc_repetition. Si fallan critical → proposal "actualizar CLAUDE.md / prompt del agente".

Datos sensibles: solo se guarda args_hash, NUNCA valores concretos de argumentos.


Estructura

fn-registry/
  functions/{domain}/     # .go + .md por funcion Y tipo Go (core, finance, datascience, cybersecurity)
  functions/pipelines/    # Composiciones, siempre impuras
  types/{domain}/         # Solo .md de tipos (los .go viven en functions/{domain}/)
  python/functions/       # .py + .md por funcion Python
  python/types/           # .py + .md por tipo Python
  bash/functions/         # .sh + .md por funcion Bash (core, infra, io, shell)
  frontend/               # pnpm + vite + react + mantine
  frontend/functions/     # .tsx/.ts + .md (core para TS puro, ui para componentes React)
  frontend/types/         # .ts + .md por tipo
  registry/               # Paquete Go: modelos, SQLite, parser, indexer, validacion, migraciones
  fn_operations/          # Paquete Go: operations database (libreria)
  apps/                   # Apps ejecutables (TUIs, CLIs, scripts) — codigo NO reutilizable, cada una con su operations.db
  cpp/apps/               # Apps C++ standalone (sin proyecto). Ej: chart_demo, shaders_lab. Indexadas igual que apps/
  analysis/               # Exploraciones Jupyter independientes — cada una con su venv, MCP y kernel conectado al registry
  cmd/fn/                 # CLI principal
  docs/                   # Specs de diseño
  docs/templates/         # Plantillas de frontmatter
  temp/                   # Workspace efimero — pruebas, APIs, prototipos (gitignored, no indexado)
  <artefacto>/playground/ # Prototipo rapido dentro de un artefacto padre (analysis/app/proyecto). No se indexa

Build

CGO_ENABLED=1 go build -tags fts5 -o fn ./cmd/fn/
CGO_ENABLED=1 go test -tags fts5 ./...

CLI

# Registry
fn index                            # Regenera registry.db
fn search "texto"                   # FTS en functions + types
fn search -k function -p pure -d core "slice"
fn list [-d domain] [-k kind]
fn show <id>
fn add -k function                  # Template
fn check params                     # Lista funciones sin params_schema

# Doctor: diagnostico read-only del registry y artefactos
fn doctor                           # Corre todos los checks
fn doctor artefacts                 # git/venv/app.md/upstream de cada app y analysis
fn doctor services                  # apps tag 'service' + systemctl + puerto
fn doctor services-spec             # audita bloque `service:` del app.md (issue 0105)
fn doctor sync                      # drift pc_locations BD vs disco
fn doctor uses-functions            # imports reales vs uses_functions del app.md
fn doctor unused                    # funciones del registry sin consumidores
fn doctor --json                    # salida JSON (cualquier subcomando)
# Ver .claude/rules/fn_doctor.md para mapeo subcomando → funcion + acciones derivadas.

# Ejecutar funciones y pipelines (fn run)
fn run <id_or_name> [args...]       # Ejecuta por ID o nombre
fn run init_metabase --project test # Go pipeline (go run .)
fn run setup_metabase_volume        # Bash pipeline (bash <file>)
fn run metabase_setup_py_infra      # Python (python/.venv/bin/python3 <file>)
fn run my_component_ts_core         # TypeScript (frontend/node_modules/.bin/tsx <file>)
fn run filter_slice_go_core         # Go function con tests (go test -v)
fn run docker_pull_image_go_infra   # Go function sin tests (go vet)
# Despacho por lenguaje:
#   go (con main.go en dir) → go run .
#   go (con tests)          → go test -v -count=1 -tags fts5 ./pkg/
#   go (sin tests)          → go vet -tags fts5 ./pkg/
#   py                      → python/.venv/bin/python3 <file>
#   bash                    → bash <file>
#   ts                      → frontend/node_modules/.bin/tsx <file>
# Si el nombre es ambiguo, muestra los IDs para desambiguar.

# Proposals
fn proposal add --kind new_function --title "..." --created-by agent [--target-id <id>]
fn proposal list [-k kind] [-s status]
fn proposal show <id>
fn proposal update <id> --status approved [--reviewed-by lucas]

# Sync entre PCs
fn sync                             # Push+pull completo contra el servidor
fn sync status                      # Estado local: PC, API, conteos
fn sync locations                   # Mapa de ubicaciones en todos los PCs
# Config: ~/.fn_pc (identidad PC), FN_REGISTRY_API (URL), REGISTRY_API_TOKEN (token)
# URL con basicAuth: export FN_REGISTRY_API="https://user:pass@registry.organic-machine.com"

# Operations (desde directorio con operations.db)
fn ops init [path]
fn ops entity add|list|show|delete
fn ops relation add|list|show|delete
fn ops graph
fn ops snapshot list|check|update
fn ops execution add|list|show
fn ops assertion add|list|show|delete|eval [--react]
fn ops assertion result add|list

FN_REGISTRY_ROOT env var permite que fn ops acceda a registry.db desde cualquier directorio.

Uso de fn run por agentes

fn run permite ejecutar directamente funciones y pipelines del registry desde la terminal. Usar para:

  • Lanzar pipelines con sus argumentos: ./fn run init_metabase --project fn_registry
  • Correr tests de funciones Go: ./fn run filter_slice_go_core
  • Ejecutar scripts Python/Bash del registry sin montar paths manualmente
  • Verificar que funciones Go compilan correctamente (go vet)

Entornos usados automaticamente:

  • Python: python/.venv/bin/python3 (venv del proyecto)
  • TypeScript: frontend/node_modules/.bin/tsx (node del proyecto)
  • Go: go run . / go test / go vet con CGO_ENABLED=1 -tags fts5
  • Bash: bash del sistema

Añadir funciones

  1. mcp__registry__fn_search query="<nombre|desc>" para verificar que no existe algo similar
  2. Crea dos archivos segun el lenguaje:
    • Go: functions/{domain}/{name}.go + .md
    • Python: python/functions/{domain}/{name}.py + .md
    • Bash: bash/functions/{domain}/{name}.sh + .md
    • TypeScript: frontend/functions/{domain}/{name}.ts + .md
  3. Ejecuta ./fn index y verifica con ./fn show {id}

Frontmatter del .md — ver template completo en docs/templates/ o con fn add -k function.

Campos params y output (obligatorios en frontmatter):

  • params: lista de {name, desc} con descripción semántica de cada parámetro (qué representa, unidades, rango)
  • output: descripción semántica de lo que retorna la función
  • Para componentes: solo output (ya tienen props)
  • Se indexan como JSON en params_schema y son buscables via FTS5
  • fn check params lista funciones sin documentar

Reglas de integridad (el indexer las valida):

  • Pipeline → siempre impuro + uses_functions no vacio
  • Pure → returns_optional: false + error_type: ""
  • Impure → error_type obligatorio (usar error_go_core)
  • tested: true → test_file_path y tests obligatorios
  • uses_functions, uses_types, returns, error_type → IDs existentes
  • Component → framework obligatorio, returns vacio (usar emits)
  • file_path siempre relativa, IDs formato {name}_{lang}_{domain}
  • Campo returns solo para IDs del registry, NO tipos nativos de Go

Añadir tipos

Dos archivos en directorios separados:

  • Codigo Go: functions/{domain}/{name}.go (junto a las funciones, mismo paquete Go)
  • Metadata .md: types/{domain}/{name}.md con file_path apuntando a functions/{domain}/{name}.go

Los .go de tipos viven en functions/{domain}/ para que Go los compile en el mismo paquete que las funciones que los usan. Los .md se mantienen en types/{domain}/ para que el indexer los identifique como tipos.

Ver template en docs/templates/.


Analysis (exploraciones Jupyter)

Carpeta analysis/ para exploraciones de datos con Jupyter + agentes Claude. Mismo patron que apps/ — cada analisis es independiente con su propio venv, MCP y kernel.

NO es codigo reutilizable — son investigaciones ad-hoc. Si algo de un analisis resulta util, se extrae como funcion al registry.

Estructura

analysis/
  {tema}/                              # Cada analisis es autonomo
    .venv/                             # Deps propias (gitignored)
    .mcp.json                          # MCP jupyter apuntando a SU venv (gitignored)
    .claude/CLAUDE.md                  # Reglas para agentes en este analisis
    .ipython/profile_default/startup/  # Kernel startup con acceso al registry
      00_fn_registry.py                # Autocarga FN_REGISTRY_ROOT, helpers, sys.path
    notebooks/                         # Notebooks de exploracion
    data/                              # Datos locales (gitignored)
    run-jupyter-lab.sh                 # Launcher Jupyter colaborativo
    pyproject.toml                     # Deps gestionadas con uv

Crear un analisis nuevo

Un solo comando deja todo listo: carpetas, venv, paquetes, launcher, MCP, kernel startup, analysis.md con frontmatter y, si va en un proyecto, fn index final.

# Analisis suelto (analysis/{nombre}/)
fn run init_jupyter_analysis finanzas
fn run init_jupyter_analysis ml scikit-learn torch

# Analisis dentro de un proyecto (projects/{proyecto}/analysis/{nombre}/)
fn run init_jupyter_analysis --project aurgi sale_prices --desc "Comprobacion precios"
fn run init_jupyter_analysis --project fn_monitoring coverage polars --tags "monitoring,coverage"

Flags del pipeline:

  • --project <nombre> — crea el analisis dentro de projects/{nombre}/analysis/ y ejecuta fn index al final. El proyecto debe existir (projects/{nombre}/project.md).
  • --desc "..." — descripcion que se escribe en el frontmatter de analysis.md.
  • --tags "a,b,c" — tags CSV que se escriben en el frontmatter.

NUNCA uses mv para mover un analisis de analysis/ a projects/{proyecto}/analysis/ despues de crearlo. Al mover, el .venv/bin/activate queda con el path antiguo hardcodeado y el launcher falla con ERROR: jupyter-collaboration no esta instalado. Si esto pasa: rm -rf .venv && uv sync dentro del directorio nuevo. La forma correcta es siempre crear con --project desde el inicio.

El pipeline init_jupyter_analysis_bash_pipelines (v1.1.0) compone 9 funciones atomicas del registry.

Usar un analisis

# Terminal 1: lanzar Jupyter
cd analysis/{tema} && ./run-jupyter-lab.sh

# Terminal 2: abrir Claude con MCP jupyter
cd analysis/{tema} && claude

# Navegador: http://localhost:8888

Acceso al registry desde notebooks

El kernel startup (00_fn_registry.py) se ejecuta automaticamente al abrir cualquier notebook y provee:

# Helpers disponibles sin importar nada:
fn_search("slice")           # Busca funciones y tipos por nombre/descripcion
fn_query("SELECT ...")       # SQL directo sobre registry.db
fn_code("filter_list_py_core")  # Codigo fuente de una funcion

# Importar funciones Python del registry directamente:
from core import filter_list, map_list, reduce_list
from finance import sma, ema, rsi
from metabase import MetabaseClient

# Variable de entorno disponible:
import os
os.environ["FN_REGISTRY_ROOT"]  # Raiz del registry

Reglas para agentes en analysis

Cada analisis tiene su .claude/CLAUDE.md con reglas especificas:

  • Celdas inmutables: nunca modificar celdas existentes, solo anadir nuevas
  • Programacion funcional obligatoria: funciones puras, sin mutacion
  • Usar MCP jupyter para ejecutar codigo, nunca bash
  • Notebooks en notebooks/, maximo 50 celdas por notebook
  • Dependencias con uv add, nunca pip directo

Bucle reactivo: CONSTRUIR → EJECUTAR → RECOPILAR → ANALIZAR → MEJORAR

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 nucleo, aisla impuras en los bordes.
  • Registra el pipeline en operations como status: designed → implemented.
  • BD: registry.db (functions, types) → operations.db (relations, entities)

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.
  • BD: operations.db (executions, relations)

3. RECOPILAR

  • Entities se pueblan — metadata contiene los valores concretos de los campos del tipo.
  • types_snapshot garantiza que operations.db es autonomo sin registry.db.
  • El agente actualiza entity.status segun los datos recibidos.
  • BD: operations.db (entities, types_snapshot)

4. ANALIZAR

  • Agente evalua todas las assertions activas sobre las entities producidas.
  • Compara metrics de la ejecucion actual con executions historicas.
  • critical falla → entity.status = corrupted.
  • warning falla → entity.status = stale.
  • Resultados en assertion_results con value concreto para debugging.
  • BD: operations.db (assertions, assertion_results, entities.status)

5. MEJORAR

  • Si assertions fallan o metricas 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.
  • BD: registry.db (proposals)

Codigo: ExecuteAndReact() en fn_operations/operations.go ejecuta pasos 2-4. CLI: fn ops assertion eval --entity-id X --react ejecuta pasos 4-5. Las assertion rules son expresiones SQL. Campos sin prefijo se reescriben a json_extract(metadata, '$.campo').


Fuentes de verdad

Que Donde
Codigo .go / .py / .tsx
Metadata .md junto al codigo
Schema de BDs sqlite3 *.db ".schema" o docs/
Indice registry.db (fn index)
Proposals, entities, executions, assertions datos vivos en sus BDs