feat(0121b): audit_e2e_coverage_go_infra + fn doctor e2e-coverage subcmd

- Crea functions/infra/audit_e2e_coverage.go: AuditE2ECoverage(roots) escanea
  app.md recursivamente, detecta e2e_checks: en frontmatter, retorna
  E2ECoverageReport{total, with_checks, missing, coverage_pct}.
- Crea functions/infra/e2e_coverage_report.go: tipo E2ECoverageReport con
  JSON tags (total, with_checks, missing, coverage_pct).
- Crea types/infra/e2e_coverage_report.md: metadata del tipo para registry.
- Crea functions/infra/audit_e2e_coverage.md: documentacion self-contained
  con Ejemplo, Cuando usarla, Gotchas.
- Crea functions/infra/audit_e2e_coverage_test.go: 3 tests (empty, all-covered,
  partial) — todos pasan.
- Edita cmd/fn/doctor.go: agrega case "e2e-coverage" -> doctorE2ECoverage().
  Output text (tabla tabwriter + lista de apps missing) y --json (E2ECoverageReport).

Acceptance verificado:
  fn doctor e2e-coverage --json -> {total, with_checks, missing, coverage_pct} OK
  fn doctor e2e-coverage        -> tabla text OK
  go test ./functions/infra/... -> 3/3 PASS
  fn show audit_e2e_coverage_go_infra -> indexada OK

task_run: task_d285372493cce2e6 iter 1

Co-authored-by: fn-orquestador <noreply@fn-registry>
This commit is contained in:
2026-05-19 01:45:54 +02:00
parent 32bb2cbd25
commit 7b0b697b18
6 changed files with 368 additions and 0 deletions
+41
View File
@@ -68,6 +68,8 @@ func cmdDoctor(args []string) {
doctorModules(r, jsonOut)
case "dod":
doctorDod(r, jsonOut)
case "e2e-coverage":
doctorE2ECoverage(r, jsonOut)
default:
fmt.Fprintf(os.Stderr, "unknown doctor subcommand: %s\n", sub)
doctorUsage()
@@ -97,6 +99,7 @@ Subcommands:
app-location Detecta artefactos (apps/analysis) en carpetas de lenguaje (cpp/apps/, etc.) - issue 0096
modules Drift entre uses_modules (app.md) y fn_module_<x> link calls (CMakeLists.txt) - issue 0097
dod Audita bloque dod_evidence_schema en dev/issues/ y dev/flows/ (issue 0114)
e2e-coverage Porcentaje de apps con e2e_checks declarado en su app.md (issue 0121b)
Flags:
--json Salida JSON (para scripting/agentes)
@@ -685,3 +688,41 @@ func doctorDod(root string, jsonOut bool) {
}
}
}
func doctorE2ECoverage(root string, jsonOut bool) {
roots := []string{
filepath.Join(root, "apps"),
filepath.Join(root, "cpp", "apps"),
filepath.Join(root, "projects"),
}
report, err := infra.AuditE2ECoverage(roots)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
if jsonOut {
emit(report)
return
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintln(w, "METRIC\tVALUE")
fmt.Fprintf(w, "total\t%d\n", report.Total)
fmt.Fprintf(w, "with_checks\t%d\n", report.WithChecks)
fmt.Fprintf(w, "missing\t%d\n", len(report.Missing))
fmt.Fprintf(w, "coverage_pct\t%.2f%%\n", report.CoveragePct)
w.Flush()
if len(report.Missing) > 0 {
fmt.Println("\nApps without e2e_checks:")
rel := func(p string) string {
if r, err := filepath.Rel(root, p); err == nil {
return r
}
return p
}
for _, m := range report.Missing {
fmt.Printf(" %s\n", rel(m))
}
}
}