Invertebrate — Revisión estilo Greptile
La ventaja de Greptile sobre un linter es el contexto: revisa el diff contra un grafo de todo el repositorio, por lo que detecta el renombre que dejó tres invocaciones rotas, el nuevo endpoint al que le falta el decorador de autenticación que todos sus hermanos tienen, la "optimización" que convierte a un llamante en un no-op. Reproduce eso. Una revisión que solo lee el diff no es esta skill.
Su segunda ventaja es la señal: cada comentario es un bug concreto y verificado con una solución, no un ensayo de estilo. Los equipos silencian a los revisores que gritan "al lobo". Ante la duda, déjalo fuera.
1. Resolver el target
| El usuario proporcionó | Fuente del diff |
|---|---|
| Número de PR / URL | gh pr view <n> --json title,body,baseRefName,headRefName,files + gh pr diff <n> |
| Rama | git diff <base>...HEAD (tres puntos = diff desde la base de fusión; base = main/master/develop, el que exista) |
| Nada | git diff HEAD (staged+unstaged); si está vacío, la rama actual vs su base |
Un archivo .diff/.patch | ese archivo; el working tree es el repositorio post-cambio |
Lee el título/descripción del PR si está disponible (desde gh, o un archivo de descripción al que el usuario apunte). "Un PR de seguridad se envía sin la corrección" es una captura real de Greptile: enumera cada afirmación que hace la descripción ("corrige X", "agrega validación para Y") y verifica que el diff realmente la cumpla. Una corrección afirmada que no está en el diff es un hallazgo con la severidad del bug que dice corregir.
Un PR limpio es un resultado válido. Si la verificación no deja hallazgos, dímelo, puntúalo 4-5/5, y para — inventar problemas para parecer minucioso es la forma más rápida de que silencien a un revisor.
2. Cargar configuración de revisión
La carpeta de configuración es .invertebrate/. Para compatibilidad con equipos que ya usan Greptile, .greptile/ usa el formato idéntico y se lee donde no exista .invertebrate/. Resuelve por directorio: en cada directorio, .invertebrate/ si está presente, si no .greptile/ — nunca ambos de un mismo directorio. Verifica la raíz del repositorio y cada directorio que contenga un archivo modificado (monorepo: el más cercano gana para valores escalares, listas/instrucciones se acumulan desde los padres). También acepta un greptile.json raíz heredado con los mismos campos. Nunca crees ni modifiques estas carpetas — son solo de entrada.
config.json:strictness1|2|3 (por defecto 2) — ver filtrado en §5commentTypes(por defecto["logic","syntax","style"]) — descarta hallazgos de tipos no listadosignorePatterns(sintaxis gitignore, separados por nueva línea) — salta archivos que coincidaninstructions— guía del revisor en texto libre, síguelarules[]—{id, rule, scope[glob], severity: low|medium|high, enabled}; aplica solo dondescopecoincida;disabledRuleselimina ids heredados
rules.md— reglas markdown simples para ese árbol de directoriosfiles.json—{files:[{path, description, scope}]}: lee estos archivos como contexto cuandoscopecoincida (o siempre si no tiene scope)
¿Ninguna carpeta en ningún lado? Usa los estándares de codificación de CLAUDE.md / AGENTS.md / CONTRIBUTING.md como reglas en su lugar. Anota en el informe qué configuración se aplicó.
Una violación de regla se convierte en un hallazgo que cita la regla (Rule: <id o primeras palabras>). La severidad de la regla se mapea: high→P1, medium→P2, low→P2.
3. Construir el grafo de contexto (la parte que importa)
Para cada hunk modificado, identifica los símbolos que define, elimina, renombra o cambia la firma/semántica de (funciones, métodos, clases, tipos, constantes exportadas, rutas, columnas de BD, claves de configuración, variables de entorno, nombres de eventos).
Para cada uno de esos símbolos, busca en todo el repositorio, no solo en los archivos modificados:
- Llamantes / referencias —
Greppor el nombre antiguo y el nuevo. Un símbolo eliminado/renombrado con referencias supervivientes es un bug garantizado. - Hermanos — código que hace el mismo tipo de cosa (otros endpoints en el router, otros manejadores de la misma interfaz, otras migraciones). Código nuevo que omite un patrón que todos sus hermanos siguen (decorador de autenticación, registro de auditoría, validación, transacción, bloqueo,
await) es una de las mejores capturas de Greptile. - Invocados — lee la implementación de cualquier cosa que el nuevo código llame y cuyo contrato importe (¿lanza excepción? ¿devuelve null? ¿ya bloquea? ¿es asíncrono?).
- Flujo de datos — de dónde vienen las entradas (¿controladas por el usuario? ¿parámetro de URL?) y a dónde van (SQL/HogQL, shell, ruta del sistema de archivos, ejecución de código dinámico, HTML).
Mantén una lista corta: símbolo → archivos que dependen de él → qué les hace el cambio. Úsala para escribir los hallazgos; no la vuelques en el informe.
4. Cazar
Recorre el diff con el grafo en mano. Categorías que Greptile realmente reporta, con ejemplos reales:
- Lógica — bucle que sale temprano dejando estado parcial; flag/condición invertida; valor con alias que evade una comprobación; advertencias que nunca llegan al usuario.
- Refactorización — renombre que deja llamantes sin definir; código movido que pierde un efecto secundario.
- Seguridad — falta de autenticación/autorización en un nuevo endpoint; inyección a través de entrada de usuario en consulta/shell/ruta; escape del sandbox/ámbito (symlinks, montajes,
~, expansión de variables); campo nulo/ausente que evade una protección. - Validación — entrada vacía/malformada aceptada como válida; entrada válida rechazada; regex sin anclaje.
- Ejecución / Sintaxis — llamada a método indefinido; falta de
await; número de argumentos incorrecto; tipo incorrecto; código que no compila. - Manejo de errores — excepciones tragadas; rastreos/secrets en crudo filtrados al cliente; recurso cerrado en el handle incorrecto/indefinido en la ruta de error.
- Concurrencia — carreras de verificar-y-actuar y leer-modificar-escribir; estado mutable compartido entre tareas/hilos; orden de inicio que pierde eventos.
- Pérdida/integridad de datos — escrituras no atómicas; doble aplicación en reproducción; truncamiento silencioso; datos eliminados que reaparecen.
- Rendimiento — consultas N+1, O(n²) en ruta crítica, una "optimización" que es un no-op silencioso.
- Alineación / filtración — verdad fundamental o secretos expuestos a través de un endpoint de estado/depuración o un registro.
Verifica cada candidato antes de conservarlo. Debes poder afirmar: la línea exacta, la entrada/estado concreto que lo desencadena y el resultado incorrecto. Si no puedes construir el fallo, descártalo. Relee el código circundante — la mitad de los bugs de apariencia plausible se manejan tres líneas después.
5. Clasificar y filtrar
Cada hallazgo recibe:
- Severidad — P0 debe corregirse antes de fusionar (agujero de seguridad, pérdida de datos, caída en una ruta común, rotura de build). P1 debería corregirse (comportamiento incorrecto, caso límite roto, violación de regla con severidad alta). P2 considerar (mantenibilidad, rendimiento menor, regla de baja severidad).
- Tipo —
logic(bugs, comportamiento, casos límite),syntax(no compilará/ejecutará, mal uso del lenguaje),style(calidad, nomenclatura, convenciones).
Filtrar por strictness:
- 1 — conserva P0, P1, P2.
- 2 (por defecto) — conserva P0, P1; conserva P2 solo si viola una regla configurada explícita.
- 3 — conserva P0, más estos P1: seguridad, caídas/500s alcanzables desde entrada de usuario, y violaciones de reglas configuradas de severidad
high. Strictness 3 significa "solo lo que activaría una paginación o lo que el equipo pidió explícitamente", y un crash desencadenable remotamente califica.
Luego descarta tipos que no estén en commentTypes. Formato puro que un formateador corregiría: no lo reportes nunca.
6. Puntuación de confianza (0-5)
| Puntuación | Significado |
|---|---|
| 5/5 | Listo para producción — fusionar |
| 4/5 | Pulido menor — fusionar tras correcciones pequeñas (solo P2) |
| 3/5 | Problemas de implementación — abordar comentarios primero (cualquier P1) |
| 2/5 | Bugs significativos — necesita rehacer (múltiples P1, o un P0 fácil de corregir) |
| 0-1/5 | Problemas críticos — replantear (P0 seguridad/pérdida de datos, o el diseño está mal) |
Las puntuaciones son contextuales: el mismo bug en pagos/auth/migraciones puntúa más bajo que en un script interno. Da una frase de justificación.
7. Diagrama
Elige según lo que cambió; omite para diffs triviales (documentación, cambios de versión, <~20 líneas de lógica local):
- sequenceDiagram — interacciones multi-componente, flujos de solicitud/API, ordenamiento asíncrono/concurrente (muestra la carrera si la hay)
- erDiagram — cambios en esquema / modelo de datos
- classDiagram — cambios en jerarquía de clases/interfaces
- flowchart — cambios en flujo de control / lógica de negocio
Diagrama el cambio, no todo el sistema. Mantenlo por debajo de ~15 nodos. Marca el paso con error con una Note / etiqueta.
8. Salida
Usa exactamente esta estructura (las secciones pueden omitirse solo donde se indique):
## Revisión Invertebrate — <título del PR o rama>
### Resumen
<2-4 frases, lenguaje sencillo: qué hace el cambio, a quién/afecta qué, por qué. Luego 1 frase sobre el riesgo principal.>
### Puntuación de Confianza: N/5
<una frase de por qué>
### Hallazgos
| # | Sev | Tipo | Ubicación | Problema |
|---|---|---|---|---|
| 1 | P0 | logic | `path/file.ts:42` | <título corto> |
(Si no hay: "No se encontraron problemas.")
### Diagrama
```mermaid
...
```
(omitir sección para cambios triviales)
### Comentarios Inline
#### 1. [P0 · logic] <título corto>
`path/file.ts:42`
<Qué está mal, el escenario de fallo concreto, y — si es multi-archivo — qué otros archivos se rompen y por qué. 2-5 frases.>
```diff
- línea antigua
+ línea corregida
```
#### 2. ...
---
<sub>Revisados <N> archivos · config: <.invertebrate o .greptile path | CLAUDE.md | valores por defecto> · strictness <n> · <sha de commit si se conoce></sub>
Los diffs de corrección sugerida deben ser reales, mínimos y aplicables al código real. Si la corrección abarca varios archivos, muestra el hunk de cada archivo con su ruta como línea de encabezado. Si no existe una corrección segura de un solo hunk, descríbela en lugar de inventarla.
Después del informe, ofrece: "Di fix all, fix P0 o fix #2 y los aplicaré." No apliques correcciones sin que te lo pidan.
9. Publicar en GitHub (solo cuando se pida: --post, "publícalo", "comenta en el PR")
Publicar es hacia afuera — hazlo solo ante una solicitud explícita para ese PR.
- Obtén
owner/repo(gh repo view --json nameWithOwner -q .nameWithOwner) y el sha de la cabeza (gh pr view <n> --json headRefOid -q .headRefOid). - Los comentarios inline solo pueden apuntar a líneas presentes en el diff del PR (lado DERECHO, números de línea nuevos). Los hallazgos en líneas fuera del diff van solo en el cuerpo del resumen.
- Escribe el JSON de la revisión en un archivo temporal y publícalo en una sola llamada:
{
"commit_id": "<sha de la cabeza>",
"event": "COMMENT",
"body": "<el informe markdown completo de §8 sin la sección de Comentarios Inline>",
"comments": [
{"path": "src/file.ts", "line": 42, "side": "RIGHT",
"body": "**P0 · logic** — <título>\n\n<explicación>\n\n```suggestion\n<reemplazo exacto para la línea 42>\n```"}
]
}
gh api repos/<owner>/<repo>/pulls/<n>/reviews --method POST --input review.json
Usa bloques ```suggestion de GitHub solo cuando el reemplazo cubra exactamente la(s) línea(s) comentada(s) (usa start_line + line para varias líneas). De lo contrario, usa un bloque ```diff. Nunca uses REQUEST_CHANGES/APPROVE a menos que el usuario lo pida. Reporta la URL de la revisión desde la respuesta.