lint-drupal-module
Lint Review — Módulo Drupal 11
Primera línea del informe generado: "Español confirmado."
Para qué sirve
Combina 4 fuentes de análisis (PHPStan, PHPCS, agente drupal-qa, agente drupal-security) en una sola invocación paralelizada, y consolida los hallazgos en un informe accionable. A mano son ~12 pasos y ~30 minutos; con la skill, lo que tarda la fuente más lenta (~2-5 min en completo, ~30s-1min en diff).
Fast path
1. Identificar módulo (nombre/ruta del usuario, o Glob si no especifica)
2. Detectar modo: completo (default) | diff (si dice "diff", "rápido", "vs develop")
3. Detectar entorno: ddev describe → ejecutar via "ddev exec"
4. Verificar herramientas (vendor/bin/phpstan, vendor/bin/phpcs); instalar si faltan PREGUNTANDO
5. Verificar agentes drupal-qa y drupal-security disponibles (si no, ver "Recovery")
6. Leer references/prompts-agentes.md (necesario para el paso 7)
7. Ejecutar las 4 fuentes EN PARALELO en el mismo mensaje:
a) Agent drupal-qa — prompt literal de references/prompts-agentes.md
b) Agent drupal-security — prompt literal de references/prompts-agentes.md
c) PHPStan level 5 vía Bash (ver "Ejecución en paralelo")
d) PHPCS Drupal,DrupalPractice vía Bash
8. Leer references/plantilla-informe.md y consolidar las 4 salidas en un informe markdown
9. Detectar IDE → escribir en <carpeta-IDE>/Lint reviews/<nombre-modo-rama>.md
10. Resumir top bloqueantes en chat; preguntar "arregla todo" / "solo crítico" / "déjalo así"
Si cualquier paso falla, detente y consulta references/edge-cases.md. No improvises.
Referencias bajo demanda
Tres archivos en references/, cargados solo cuando los necesitas (progressive disclosure):
| Archivo | Cuándo cargarlo | Por qué |
|---|---|---|
references/prompts-agentes.md |
Antes del paso 7 (invocar agentes) | Contiene los prompts literales para drupal-qa y drupal-security. Son largos a propósito — sin brief explícito los agentes devuelven reviews superficiales. Cópialos literales, solo sustituye <ruta-absoluta>, <modo>, <lista-archivos>. |
references/plantilla-informe.md |
Antes del paso 8 (redactar informe) | Plantilla fija. La consistencia entre informes de distintos módulos es lo que hace que el equipo los lea rápido. |
references/edge-cases.md |
Cuando algo falle | Síntoma → causa → solución para los problemas más comunes (DDEV, PHPStan, services.yml, OAuth, modo diff). |
Si ya leíste un archivo en esta sesión, no recargues — el contexto lo conserva.
Modos
Modo completo (default)
Analiza TODOS los archivos del módulo. Más exhaustivo (~2-5 min). Úsalo:
- Antes de un release
- En módulos recién creados
- Auditorías periódicas
- Cuando el usuario no especifica modo
Modo diff
Analiza SOLO los archivos cambiados en la rama actual respecto a origin/develop. Más rápido (~30s-1min). Úsalo:
- Reviews intermedias durante desarrollo
- Validación pre-push
- Cuando el usuario dice "diff", "rápido", "solo lo que cambié", "vs develop"
Obtener la lista de archivos analizables del módulo (filtrando extensiones que PHPStan/PHPCS pueden procesar):
cd drupal
git fetch origin develop --quiet
git diff --name-only origin/develop...HEAD \
| grep "^web/modules/custom/<nombre>/" \
| grep -E '\.(php|module|inc|install|profile|theme|yml|twig)$'
El segundo grep es importante: sin él recibirás .css, .md o imágenes que PHPStan rechaza con "no PHP files found". Para PHPStan específicamente, restringe aún más a \.(php|module|inc|install|profile|theme)$ (sin yml/twig).
Si el resultado está vacío o estás en develop → ver references/edge-cases.md, sección "Modo diff".
Identificación del módulo
| Lo que dice el usuario | Acción |
|---|---|
Nombre exacto (chat_soporte_tecnico_ia) |
Glob: "**/web/modules/custom/<nombre>/*.info.yml" |
Ruta (web/modules/custom/foo) |
Validar que existe <ruta>/<basename>.info.yml |
| Sin especificar | Glob: "**/web/modules/custom/*/*.info.yml". Si hay 1 → usar; si >1 → listar y preguntar; si 0 → parar |
Entorno de ejecución
ddev describe(silencioso) → si OK, todo dentro de DDEV conddev exec.- Si no hay DDEV → buscar
vendor/bin/phpstandirecto. - Si nada → preguntar al usuario qué entorno usa.
Path en contenedor DDEV: verifica con ddev exec "ls /var/www/html". Suele ser /var/www/html/drupal o /var/www/html según el docroot del .ddev/config.yaml.
Instalación de herramientas
Si vendor/bin/phpstan no existe:
ddev composer require --dev phpstan/phpstan mglaman/phpstan-drupal phpstan/phpstan-deprecation-rules
Pedir confirmación antes de instalar. PHPCS suele venir con drupal/coder (verificar con ddev exec "vendor/bin/phpcs -i" | grep -i drupal).
Configuración PHPStan
Crea phpstan.lint-review.neon en la raíz del proyecto Drupal (no en el módulo):
parameters:
level: 5
paths:
- web/modules/custom/<nombre>
excludePaths:
- web/modules/custom/<nombre>/js/vendor/*
- web/modules/custom/<nombre>/tests/fixtures/*
reportUnmatchedIgnoredErrors: false
includes:
- vendor/mglaman/phpstan-drupal/extension.neon
- vendor/mglaman/phpstan-drupal/rules.neon
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
No uses drupal_root (deprecated en phpstan-drupal 2.x — ver edge-cases).
Ejecución en paralelo
Crítico: lanza las 4 fuentes en el MISMO mensaje (mismo bloque de tool calls). Sin paralelización pierdes el principal valor de la skill.
Modo completo
# PHPStan — usa el bloque paths: del .neon
ddev exec "cd /var/www/html/drupal && vendor/bin/phpstan analyse -c phpstan.lint-review.neon --no-progress --error-format=raw"
# PHPCS — apunta al directorio del módulo. Restringido a archivos PHP con --extensions.
# ⚠️ NUNCA incluir `js` en --extensions: el standard Drupal aplica reglas PHP al JS
# y phpcbf puede convertir null/true/false → NULL/TRUE/FALSE, rompiendo el JS en runtime.
# Los archivos JS se analizan con ESLint/prettier, no con PHPCS (ver edge-cases.md).
ddev exec "cd /var/www/html/drupal && vendor/bin/phpcs --standard=Drupal,DrupalPractice --report=full --extensions=php,module,inc,install,profile,theme --ignore='*/vendor/*,*/js/*' web/modules/custom/<nombre>"
Modo diff
Tras obtener la lista de archivos cambiados (ver sección "Modo diff"), pásalos como argumentos posicionales — sobreescriben el bloque paths: del .neon:
# PHPStan — solo archivos PHP cambiados
ddev exec "cd /var/www/html/drupal && vendor/bin/phpstan analyse -c phpstan.lint-review.neon --no-progress --error-format=raw \
web/modules/custom/<nombre>/src/Foo.php \
web/modules/custom/<nombre>/src/Bar.php"
# PHPCS — filtra archivos PHP y YAML (no JS) antes de pasarlos como positional args.
# Pasa SOLO archivos cuya extensión esté en --extensions; si pasas un .js posicional,
# phpcbf lo procesa igualmente aunque no esté en --extensions, rompiendo el JS.
ddev exec "cd /var/www/html/drupal && vendor/bin/phpcs --standard=Drupal,DrupalPractice --report=full --extensions=php,module,inc,install,profile,theme --ignore='*/vendor/*' \
web/modules/custom/<nombre>/src/Foo.php \
web/modules/custom/<nombre>/src/Bar.php \
web/modules/custom/<nombre>/<modulo>.routing.yml"
Nota sobre
phpcbf: PHPCS a menudo reporta "PHPCBF CAN FIX N OF THESE SNIFF VIOLATIONS AUTOMATICALLY". Si el número es alto (>50% de los ERRORS de PHP, no cuentes los de JS), merece la pena ofrecerle al usuariophpcbfcomo acción rápida tras el informe (ver "Después del informe"). Los JS NUNCA deben ir a phpcbf — ver el edge case "phpcbf rompe JavaScript" enreferences/edge-cases.md.
Agentes (en el mismo mensaje que los dos comandos anteriores)
- Agent
drupal-qa— prompt literal dereferences/prompts-agentes.md, sección "Prompt paradrupal-qa". - Agent
drupal-security— prompt literal de la misma referencia, sección "Prompt paradrupal-security".
En modo diff, pasa la lista de archivos a los agentes con la ruta completa relativa al repo (web/modules/custom/<nombre>/src/Foo.php), no la subruta del módulo. Los agentes hacen Read sobre esas rutas.
Consolidación del informe
Sigue la plantilla literal de references/plantilla-informe.md. La estructura es fija: cabecera, resumen ejecutivo, una sección por fuente (PHPStan/PHPCS/QA/Security), acciones priorizadas P0/P1/P2, cobertura buenas prácticas, comandos de verificación.
Reglas críticas (todas detalladas en la plantilla):
- Severidades fijas: 🔴 ERROR/CRÍTICO, 🟠 ALTO, 🟡 MEDIO/WARNING, 🟢 BAJO, ℹ️ INFO.
archivo:líneasiempre clickable, ruta relativa al proyecto.- Top 5 bloqueantes con ID corto reusable (
SEC-ALTO-1,QA-ROUTING, etc.). - P0 deben ser accionables — "añadir
_csrf_request_header_tokenen las 9 rutas POST", no "mejorar la seguridad". - Veredicto categórico al final del resumen ejecutivo.
Ubicación del informe
Paso 1 — IDE por env var (PRIORITARIO). Ejecuta printenv CLAUDE_CODE_ENTRYPOINT:
CLAUDE_CODE_ENTRYPOINT |
Carpeta |
|---|---|
claude-antigravity |
.antigravity/Lint reviews/ |
claude-cursor |
.cursor/Lint reviews/ |
claude-vscode |
.vscode/Lint reviews/ |
otros (cli, vacío) |
continuar al Paso 2 |
Paso 2 — fallback por existencia: .antigravity/ > .cursor/ > .vscode/ > docs/lint-reviews/.
Nombre: lint-review-<nombre-modulo>-<modo>-<rama>.md. Sobrescribir si existe (es la versión más reciente). NUNCA caigas a detección por carpeta cuando el env var es claro — eso causa el bug de elegir .cursor/ solo porque sobrevive de un uso anterior del IDE.
Después del informe
- Resumen 3-5 líneas en chat: total hallazgos, top 3 bloqueantes, veredicto.
- Link clickable al informe (ruta relativa).
- Pregunta al usuario qué hacer (no asumas). Las opciones dependen de lo que encontraste:
- "arregla todo" → delegar a
drupal-backendcon la lista P0 estructurada (archivo:línea + acción) - "solo crítico" → solo HIGH/CRITICAL de seguridad
- "auto-fix PHPCS" → ofrece esta opción SOLO si PHPCS reportó que phpcbf puede arreglar una cantidad significativa (>50% de los ERRORS de PHP, excluyendo los de JS). Ejecuta:
ddev exec "cd /var/www/html/drupal && vendor/bin/phpcbf --standard=Drupal,DrupalPractice --extensions=php,module,inc,install,profile,theme --ignore='*/vendor/*,*/js/*' web/modules/custom/<nombre>". OBLIGATORIO el flag--extensionspara excluir.js— sin él, phpcbf conviertenull/true/false→NULL/TRUE/FALSEen JavaScript y rompe el código en runtime (ver edge-cases.md). Avisa al usuario de que phpcbf modifica archivos in-place y pídele que revise el diff antes de commitear. - "déjalo así" → cerrar
- "arregla todo" → delegar a
- Recordar: tras fixes en
routing.ymloservices.yml→drush crobligatorio + tests del módulo + re-ejecutar la skill para verificar.
NEVER (lecciones aprendidas a las malas)
Estas son las trampas que he visto romper la skill en sesiones reales. Cada una incluye el porqué, no solo la regla.
- NUNCA modifiques archivos del módulo durante la skill. Solo reportas. Por qué: los fixes son una fase posterior con confirmación explícita del usuario; mezclar análisis y fix dificulta auditar qué cambió.
- NUNCA ejecutes las 4 fuentes en mensajes separados. Por qué: la skill tarda ~4x más y pierdes el principal valor de tener herramientas + agentes corriendo en paralelo. Si tu cliente no soporta tool calls paralelas, dilo en voz alta antes de empezar para que el usuario lo sepa.
- NUNCA parafrasees los prompts de los agentes. Cópialos literales desde
prompts-agentes.md. Por qué: sin la checklist explícita los agentes devuelven reviews superficiales (ver el docu del propio prompts-agentes.md). - NUNCA marques el veredicto como "APTO" con hallazgos ALTO/CRÍTICO sin resolver. Por qué: el equipo lee solo el veredicto cuando va con prisa; un APTO falso bloquea la cultura de auditar.
- NUNCA listes
Unsafe usage of new static()en Controllers como bloqueante. Por qué: es falso positivo conocido de phpstan-drupal con el patrón estándar de Drupal (ver edge-cases). - NUNCA elimines aliases FQCN en
services.ymlsin verificar la Forma A vs Forma B. Por qué: la Forma A (alias real con'@servicio') es necesaria para el autowiring del Hook OOP. Eliminarla rompedrush cr. Ver edge-cases. - NUNCA asumas que los tests funcionales pasan solo porque PHPUnit no falla. Por qué: si PHPStan reporta métodos inexistentes (
getClient(),post()sobre interfaces) en el directoriotests/, el test depende del driver actual y romperá silenciosamente en CI cuando cambie. Reportarlo como bloqueante. - NUNCA escribas el informe en inglés. Código, comandos y nombres de clase en inglés; explicaciones en español. Por qué: el equipo trabaja en español y los informes mezclados son ruido.
- NUNCA ejecutes
phpcbfsobre archivos JavaScript (ni pasándolos como argumento ni dejando que el standard Drupal los incluya). Por qué: el standard Drupal de PHPCS aplica la reglaDrupal.Semantics.ConstantNamea cualquier archivo que pilla, incluyendo.js. Phpcbf conviertenull/true/false→NULL/TRUE/FALSEen JavaScript, lo que rompe el código en runtime conReferenceError. Usa siempre--extensions=php,module,inc,install,profile,themey--ignore='*/js/*'al llamar a phpcbf (y a phpcs por consistencia). Los JS se analizan/arreglan con ESLint, no con PHPCS. Ver el edge case completo enreferences/edge-cases.md.
Checklist de auto-verificación (antes de entregar)
Verifica cada item leyendo el informe que has generado. Si algo falta, vuelve atrás antes de entregárselo al usuario.
- Primera línea del informe es exactamente
Español confirmado. - El informe está en
<carpeta-IDE>/Lint reviews/lint-review-<nombre>-<modo>-<rama>.md(verifica conls) - Las 4 fuentes aparecen en el informe (PHPStan, PHPCS, drupal-qa, drupal-security). Si alguna no se ejecutó, debe estar marcada como
❌ no ejecutada — <razón>, no omitida silenciosamente. - Cada hallazgo tiene
archivo:líneacon ruta relativa al proyecto (no rutas absolutas del contenedor DDEV). - Sección "P0 bloqueantes" con acciones concretas. Si una P0 dice "mejorar X", reescríbela hasta que diga "añadir/eliminar/cambiar Y en
archivo:línea". - Tabla de resumen ejecutivo con conteos por fuente y total.
- Veredicto explícito al final del resumen (
APTO,APTO con correcciones menores,APTO con correcciones críticas,NO APTO). Nada de "depende". - Si hay hallazgos ALTO/CRÍTICO sin resolver, el veredicto NO es "APTO".
- Sección "Comandos de verificación" al final, con los comandos reales que se usaron (no genéricos).
- El módulo no ha sido modificado:
git statussobre la carpeta del módulo no muestra cambios atribuibles a esta skill. - La última línea de tu mensaje en chat es una pregunta al usuario (
arregla todo/solo crítico/déjalo así), no un asume "ahora arreglo todo".
Recovery — qué hacer si algo falla
| Síntoma | Acción |
|---|---|
references/*.md no existe |
Avisar al usuario, no inventar plantillas |
| DDEV no levantado | Pedir al usuario antes de ddev start |
| PHPStan/PHPCS no instalados | Pedir confirmación para instalar (ddev composer require --dev ...) |
Agentes drupal-qa o drupal-security no disponibles |
Continuar con las otras fuentes (PHPStan + PHPCS) y pedir al usuario que confirme si quiere review manual del modelo (más lento, menos rigor) |
| Una de las 4 fuentes falla en runtime | Continuar con las otras 3, marcar la fallida en el informe |
| No se puede crear la carpeta del IDE | Crear con mkdir -p; si falla, usar docs/lint-reviews/ |
| Modo diff sin cambios en el módulo | Ofrecer cambiar a completo |
Estás en develop (no hay rama feature) |
Abortar con mensaje claro |
| Cliente no soporta tool calls paralelas | Avisar al usuario al inicio: la skill será 4x más lenta, ¿continuar? |
| Síntoma no listado | Consulta references/edge-cases.md. Si tu síntoma no aparece, añádelo después de resolverlo |
Relación con skills hermanas
codex-diff-develop= revisión de lógica de negocio Codex sobre el diff (los 18 puntos del framework). Esta skill = lint estático (tipos, estándares, seguridad) sobre módulo o diff.codex-pr-review= revisión arquitectónica de PR completo, opinión humana. Esta skill = nivel inferior, herramientas automatizadas + agentes especializados.- Las tres son complementarias. Workflow ideal pre-merge:
lint-drupal-module(esta skill) → fixes mecánicoscodex-diff-develop→ fixes de lógicacodex-pr-review→ revisión final antes de mergear
More from j4rk0r/claude-skills
skill-advisor
Pre-execution assistant that builds a full execution plan with installed skills (✅) AND uninstalled gaps (❌) the task needs, then offers to install missing skills one by one. Use BEFORE starting any multi-step task. Triggers: 'recommend skills', 'what skill should I use', 'advise', 'suggest', 'help me with', or any work instruction involving code, design, planning, debugging, docs, testing, commits, PRs, strategy.
9skill-guard
Security auditor for Claude Code skills. Analyzes skills BEFORE installation using a 9-layer threat detection engine (permissions, static patterns, LLM semantic analysis, bundled scripts, data flow, MCP abuse, supply chain, reputation, anti-evasion) with scoring 0-100 and community audit registry. MUST be used whenever the user is about to install a skill — via npx skills add, /find-skills recommendation, /skill-advisor suggestion, or manual request. Also use when user says 'is this skill safe', 'audit this skill', 'check this skill', 'security scan', 'review before installing', or any mention of skill safety/trust/security. Intercept ALL skill installations proactively.
8skill-learner
>
6milestone
Persistent development milestone tracker with full context across conversations. Use when: tracking multi-session features, resuming work from a previous conversation, asking 'what's left to do on X' or 'what's pending', breaking work into trackable subtasks, planning complex implementations, updating progress after coding, checking project status, completing a subtask with QA validation, auditing what's missing in the project, syncing milestones with actual code state, or closing/archiving a finished milestone. Also trigger when user references a milestone by name, says 'what did we do last time', 'resume where we left off', 'how far along is X', 'mark this as done', 'milestone done', 'close this milestone', 'what's missing', 'audit the project', 'sync milestones', or wants to plan a feature with subtasks. Commands: /milestone, /milestone <name>, /milestone init, /milestone sync, /milestone start, /milestone done, /milestone update.
5usage-tracker
Track and report local Claude Code usage per request: tokens consumed, estimated cost in €, sessions, projects, and tool breakdown. Use when the user asks about consumption, credits, usage, cost per request, wants to see a report, asks why a specific request was expensive, suspects a process is consuming tokens, wants to optimize their Claude Code usage, or wants to audit tool usage by request. Also triggers on Spanish phrases: 'cuánto me está costando', 'cuántos tokens', 'consumo de hoy', 'qué petición fue cara', 'está consumiendo mucho', 'optimizar consumo', 'reporte de uso', 'ver uso', 'instalar tracker', 'hook no registra'. Commands: /usage-tracker report [hoy|semana|mes|all] [proyecto], /usage-tracker top-requests [hoy|semana], /usage-tracker install, /usage-tracker status
5codex-pr-review
Revisa pull requests en proyectos Drupal 11 (u otro) siguiendo la metodología Codex (lógica de negocio, edge cases de hooks/queries, seguridad, performance, completitud). Genera un informe .md en la carpeta del IDE detectado (.antigravity/, .cursor/, .vscode/ o docs/) con hallazgos por severidad y soluciones accionables. Usar cuando el usuario pida "revisión Codex", "revisión de PR", "revisar PR", "revisar PR #N", "revisión tipo Codex" o indique un número de PR con ramas (ej. develop ← feature/alejandro). Triggers: revisión PR, revisar PR, codex PR, revisión Codex, lint PR.
4