---
name: audit_data_table_usage
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "AuditDataTableUsage(registryRoot string) ([]DataTableUsageEntry, error)"
description: "Escanea apps C++ del registry que declaran uses_modules: [data_table_cpp] y detecta anti-patrones en su uso de data_table::render: ImGui::BeginTable inline, State stack-local (no persistente), render sin BeginChild host, event sink ignorado, y enlace cmake faltante."
tags: [audit, data_table, cpp, lint, doctor, modules]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/infra/audit_data_table_usage.go"
params:
  - name: registryRoot
    desc: "Raiz absoluta del repositorio fn_registry. Se escanean apps/*, projects/*/apps/*. Solo procesa apps con lang: cpp y uses_modules incluye data_table_cpp."
output: "Slice de DataTableUsageEntry, uno por app C++ con uses_modules: [data_table_cpp]. Status: ok (sin findings warn/error), warn (hay findings), n/a (no declara data_table_cpp)."
---

## Ejemplo

```go
import "fn-registry/functions/infra"

entries, err := infra.AuditDataTableUsage("$HOME/fn_registry")
if err != nil {
    panic(err)
}
for _, e := range entries {
    if e.Status == "warn" {
        fmt.Printf("[%s] %s\n", e.AppID, e.DirPath)
        for _, f := range e.Findings {
            fmt.Printf("  %s (%s) %s:%d  %s\n", f.Kind, f.Severity, f.File, f.Line, f.Snippet)
        }
    }
}
```

Expuesto via CLI (una vez integrado en `fn doctor`):

```bash
fn doctor data-table           # tabla legible
fn doctor data-table --json    # JSON para agentes
```

## Cuando usarla

- Tras anadir `data_table_cpp` a un nuevo app, verifica que el patron canonico se sigue.
- Como gate pre-merge cuando se toca código de integración de data_table.
- Periodicamente para detectar apps que usan `ImGui::BeginTable` directamente en lugar de `data_table::render`.
- Para auditar que el event sink (`TableEvent`/`events_out`) se consume donde se necesita interactividad.

## Gotchas

- `isInsideFunctionBody` es heuristica de balance de llaves: falsos positivos posibles con lambdas o structs anonimos. Ruido bajo en codigo real.
- `no_child_host` mira 30 lineas hacia atras del `data_table::render(`. Si el BeginChild esta mas lejos (extraido en helper), se reportara falso positivo. Severidad `warn`, no `error`.
- `inline_begintable` suprime findings cuando el archivo contiene `data_table` y `modules` en su path relativo (evita ruido del modulo mismo).
- Apps cuyo directorio no existe en el PC local (sub-repos no clonados) se marcan `warn: directory_missing` en vez de analizarse. Esperado en entorno multi-PC.
- `cmake_missing_link` usa `if(TARGET fn_module_data_table)` pattern (conditional link). La funcion detecta la presencia de la string `fn_module_data_table` en CMakeLists.txt, sea en `target_link_libraries` o en el guard.
