docs(rules): registry-first + FTS5 quoting gotcha
- Nueva regla registry_first.md: antes de escribir codigo en un artefacto, buscar en registry.db (FTS5); si falta una primitiva reutilizable, delegar a fn-constructor en vez de escribir inline. - INDEX.md: entrada 22 para la nueva regla. - CLAUDE.md: nota sobre escapado de tokens FTS5 con caracteres especiales (column:"valor-con-guion") para evitar errores "no such column" / "syntax error near .". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,17 @@ sqlite3 registry.db ".schema"
|
||||
|
||||
**Regla:** Si necesitas saber si algo existe o hay algo similar, haz la consulta FTS5 sobre la BD. No asumas que no existe sin consultar primero.
|
||||
|
||||
**Escapado FTS5 (gotcha):** despues de `column:` el valor debe ser un solo token alfanumerico ASCII (underscores OK). Cualquier otro caracter (`-`, `.`, `:`, espacios) rompe el parser con `no such column: X` o `syntax error near "."`. Encierra el valor en comillas dobles dentro del MATCH:
|
||||
|
||||
```bash
|
||||
# MAL: description:single-page → "no such column: page"
|
||||
# MAL: description:embed.FS → 'syntax error near "."'
|
||||
# BIEN:
|
||||
sqlite3 registry.db "SELECT id FROM functions WHERE id IN (SELECT id FROM functions_fts WHERE functions_fts MATCH 'description:\"single-page\" OR description:\"embed.FS\"');"
|
||||
```
|
||||
|
||||
Tokens multi-palabra tambien necesitan comillas: `description:"react router"`.
|
||||
|
||||
### Schema rapido
|
||||
|
||||
**functions** — columnas: `id, name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, example, tested, tests, test_file_path, file_path, created_at, updated_at, props, emits, has_state, framework, variant, notes, documentation, code, content_hash, source_repo, source_license, source_file, params_schema`
|
||||
|
||||
@@ -25,3 +25,4 @@ Reglas operativas del proyecto. Cada archivo es una regla independiente.
|
||||
| 19 | [cpp_apps.md](cpp_apps.md) | Estandarizacion de apps C++: estructura, CMake, app.md, sub-repo, runtime — apunta a cpp/PATTERNS.md y cpp/DESIGN_SYSTEM.md como autoritativas |
|
||||
| 20 | [artefactos.md](artefactos.md) | Termino paraguas para apps, analysis, vaults, projects y playgrounds (todo lo que no es codigo reutilizable) |
|
||||
| 21 | [playgrounds.md](playgrounds.md) | Prototipos rapidos dentro de un artefacto padre — heredan entorno, no se indexan, no tienen repo propio |
|
||||
| 22 | [registry_first.md](registry_first.md) | Antes de escribir codigo en un artefacto: buscar en el registry, reutilizar si existe, delegar a `fn-constructor` si falta |
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
## Registry-first: reutilizar antes que escribir, delegar antes que escribir inline
|
||||
|
||||
**OBLIGATORIO para todos los artefactos** (apps, analyses, projects, playgrounds, services). El registry existe para que las apps se compongan a partir de funciones probadas. No respetar esto convierte cada app en una isla con codigo duplicado y bugs unicos.
|
||||
|
||||
### Flujo obligatorio antes de escribir codigo en un artefacto
|
||||
|
||||
1. **Consultar registry.db con FTS5** para encontrar funciones existentes que cubran el caso. No es opcional. Buscar por `name`, `description`, `tags`, `signature`, `code` y `params_schema`. Probar varios sinonimos (`http`, `serve`, `router`; `id`, `uuid`, `random_hex`; etc.).
|
||||
|
||||
2. **Reutilizar lo que existe**. Importar la funcion del registry y declararla en `uses_functions` del `app.md`. NO reescribir logica inline cuando ya hay una funcion.
|
||||
|
||||
3. **Si falta una pieza reutilizable → delegar a `fn-constructor`** (subagent_type `fn-constructor`). NO escribir la funcion inline en el artefacto. El agente construye la funcion en su sitio (`functions/{domain}/`, `python/functions/{domain}/`, etc.) con `.go/.py/.sh/.ts` + `.md` correctos, tests, y respetando las reglas de pureza/firma.
|
||||
|
||||
4. **Solo despues** se escribe el codigo del artefacto, que orquesta funciones del registry y aporta unicamente la logica especifica del dominio (CRUD de tablas concretas, layout de UI, flujo de la app).
|
||||
|
||||
### Que va al registry vs que va al artefacto
|
||||
|
||||
| Tipo de codigo | Donde |
|
||||
|---|---|
|
||||
| Logica reutilizable, primitiva, generica (parser, helper http, abrir SQLite, generar IDs, formatear timestamps con politica fija, middleware, etc.) | `functions/{domain}/` — delegar a `fn-constructor` si no existe |
|
||||
| Composicion de varias funciones del registry para un flujo concreto | `pipelines` (registry) o codigo del artefacto segun reusabilidad |
|
||||
| Schema SQL especifico del artefacto | Migraciones del artefacto |
|
||||
| Handlers HTTP que solo hacen sentido para este artefacto (ej. `/api/board` de un kanban) | Codigo del artefacto, pero usando `http_json_response_go_infra`, `http_parse_body_go_infra`, etc. del registry |
|
||||
| Layout/components especificos de la UI del artefacto | Codigo del artefacto, pero consumiendo componentes de `frontend/functions/ui/` (`@fn_library`) |
|
||||
|
||||
Regla practica: **si dos artefactos ya hacen o haran lo mismo, es funcion del registry**. One-liners idiomaticos de la stdlib (`time.Now().UTC().Format(...)`) NO necesitan ser registry — se ven en cualquier sitio. Pero un patron como "abrir SQLite con WAL + foreign keys + ping" SI (y por eso existe `sqlite_open_go_infra`).
|
||||
|
||||
### Cuando delegar a `fn-constructor`
|
||||
|
||||
Delegar SIEMPRE que se necesite una funcion reutilizable que no existe. El prompt del subagente debe incluir:
|
||||
- Lenguaje, dominio, nombre propuesto.
|
||||
- Firma esperada (params + return).
|
||||
- Pureza (`pure` o `impure`).
|
||||
- Una breve descripcion del proposito y del comportamiento.
|
||||
- Si hay funciones similares en el registry, listarlas para evitar duplicados.
|
||||
|
||||
El agente construye la funcion siguiendo las reglas del registry (`purity.md`, `ids_naming.md`, `types_in_signatures.md`, etc.) y deja `fn index` listo para ejecutar.
|
||||
|
||||
### Auditoria
|
||||
|
||||
Despues de implementar el artefacto, verificar que `uses_functions` del `app.md` (o equivalente) declara TODAS las funciones del registry consumidas. Esto se puede cruzar con los `import` reales del codigo:
|
||||
|
||||
```bash
|
||||
# Para Go:
|
||||
grep -rh '"fn-registry/functions/' apps/<app>/ | sort -u
|
||||
# Cada paquete importado tiene que tener al menos una funcion declarada en uses_functions.
|
||||
```
|
||||
|
||||
### Por que esta regla
|
||||
|
||||
Sin esta regla cada app reinventa: helpers SQLite, middleware HTTP, generacion de IDs, parsers, validadores, formateo de fechas. El registry pierde su razon de ser. Con esta regla, una funcion bien hecha se reutiliza en N apps; un bug se arregla una vez; la velocidad de cada app nueva crece a medida que el registry crece.
|
||||
Reference in New Issue
Block a user