--- name: audit_app_location kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func AuditAppLocation(repoRoot string) ([]AppLocationViolation, error)" description: "Detecta artefactos (apps y analyses) ubicados en carpetas de lenguaje (cpp/apps/, python/apps/, bash/apps/, frontend/apps/, y sus equivalentes /analysis/). Estas ubicaciones violan la convencion del registry (issue 0096): los artefactos deben vivir en apps/ o analysis/ en la raiz, o en projects/*/apps/ y projects/*/analysis/. Retorna una lista de AppLocationViolation con la ruta relativa, kind (app|analysis) y lang (cpp|python|bash|frontend)." tags: [doctor, audit, location, artefacts, registry] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: ["os", "path/filepath"] params: - name: repoRoot desc: "Ruta absoluta a la raiz del repositorio fn_registry. Todas las rutas en las violaciones son relativas a este directorio." output: "Lista de AppLocationViolation con (Path, Kind, Lang) por cada artefacto mal ubicado. Vacia si no hay violaciones. Error si un directorio prohibido existe pero no es legible." tested: true tests: - "detecta app.md en directorio prohibido cpp/apps" - "directorios prohibidos inexistentes no producen error" - "detecta analysis.md en directorio prohibido python/analysis" test_file_path: "functions/infra/audit_app_location_test.go" file_path: "functions/infra/audit_app_location.go" --- ## Ejemplo ```go violations, err := AuditAppLocation("/home/lucas/fn_registry") if err != nil { log.Fatal(err) } for _, v := range violations { fmt.Printf("[%s/%s] %s → mover a apps/%s o projects/.../apps/%s\n", v.Lang, v.Kind, v.Path, filepath.Base(v.Path), filepath.Base(v.Path)) } // Ejemplo de salida: // [cpp/app] cpp/apps/my_tool → mover a apps/my_tool o projects/.../apps/my_tool ``` ## Cuando usarla Usar como check de `fn doctor artefacts` o en pre-commit para detectar artefactos que se crearon en la carpeta del lenguaje equivocada. Invocar despues de `fn index` para validar el estado del repo. ## Gotchas - Solo revisa subdirectorios de nivel 1 dentro de cada directorio prohibido. No escanea recursivamente. - Un subdirectorio sin `app.md` ni `analysis.md` NO se reporta (ej. `cpp/apps/bar/` sin manifest = ignorado). - Los artefactos en `apps/`, `analysis/`, `projects/*/apps/` y `projects/*/analysis/` son ubicaciones canonicas y NO se comprueban. - `AppLocationViolation` esta definida en el mismo paquete (`infra`), no como tipo separado del registry.