--- id: "0107a" title: "fn doctor modules — detectar drift uses_modules vs uses_functions y version skew" status: pendiente type: feature domain: - meta - cpp-stack - tooling scope: registry priority: alta depends: [] blocks: - "0107b" related: - "0107" created: 2026-05-17 updated: 2026-05-17 tags: [modules, fn-doctor, drift, audit, cpp] --- # 0107a — `fn doctor modules` Parte del issue principal [0107](0107-modules-standardization.md). Feature flag `modules-v2`. ## Objetivo Subcomando `fn doctor modules` + funcion del registry `audit_modules_drift_go_infra` que detecta: 1. App declara `uses_modules: [X]` Y un miembro de X aparece en `uses_functions` → drift. 2. App declara `uses_modules: [X]` pero su `CMakeLists.txt` NO linkea `fn_module_X` → mismatch. 3. App linkea `fn_module_X` pero NO declara `uses_modules: [X]` → mismatch inverso. 4. App declara `uses_modules: [{name: X, min_version: "1.4"}]` y `module.md::version` < 1.4 → version skew (post 0107e). ## Tareas - [ ] **1.1** `functions/infra/audit_modules_drift.go` con firma: ```go type ModuleDriftReport struct { ModuleID string ModuleVersion string ConsumersTotal int ConsumersWithDrift int Violations []DriftViolation } type DriftViolation struct { AppID string Kind string // "duplicate_members" | "uses_modules_no_link" | "link_no_uses_modules" | "version_skew" DuplicatedIDs []string Message string } func AuditModulesDrift(registryDB string, cppRoot string) ([]ModuleDriftReport, error) ``` - [ ] **1.2** `.md` correspondiente con frontmatter completo + ejemplo lanzable. - [ ] **1.3** Subcomando en `cmd/fn/doctor.go`: `fn doctor modules` + `fn doctor modules --json`. - [ ] **1.4** Exponer via MCP: `mcp__registry__fn_doctor subcommand="modules"`. - [ ] **1.5** Test sintetico: fixture con 1 modulo + 3 apps (1 limpia, 1 con drift de duplicados, 1 con version skew). - [ ] **1.6** Anadir entrada a `.claude/rules/fn_doctor.md` mapeando subcomando. ## Output esperado (texto) ``` fn doctor modules ================= data_table_cpp v1.4.0 — 7 consumers services_monitor DRIFT 12 duplicated members in uses_functions dag_engine_ui DRIFT 12 duplicated members in uses_functions odr_console DRIFT 5 duplicated members in uses_functions navegator_dashboard DRIFT 12 duplicated members in uses_functions graph_explorer DRIFT 12 duplicated members in uses_functions registry_dashboard DRIFT 11 duplicated members in uses_functions app_gestion DRIFT 12 duplicated members in uses_functions framework_cpp v1.1.0 — 0 explicit consumers (transitive via add_imgui_app) Summary: 2 modules, 7 apps with drift, 0 version skews. Exit: 1 (drift detected) ``` ## Riesgos - Falso positivo si un app legitimamente necesita un miembro fuera del scope del modulo (ej. usar `lua_engine` standalone). Mitigacion: post-0107d (members generales fuera del modulo), este caso desaparece. Mientras tanto: flag `--ignore-known` con allowlist temporal.