La comunicación con el usuario y los informes de revisión se realizan en español.
Para el diff entre HEAD y el punto fijo proporcionado por el usuario, realiza una revisión de doble eje:
- Normas: ¿El código sigue las guías de estilo documentadas en este repositorio?
- Especificaciones: ¿El código implementa fielmente el issue/especificación original?
Ambos ejes se ejecutan con subagentes paralelos para que no contaminen el contexto del otro, y luego esta habilidad consolida sus hallazgos.
El rastreador de issues ya debería estar disponible. Si no es así, indícale al usuario que ejecute primero /setup-matt-pocock-skills.
Flujo de trabajo
1. Determinar el punto fijo
El punto fijo es lo que el usuario dice (SHA de commit, nombre de rama, etiqueta, main, HEAD~5, etc.). Si no lo especifica, pregúntale.
Anota el comando diff de una vez: git diff <fixed-point>...HEAD (tres puntos, para comparar con la base de fusión). También anota la lista de commits con git log <fixed-point>..HEAD --oneline.
Antes de continuar, verifica que el punto fijo se pueda resolver (git rev-parse <fixed-point>) y que el diff no esté vacío. Las referencias incorrectas o los diffs vacíos deben fallar aquí, no dentro de los dos subagentes paralelos.
2. Encontrar la fuente de especificaciones
Busca la especificación original en el siguiente orden:
- Referencias a issues en los mensajes de commit (
#123,Closes #45,!67de GitLab, etc.), obtenidas a través del flujo del archivo del rastreador. - Una ruta pasada por el usuario como parámetro.
- Archivos de especificaciones en
docs/,specs/o.scratch/que coincidan con el nombre de la rama o la funcionalidad. - Si no se encuentra nada, pregúntale al usuario dónde está la especificación. Si dice que no hay, el subagente de Especificaciones se omite e informa "No hay especificaciones disponibles".
3. Encontrar la fuente de normas
Busca en el repositorio todos los archivos que documenten cómo se debe escribir el código. Si existen CODING_STANDARDS.md o CONTRIBUTING.md, deben incluirse. En proyectos Python, también revisa la configuración de linters/formateadores (ruff, black, mypy, etc.) en pyproject.toml, pero las reglas que la herramienta ya impone no necesitan revisarse.
Además de lo documentado en el repositorio, el eje de Normas siempre incluye la siguiente línea base de malos olores: un conjunto fijo de malos olores de código de Fowler (capítulo 3 de "Refactorización"), incluso si el repositorio no tiene nada documentado. Dos reglas lo rigen:
- El repositorio tiene prioridad. Las normas documentadas en el repositorio siempre ganan; cuando aprueban algo que la línea base marcaría, no marques ese mal olor.
- Siempre es un juicio. Cada mal olor es una heurística etiquetada ("podría tener Feature Envy"), nunca una infracción estricta. Al igual que con cualquier norma aquí, salta las que la herramienta ya impone.
Cada mal olor se escribe como "Qué es → Cómo arreglarlo"; compáralo con el diff:
- Nombre Misterioso (Mysterious Name): El nombre de una función, variable o tipo no indica lo que hace o contiene. → Renombrar; si no se puede pensar en un nombre honesto, el diseño en sí mismo es ambiguo.
- Código Duplicado (Duplicated Code): La misma forma lógica aparece en más de un bloque o archivo en este cambio. → Extraer la forma común y llamarla desde ambos lugares.
- Envidia de Características (Feature Envy): Un método accede más a los datos de otro objeto que a los propios. → Mover el método al objeto cuyos datos envidia.
- Montones de Datos (Data Clumps): Los mismos campos o parámetros aparecen siempre juntos (un tipo que quiere nacer). → Envolverlos en un tipo y pasar ese tipo.
- Obsesión por los Primitivos (Primitive Obsession): Usar un tipo primitivo o una cadena para representar un concepto del dominio que merece su propio tipo (por ejemplo, usar
strpara un número de parte,floatpara cantidad y tipo de moneda). → Darle a ese concepto su propio tipo pequeño (por ejemplo,dataclass). - Switches Repetidos (Repeated Switches): La misma cadena de
match/ifsobre el mismo tipo aparece repetidamente en este cambio. → Usar polimorfismo o una tabla de consulta compartida entre ambos lugares. - Cirugía de Escopeta (Shotgun Surgery): Un cambio lógico fuerza modificaciones dispersas en muchos archivos del diff. → Centralizar lo que cambia junto en un solo módulo.
- Cambio Divergente (Divergent Change): Un archivo o módulo se modifica por varias razones no relacionadas. → Dividirlo para que cada módulo cambie por una sola razón.
- Generalidad Especulativa (Speculative Generality): Abstracciones, parámetros o ganchos añadidos para requisitos que no están en la especificación. → Eliminarlos; revertir a la versión en línea y esperar a que surja la necesidad real.
- Cadenas de Mensajes (Message Chains): Largas navegaciones de
a.b().c().d()de las que el código llamante no debería depender. → Ocultar ese recorrido detrás de un método del primer objeto. - Hombre del Medio (Middle Man): Una clase o función que principalmente delega hacia abajo. → Eliminarla y llamar directamente al destino real.
- Legado Rechazado (Refused Bequest): Una subclase o implementador ignora o sobrescribe la mayor parte de lo que hereda. → Abandonar la herencia y usar composición.
4. Lanzar dos subagentes en paralelo
Lanza dos llamadas a subagentes simultáneamente (en primer plano) y consolida los informes que devuelven.
El prompt del subagente de Normas debe incluir:
- El comando diff completo y la lista de commits.
- La lista de archivos fuente de normas que encontraste en el paso 3, junto con la línea base de malos olores del paso 3 completa (el subagente no tiene otra forma de obtenerla).
- Instrucción: "Informa en español, indicando archivo/bloque en cada caso relevante: (a) cada lugar donde el diff viola las normas documentadas: cita la norma (archivo y regla); y (b) cualquier mal olor de la línea base que encuentres: nombra el mal olor y cita el bloque. Distingue entre infracciones estrictas y juicios: las violaciones a normas documentadas pueden ser estrictas, pero los malos olores de la línea base son siempre juicios, y las normas documentadas del repositorio tienen prioridad sobre la línea base. Salta las reglas que la herramienta ya impone. Máximo 400 palabras."
El prompt del subagente de Especificaciones debe incluir:
- El comando diff y la lista de commits.
- La ruta a la especificación o su contenido ya obtenido.
- Instrucción: "Informa en español: (a) requisitos que la especificación pide pero que faltan o están solo parcialmente implementados; (b) comportamientos en el diff que no fueron solicitados (desviación del alcance); (c) requisitos que parecen implementados pero de manera incorrecta. Cada hallazgo debe citar el texto correspondiente de la especificación. Máximo 400 palabras."
Si no hay especificación, omite el subagente de Especificaciones e indica en el informe final.
5. Consolidar
Coloca los dos informes bajo los encabezados ## Normas y ## Especificaciones, tal como fueron entregados o con una ligera organización. No combines ni reordenes los hallazgos, ya que los dos ejes están deliberadamente separados (ver "Por qué dos ejes").
Termina con un resumen de una línea: el número total de hallazgos por eje y el problema más grave dentro de cada eje (si lo hay). No elijas un único ganador entre ejes: eso es precisamente lo que la separación en dos ejes pretende evitar.
Por qué dos ejes
Un cambio puede aprobar un eje pero no el otro:
- Sigue todas las normas pero implementa lo incorrecto → Normas aprobadas, Especificaciones reprobadas.
- Hace exactamente lo que pide el issue pero rompe las convenciones del proyecto → Especificaciones aprobadas, Normas reprobadas.
Informar por separado evita que un eje opaque al otro.