--- name: generate_proposals_from_telemetry lang: go domain: infra version: 0.1.0 purity: impure kind: function description: "Genera proposals automaticas para registry.db.proposals a partir de telemetria de call_monitor.operations.db. Aplica 4 reglas MVP: copy_detected, orphan, bug, wrapper_skip. IDs deterministas (sha1 truncado) garantizan idempotencia. Cierra la fase MEJORAR del bucle reactivo. Issue 0085h." tags: [audit, reactive-loop, monitoring, proposals, registry] signature: "func GenerateProposalsFromTelemetry(registryRoot string) ([]ProposalDraft, error)" error_type: "error_go_core" returns_optional: false params: - name: registryRoot desc: "Path absoluto a raiz del fn_registry (contiene registry.db y projects/fn_monitoring/apps/call_monitor/operations.db)." output: "Lista de ProposalDraft con kind, target_id, title, description, rule_id, evidence. NO escribe a DB — usar PersistProposalDrafts para persistir." uses_functions: [] uses_types: [] imports: - crypto/sha1 - database/sql - encoding/json - fmt - path/filepath - strings - time - github.com/mattn/go-sqlite3 example: | import "fn-registry/functions/infra" drafts, err := infra.GenerateProposalsFromTelemetry("$HOME/fn_registry") if err != nil { ... } inserted, total, err := infra.PersistProposalDrafts("$HOME/fn_registry", drafts) fmt.Printf("%d/%d proposals nuevas\n", inserted, total) file_path: "functions/infra/generate_proposals_from_telemetry.go" tested: false notes: | Reglas MVP implementadas: | Regla | Threshold | Proposal | |---|---|---| | copy_detected | match en copied_code | improve_function (target = registry_id matched) | | orphan | calls_90d=0 AND writes_count=0 AND no upstream consumer | deprecate_function | | bug | error_rate>0.1 AND calls_total>3 | improve_function | | wrapper_skip | violations.function_id COUNT > 3 | improve_function | Reglas pendientes (sin data aun): - perf_regression: requiere p95 (no almacenado todavia). - test_flaky: requiere test_runs poblado. - e2e_blast_radius: requiere e2e_runs_fn poblado. - pattern_inline: requiere patterns clustering (0085f). Idempotencia: cada proposal tiene `id = auto_{rule}_{sha1-10}` deterministico sobre (rule_id, target_id, extra). PersistProposalDrafts usa INSERT OR IGNORE para no sobreescribir proposals ya revisadas (approved/rejected). created_by='reactive_loop' para distinguir de proposals manuales. Filtrado orphan: cruza con `uses_functions` JSON arrays de functions/apps/ analysis. Si alguien declara la funcion como dependencia, no se marca orfana aunque tenga calls_90d=0 (uso intencional, no instrumentado por telemetria). ---