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:
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user