--- name: audit_e2e_coverage kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func AuditE2ECoverage(roots []string) (E2ECoverageReport, error)" description: "Escanea directorios en busca de app.md y reporta cuales declaran e2e_checks en su frontmatter YAML. Retorna total, with_checks, missing (paths relativos) y coverage_pct (0-100). Impuro por lectura de filesystem." tags: [e2e_checks, coverage, audit, doctor, infra] params: - name: roots desc: "lista de directorios raiz a escanear recursivamente buscando app.md (ej. ['apps', 'cpp/apps', 'projects']). Directorios inexistentes se ignoran silenciosamente." output: "E2ECoverageReport con total/with_checks/missing/coverage_pct. Error no nil solo ante fallo real de I/O." uses_functions: [] uses_types: ["e2e_coverage_report_go_infra"] returns: ["e2e_coverage_report_go_infra"] returns_optional: false error_type: "error_go_core" imports: ["fmt", "math", "os", "path/filepath", "strings"] tested: true tests: - "directorio vacio sin app.md retorna Total=0 y CoveragePct=0" - "todos los app.md con e2e_checks retorna CoveragePct=100" - "cobertura parcial calcula CoveragePct correcto y puebla Missing" test_file_path: "functions/infra/audit_e2e_coverage_test.go" file_path: "functions/infra/audit_e2e_coverage.go" --- ## Ejemplo ```go report, err := infra.AuditE2ECoverage([]string{"apps", "cpp/apps", "projects"}) if err != nil { log.Fatal(err) } fmt.Printf("Coverage: %.2f%% (%d/%d apps)\n", report.CoveragePct, report.WithChecks, report.Total) for _, m := range report.Missing { fmt.Println(" missing:", m) } ``` ## Cuando usarla Usar como backend de `fn doctor e2e-coverage` para detectar apps sin contrato de validacion. Tambien util antes de crear proposals `e2e_check_add`: llamar primero para obtener la lista de apps que necesitan cobertura y priorizar las que mas se usan. ## Gotchas - Solo detecta `e2e_checks:` como substring en el frontmatter — no valida la estructura YAML completa del bloque. Un `# e2e_checks:` comentado pasaria como cubierto. - Los paths en `Missing` son los paths tal como los devuelve `filepath.WalkDir`, que pueden ser absolutos si los elementos de `roots` son absolutos. Para comparacion reproducible, pasar roots relativas al cwd. - Un `app.md` no legible (permisos) se cuenta en `Total` y se añade a `Missing` — no aborta el scan.