--- name: audit_modules_drift kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "AuditModulesDrift(root string) ([]ModuleDriftCheck, error)" description: "Detecta drift entre app.md uses_modules y CMakeLists.txt fn_module_ link calls. Para cada app C++ con CMakeLists.txt: parsea uses_modules + regex sobre target_link_libraries. Devuelve por-app: declared/linked/missing/extra/OK." tags: [audit, modules, cmake, drift, doctor, cpp] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: - gopkg.in/yaml.v3 file_path: "functions/infra/audit_modules_drift.go" params: - name: root desc: "Raiz del repositorio fn_registry. Se escanean apps/*, projects/*/apps/*." output: "Slice de ModuleDriftCheck (uno por app C++ con CMakeLists.txt). Apps sin CMakeLists son saltadas." --- ## Ejemplo ```go import "fn-registry/functions/infra" checks, err := infra.AuditModulesDrift("$HOME/fn_registry") if err != nil { panic(err) } for _, c := range checks { if !c.OK { fmt.Printf("DRIFT %s: missing=%v extra=%v\n", c.AppID, c.MissingLinks, c.ExtraLinks) } } ``` Tambien expuesto via CLI: ```bash fn doctor modules # tabla legible fn doctor modules --json # JSON para agentes ``` ## Cuando usarla Tras anadir/quitar un modulo a la app: - Verifica que el `uses_modules` del `app.md` y `target_link_libraries(... PRIVATE fn_module_*)` del CMakeLists.txt coinciden. - Tras renombrar un modulo, detecta apps que quedaron con la version antigua. - Como gate en `/full-git-push` antes de mergear cambios de modulos. ## Gotchas - Apps sin `CMakeLists.txt` (Python, bash, etc.) se saltan — el drift check no aplica. - Modulos IDs en `uses_modules` llevan sufijo `_` (ej. `data_table_cpp`); los link targets son `fn_module_` (sin sufijo). La funcion strippa el sufijo antes de comparar. - Regex acepta `fn_module_` en cualquier parte del CMakeLists — comentarios incluidos. Si un comentario referencia un modulo no usado, se reporta como `extra_links` (falso positivo aceptable).