Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.1 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | tested | tests | test_file_path | file_path | params | output | |||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| audit_projects_coverage | function | go | infra | 1.0.0 | impure | func AuditProjectsCoverage(registryRoot string) ([]ProjectCoverage, error) | Audita la cobertura de los projects del registry frente a sus sub-repos Gitea: comprueba si cada project tiene .git local, remote origin y repo_url declarado, y cuantos de sus hijos (apps + analyses) estan clonados en disco versus solo conocidos por la BD. Motor del subcomando fn doctor projects. Solo lee registry.db + filesystem + git local, nunca la red ni la API de Gitea. Incluye FindOrphanProjectRefs, el check inverso: detecta apps o analyses que declaran un project_id sin fila en la tabla projects (project paraguas huerfano, riesgo de perdida al sincronizar). |
|
false | error_go_core |
|
true |
|
functions/infra/audit_projects_coverage_test.go | functions/infra/audit_projects_coverage.go |
|
Slice de ProjectCoverage, una entrada por fila de la tabla projects, con flags de git/remote/repo_url, conteos de hijos clonados vs declarados, y la lista de issues detectados. La funcion de formato FormatProjectsCoverage produce una tabla de texto humano. |
Ejemplo
package main
import (
"fmt"
"fn-registry/functions/infra"
)
func main() {
rows, err := infra.AuditProjectsCoverage("/home/enmanuel/fn_registry")
if err != nil {
panic(err)
}
fmt.Print(infra.FormatProjectsCoverage(rows))
}
Salida típica:
PROJECT GIT REMOTE REPO_URL CHILDREN ISSUES
fleet_monitoring ✓ ✓ ✓ 2/2 -
fn_monitoring ✓ ✓ ✓ 3/3 -
message_bus ✓ ✓ ✓ 3/4 children_missing
web_scraping ✗ ✗ ✗ 0/3 no_gitea_repo; children_missing
1/4 projects con problemas de cobertura.
Check inverso: FindOrphanProjectRefs
Mientras AuditProjectsCoverage parte de la tabla projects y mira hacia abajo (¿están sus hijos clonados?), FindOrphanProjectRefs recorre el grafo en sentido contrario: parte de las apps y analyses y mira hacia arriba (¿existe el project paraguas que declaran?). Detecta el drift inverso, apps o analyses cuyo project_id no tiene ninguna fila en la tabla projects. Es un project huérfano: existe en otro PC y nunca se sincronizó a este, o nunca se creó aquí. Es un riesgo de pérdida silenciosa, porque el enlace del hijo apunta a un project que este registro no conoce.
package main
import (
"fmt"
"fn-registry/functions/infra"
)
func main() {
orphans, err := infra.FindOrphanProjectRefs("/home/enmanuel/fn_registry")
if err != nil {
panic(err)
}
fmt.Print(infra.FormatOrphanProjectRefs(orphans))
}
La firma es func FindOrphanProjectRefs(registryRoot string) ([]OrphanProjectRef, error). Cada OrphanProjectRef agrupa, por ProjectID huérfano, los ids de las apps (Apps) y analyses (Analyses) que lo referencian, ambas listas ordenadas alfabéticamente y el slice resultante ordenado por ProjectID. Cuando todos los hijos apuntan a un project conocido devuelve un slice vacío (no nil) sin error. FormatOrphanProjectRefs produce una tabla de texto humano con el project_id, cuántas apps y analyses lo referencian y sus ids; si no hay huérfanos imprime una sola línea dejándolo claro.
Caso real detectado en este registro: apps con project_id ∈ {element_agents, imagegen, osint_graph} sin fila correspondiente en projects.
Salida típica con huérfanos:
PROJECT_ID APPS ANALYSES REFERENCED_BY
element_agents 1 0 shell_agent
imagegen 1 0 imagegen_ui
osint_graph 2 1 graph_explorer, scraper, gliner_glirel_tuning
3 project_id huérfanos (referenciados por hijos pero sin fila en projects).
Cuando usarla
Úsala antes de un /full-git-pull masivo o tras clonar el registry en un PC nuevo para saber qué projects están realmente respaldados por su sub-repo Gitea y cuántos de sus hijos (apps y analyses) quedarían sin clonar. También como motor del futuro subcomando fn doctor projects: el caller la enchufa desde cmd/fn/doctor.go igual que AuditUsesFunctions o AuditServicesSpec, formatea con FormatProjectsCoverage para texto humano y serializa el slice directamente para --json.
Gotchas
- Es impura: lee
registry.db(abierto en modo read-only?mode=ro), recorre el filesystem y ejecutagit -C <dir> remote get-url origin. No toca la red ni la API de Gitea, así que no necesita token y es rápida. HasRemotesolo se evalúa cuando el project tiene.gitlocal; si no hay.git, quedafalsesin intentar el comando git.gitHasRemoteOrigindevuelvefalseante cualquier error (no hay remoteorigin, no es un repo, git no instalado). No distingue "sin origin" de "git ausente"; si necesitas esa distinción, compruebagitpor separado.- El issue
no_gitea_repose emite solo cuando faltan ambos indicadores (!HasRemote && !RepoURLDeclared). Un project conrepo_urldeclarado pero sin clonar (dir_not_found) NO se marcano_gitea_repo— el repo existe en Gitea, simplemente no está en este disco. ChildrenMissingcuenta los hijos (apps + analyses con eseproject_id) cuya carpeta no tiene.giten disco: son los que se perderían o habría que reclonar. Cero hijos en la BD produce0/0y no genera issue.- Si
projects.dir_pathestá vacío, se derivaprojects/<id>. Losdir_pathya absolutos se respetan tal cual. - Devuelve error únicamente si
registry.dbno puede abrirse o consultarse. Los projects cuyo directorio no existe SÍ aparecen en el resultado, marcados condir_not_found, para que el caller los muestre en vez de descartarlos en silencio. FindOrphanProjectRefstambién es impura: leeregistry.dben modo read-only (?mode=ro), pero no toca el filesystem ni git, solo cruza las tablasprojects,appsyanalysis. Ignora los hijos conproject_idvacío (no son huérfanos, simplemente no pertenecen a ningún project). Devuelve un slice vacío no-nil cuando no hay huérfanos, así que el caller puede distinguir "sin huérfanos" (slice vacío, error nil) de "fallo al leer la BD" (error no nil).