From c72ae15429df02f05d31afc96cfb3db5cd90022e Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Mon, 30 Mar 2026 14:23:53 +0200 Subject: [PATCH] feat: source attribution para funciones externas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sistema de extracción de funciones desde repos externos. Agrega campos source_repo, source_license y source_file en functions y types (migración 006). Incluye manifest sources/sources.yaml, regla sources.md, parser con campos de atribución, y template actualizado con los nuevos campos. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/rules/sources.md | 49 +++++++++++++++++++ .gitignore | 3 ++ docs/templates/function.md | 4 ++ .../migrations/006_source_attribution.sql | 8 +++ registry/parser.go | 18 ++++++- sources/sources.yaml | 20 ++++++++ 6 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 .claude/rules/sources.md create mode 100644 registry/migrations/006_source_attribution.sql create mode 100644 sources/sources.yaml diff --git a/.claude/rules/sources.md b/.claude/rules/sources.md new file mode 100644 index 00000000..5314710b --- /dev/null +++ b/.claude/rules/sources.md @@ -0,0 +1,49 @@ +## Extraccion de funciones desde repos externos (`sources/`) + +### Workflow + +1. Clonar repo en `sources/` (gitignored, solo el manifest `sources/sources.yaml` se versiona) +2. El agente analiza el repo y propone funciones candidatas +3. Las funciones se **copian y adaptan** al formato del registry (.go/.py/.sh/.ts + .md con frontmatter) +4. `fn index` las registra. El manifest se actualiza con las funciones extraidas. + +### Filtro de calidad (obligatorio antes de extraer) + +Una funcion externa solo se extrae si cumple TODOS estos criterios: + +- **Firma generica**: no depende de tipos internos del repo origen ni de config hardcodeada +- **Sin estado global**: no usa variables globales, singletons, ni init() con side effects +- **Dependencias minimas**: solo stdlib o dependencias ya presentes en fn_registry +- **Pura si es posible**: si la funcion puede ser pura, debe extraerse como pura +- **Sin credenciales**: no contiene secrets, API keys, ni paths absolutos +- **Testeable**: la logica debe poder validarse con tests unitarios +- **No duplicada**: consultar registry.db con FTS5 antes de extraer para evitar duplicados +- **Licencia compatible**: el repo debe tener licencia permisiva (MIT, Apache 2.0, BSD, etc.) + +### Adaptacion al extraer + +- Renombrar a snake_case siguiendo la convencion del registry +- Adaptar firma para usar tipos nativos (no tipos internos del repo) +- Crear .md con frontmatter completo incluyendo `source_repo`, `source_license`, `source_file` +- Actualizar `sources/sources.yaml` con la extraccion + +### Campos de atribucion en frontmatter + +```yaml +source_repo: "https://github.com/user/project" +source_license: "MIT" +source_file: "pkg/original_file.go" +``` + +Estos campos se indexan en registry.db y permiten consultar: +```sql +SELECT id, source_repo, source_license FROM functions WHERE source_repo != ''; +``` + +### Lenguajes soportados para extraccion + +Cualquier lenguaje puede analizarse como fuente. El destino depende de la naturaleza de la funcion: +- Algoritmos/logica pura → Go (functions/{domain}/) o Python (python/functions/{domain}/) +- Scripts/utilidades sistema → Bash (bash/functions/{domain}/) +- UI/frontend → TypeScript (frontend/functions/{domain}/) +- C/Rust/otros → Traducir a Go o Python, manteniendo la semantica original diff --git a/.gitignore b/.gitignore index df070212..604f9558 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,9 @@ python/.venv/ # Node / pnpm **/node_modules/ +# Sources — repos externos clonados (solo se versiona el manifest) +sources/*/ + # OS .DS_Store Thumbs.db diff --git a/docs/templates/function.md b/docs/templates/function.md index 6380fc50..394c37d3 100644 --- a/docs/templates/function.md +++ b/docs/templates/function.md @@ -18,6 +18,10 @@ tested: false tests: [] test_file_path: "" file_path: "functions/core/filter_slice.go" +# Source attribution (solo para funciones extraidas de repos externos) +# source_repo: "https://github.com/user/project" +# source_license: "MIT" +# source_file: "pkg/utils.go" --- ## Ejemplo diff --git a/registry/migrations/006_source_attribution.sql b/registry/migrations/006_source_attribution.sql new file mode 100644 index 00000000..977aa973 --- /dev/null +++ b/registry/migrations/006_source_attribution.sql @@ -0,0 +1,8 @@ +-- Source attribution for functions extracted from external repositories. +ALTER TABLE functions ADD COLUMN source_repo TEXT NOT NULL DEFAULT ''; +ALTER TABLE functions ADD COLUMN source_license TEXT NOT NULL DEFAULT ''; +ALTER TABLE functions ADD COLUMN source_file TEXT NOT NULL DEFAULT ''; + +ALTER TABLE types ADD COLUMN source_repo TEXT NOT NULL DEFAULT ''; +ALTER TABLE types ADD COLUMN source_license TEXT NOT NULL DEFAULT ''; +ALTER TABLE types ADD COLUMN source_file TEXT NOT NULL DEFAULT ''; diff --git a/registry/parser.go b/registry/parser.go index e47b8c95..cea70bac 100644 --- a/registry/parser.go +++ b/registry/parser.go @@ -32,6 +32,11 @@ type rawFunction struct { TestFilePath string `yaml:"test_file_path"` FilePath string `yaml:"file_path"` + // Source attribution + SourceRepo string `yaml:"source_repo"` + SourceLicense string `yaml:"source_license"` + SourceFile string `yaml:"source_file"` + // Component fields Props []PropDef `yaml:"props"` Emits []string `yaml:"emits"` @@ -50,8 +55,11 @@ type rawType struct { Definition string `yaml:"definition"` Description string `yaml:"description"` Tags []string `yaml:"tags"` - UsesTypes []string `yaml:"uses_types"` - FilePath string `yaml:"file_path"` + UsesTypes []string `yaml:"uses_types"` + FilePath string `yaml:"file_path"` + SourceRepo string `yaml:"source_repo"` + SourceLicense string `yaml:"source_license"` + SourceFile string `yaml:"source_file"` } // rawApp mirrors the YAML frontmatter of an app .md file. @@ -146,6 +154,9 @@ func ParseFunctionMD(path string, root string) (*Function, error) { HasState: raw.HasState, Framework: raw.Framework, Variant: raw.Variant, + SourceRepo: raw.SourceRepo, + SourceLicense: raw.SourceLicense, + SourceFile: raw.SourceFile, } if root != "" && raw.FilePath != "" { @@ -196,6 +207,9 @@ func ParseTypeMD(path string, root string) (*Type, error) { Description: raw.Description, Tags: raw.Tags, UsesTypes: raw.UsesTypes, + SourceRepo: raw.SourceRepo, + SourceLicense: raw.SourceLicense, + SourceFile: raw.SourceFile, Examples: sections.example, Notes: sections.notes, Documentation: sections.documentation, diff --git a/sources/sources.yaml b/sources/sources.yaml new file mode 100644 index 00000000..91ff9a4d --- /dev/null +++ b/sources/sources.yaml @@ -0,0 +1,20 @@ +# Manifest de repositorios externos para extraccion de funciones. +# Cada entrada registra un repo clonado en sources/ y las funciones extraidas. +# +# Formato: +# - repo: https://github.com/user/project +# license: MIT +# cloned_dir: project # nombre del directorio en sources/ +# extracted: # funciones ya extraidas (el agente las registra) +# - id: func_name_go_core +# source_file: pkg/utils.go # path relativo dentro del repo original +# date: 2026-03-29 +# +# Workflow: +# 1. Clonar repo en sources/: git clone sources/ +# 2. Invocar agente extractor para analizar y proponer funciones +# 3. El agente copia, adapta, crea .go + .md con atribucion +# 4. fn index para registrar en registry.db +# 5. Actualizar este manifest con las funciones extraidas + +repos: []