--- name: audit_copied_code lang: go domain: infra version: 0.1.0 purity: impure kind: function description: "Audita apps en busca de cuerpos de funcion copiados del registry sin import. Calcula fingerprint normalizado (strip comments + whitespace) por funcion del registry y por funcion declarada en apps/, projects/*/apps/. Reporta matches exactos. MVP: exact_copy con sha256 truncado. Issue 0085k." tags: [audit, drift, monitoring, registry, doctor, copied-code] signature: "func AuditCopiedCode(registryRoot string) ([]CopiedCodeEntry, error)" error_type: "error_go_core" returns_optional: false params: - name: registryRoot desc: "Path absoluto al directorio raiz del fn_registry (contiene registry.db). El audit busca apps/ y projects/*/apps/ dentro." output: "Lista de CopiedCodeEntry: {app_file, app_function, registry_id, body_hash, similarity, kind}. similarity=1.0 y kind='exact_copy' en MVP." uses_functions: [] uses_types: [] imports: - crypto/sha256 - database/sql - io/fs - os - path/filepath - regexp - strings - github.com/mattn/go-sqlite3 example: | import "fn-registry/functions/infra" entries, err := infra.AuditCopiedCode("$HOME/fn_registry") if err != nil { ... } for _, e := range entries { fmt.Printf("%s:%s ~ %s (%s, %.2f)\n", e.AppFile, e.AppFunction, e.RegistryID, e.Kind, e.Similarity) } file_path: "functions/infra/audit_copied_code.go" tested: false notes: | Pipeline interno: 1. Lee `registry.db.functions(id, lang, code, file_path)` para construir fingerprint index `hash → [registry_id, ...]`. Cada `code` se parsea por `extractFunctions(code, lang)` para indexar cada funcion declarada dentro del archivo (importante para `.py` que contiene varias). 2. Construye skip-set con los `file_path` del registry para no flagear la funcion como copia de si misma. 3. Walk recursivo de `apps/` y `projects/*/apps/`. Skip de `.git`, `.venv`, `node_modules`, `__pycache__`, `build`, `dist`, `vendor`, `.pytest_cache`, `.cache`. 4. Por cada archivo `.go/.py/.sh/.ts/.cpp`, extrae funciones y hash. 5. Match en fpIndex → emite CopiedCodeEntry. Normalizacion: - Go/TS/C++: strip `//...` y `/* ... */`, collapse whitespace. - Python: strip docstrings (triple quotes), strip `#...` lines, collapse. - Bash: strip `#...` lines, collapse. Hash: sha256 hex truncado a 16 chars del cuerpo normalizado. Cuerpos con menos de 20 chars normalizados se descartan (trivialmente similares). Limitaciones MVP: - Solo exact_copy. near_copy/partial_match (fuzzy hash, AST SimHash, embeddings) en fase futura. - extractFunctions con regex naive. Falla con: - signatures multi-linea - lambdas y closures - metodos con receivers complejos - cadenas/comentarios con `{` dentro - C++ regex es la mas fragil (templates, namespaces, multiple inheritance). - No detecta copias con renames de variables. Para eso = fuzzy hash. Privacidad: solo se persisten paths, function names, y hashes. Nunca contenido del codigo. El cuerpo solo vive en memoria durante el audit. ---