--- id: "0087" title: "Capability Discovery Acceleration" status: pendiente type: feature domain: - meta scope: multi-app priority: alta depends: [] blocks: [] related: [] created: 2026-05-17 updated: 2026-05-17 tags: [] --- # 0087 — Capability Discovery Acceleration **Status:** done **Created:** 2026-05-14 **Closed:** 2026-05-14 **Related:** 0085 (telemetry), 0086 (delegation + capability groups) ## Problema Crear funciones para reutilizar = bueno largo plazo, pero introduce un **coste de descubrimiento** cada sesion: Claude tiene que FTS-buscar antes de usar. Si la busqueda falla o es mediocre, Claude reinventa inline ("violation: reinvent_inline"). En la sesion del 2026-05-13/14 Claude reinvento taskkill+cp+start 5 veces seguidas pese a que `deploy_cpp_exe_to_windows` ya existia. Objetivo: que **conocer las capacidades sea gratis o casi gratis** para Claude. ## Modelo de capas Cinco capas escalonadas por coste de lookup. Cada una cubre un slice de casos: | Capa | Coste lookup | Cobertura | Mecanismo | |---|---|---|---| | 1 | 0 (contexto base) | Top 20 funciones mas usadas + funciones creadas ultimos 7d | Bloque auto-generado en `CLAUDE.md` | | 2 | 0 (cada turno) | Funciones recien creadas + violations recientes | Hook `UserPromptSubmit` injecta linea `FRESH:` / `TOP:` | | 3 | 0 (mid-flight) | Patrones inline que matchean funcion existente | Hook `PreToolUse` con fuzzy FTS5 | | 4 | 1 read on demand | Cualquier dominio especifico | `docs/capabilities/.md` cargado solo si tarea matchea | | 5 | 0 (persistente) | Insights cross-session | `MEMORY.md` linea por capacidad clave | ## Piezas (7) | # | Pieza | Lang/Tipo | Aprox LOC | Tanda | |---|---|---|---|---| | 1 | `fn doctor capabilities --emit-claude-md` — top 20 + fresh 7d | Go subcommand | 80 | A | | 2 | Hook `UserPromptSubmit` → linea `FRESH:` + `TOP:` | bash | 40 | B | | 3 | `fn_match` binario fuzzy FTS5 sobre functions (input: command, output: top-N matches) | Go binary | 120 | A | | 4 | Hook `PreToolUse` → consume `fn_match`, inyecta `USE:` hint si confidence alta | bash | 60 | B | | 5 | `ids_naming.md` endurecer + validator en `fn_create_function` | Go + rules | 50 | A | | 6 | `/fn_claude` post-creation auto-append `[[fn_id]] — purpose` a `MEMORY.md` | bash skill | 30 | C | | 7 | Excepcion explicita en `registry_calls.md`: hooks pueden leer `registry.db` directo | rules | — | A | ### Fuzzy matching (pieza 3 + 4) `fn_match`: - **Input:** command string + optional tool context (Bash / Edit / heredoc). - **Pipeline:** 1. Tokenizar comando: split en palabras, ignora flags (`-v`, `/F`), conserva tokens significativos. 2. Query FTS5 sobre `functions_fts MATCH 'tok1 OR tok2 OR ...'` ordenado por `bm25()`. 3. Re-score con weights: `name` match peso x3, `tags` peso x2, `description` peso x1. 4. Threshold dinamico: `top.score / second.score > 1.5` → confidence alta. - **Output JSON:** `[{id, score, signature, snippet}, ...]` top 3. - **Latencia objetivo:** < 50ms (hook PreToolUse no puede bloquear). Hook `PreToolUse`: - Captura tool + payload. - Llama `fn_match` con timeout 200ms (no bloquea si tarda). - Si confidence alta → inyecta `FUZZY-MATCH: USE \`./fn run \` instead. Signature: .` en stderr (Claude lo lee). - Si confidence baja → silencio. ### Excepcion hooks (pieza 7) `.claude/rules/registry_calls.md` actualmente dice "NUNCA sqlite3 registry.db directo" pero esa regla apunta al AGENTE. Los hooks son lectores externos del proceso de Claude — necesitan acceso directo y rapido a FTS5 sin pasar por MCP (que requiere tool invocation por Claude). Anadir clausula: > **Hooks (PreToolUse/PostToolUse/UserPromptSubmit) pueden leer `registry.db` directo via `sqlite3` o binario Go con read-only conn.** No estan sujetos a la regla MCP-first porque no son acciones del agente, son inspeccion automatizada del entorno. Excepcion: SOLO lectura. NUNCA escritura desde hooks. ## Plan de tandas (paralelizable) ### Tanda A — cero dependencias, lanzar en paralelo - Pieza 1: `fn doctor capabilities --emit-claude-md` (Go). - Pieza 3: `fn_match` binario (Go). - Pieza 5: `ids_naming` validator + endurecer (Go + rules). - Pieza 7: clausula en `registry_calls.md` (rules, instant). ### Tanda B — depende de tanda A (consume binarios) - Pieza 2: hook `UserPromptSubmit` consume `fn doctor capabilities` output. - Pieza 4: hook `PreToolUse` consume `fn_match`. ### Tanda C — refuerzos - Pieza 6: extension de `/fn_claude` skill. ## Acceptance criteria - [x] `fn doctor capabilities --emit-claude-md` imprime bloque markdown valido pegable en CLAUDE.md. - [x] Hook `UserPromptSubmit` añade linea `FRESH: , , ...` cada turno (max 5 funciones de los ultimos 7d). - [x] `fn_match "taskkill registry_dashboard.exe"` devuelve `deploy_cpp_exe_to_windows_bash_infra` con score > threshold en < 50ms. - [x] Hook `PreToolUse` con `fn_match` muestra hint `USE: ...` en al menos 3 patrones reproducibles (taskkill, cp Desktop, cmd.exe start). - [x] Validator de `fn_create_function` rechaza nombres no predictibles (sin verbo o sin dominio). — `apps/registry_mcp/naming.go` + unit tests (2026-05-14). - [x] `/fn_claude` tras crear N funciones, MEMORY.md tiene N nuevas lineas `[[id]] — purpose`. — `.claude/scripts/append_fn_to_memory.sh` + step 5b en `.claude/commands/fn_claude.md` (2026-05-14). - [x] Reglas: `registry_calls.md` documenta la excepcion explicita para hooks. ## Metricas de exito Antes / despues, ventana 7d: - `Reg %` (% calls con function_id != '') — esperado +10pp. - `violations` count — esperado -50%. - Tiempo medio entre "patron inline" y "uso de funcion correspondiente" — esperado dia 1 → mismo turno. Visibles en Monitor tab del `registry_dashboard`. ## Notas - Capa 3 (fuzzy interceptor) es la mas potente pero requiere **benchmark** de latencia antes de habilitar en cada Bash. Si supera 100ms, degradar a "solo en comandos > N chars" o "solo al final del turno". - No introducir mas reglas: las que hay (`registry_first.md`, `delegation.md`, `registry_calls.md`) son suficientes. Esto es **infraestructura para que se cumplan**.