Política de Linters y Formateadores por Stack
⚠️ Verificar versiones antes de usar — las versiones de paquetes (ESLint, ruff, PHPStan, etc.) pueden estar desactualizadas. Usar
bun info <paquete> versionpara npm omise ls-remote <herramienta>para herramientas. Ver politicas-core.
Distribución de configuraciones — tres mecanismos
Un linter revisa el código en busca de errores y malas prácticas; un formateador solo ordena el estilo (indentación, comillas, orden) sin cambiar lo que el código hace. Esta nota fija qué herramienta cumple cada rol en cada stack y cómo se comparten sus reglas entre repos.
La config (las reglas) de cada herramienta se comparte por el mecanismo nativo de esa herramienta. El lefthook de wiedii-configs solo orquesta (ejecuta la herramienta sobre los archivos staged); no contiene las reglas. Según lo que cada tool soporte:
- Paquete de config compartida del gestor del lenguaje (preferido): en npm para JS — ESLint (
eslint-config-wiedii), Prettier (prettier-config-wiedii), Stylelint (stylelint-config-wiedii); en Composer para PHP — PHPStan, PHP-CS-Fixer y Rector vía un paquetewiedii/coding-standard. Se publican al registry privado de Wiedii, cada repo los referencia en su archivo de config, y Renovate los mantiene. Una sola fuente de verdad; funcionan igual en IDE, CI y hook. - Config sembrada por repo (la genera la skill de
wiedii-dev): para tools sin sharing nativo entre repos — Ruff/mypy (Python) y golangci-lint (Go). - Opciones centralizadas en el hook (
--option): solo para tools sin config compartida — taplo (TOML). Último recurso (ver capas abajo).
Caso aparte: gofmt/gofumpt (formato Go) son opinionados, zero-config — no hay nada que compartir.
| Stack | Herramienta | Mecanismo |
|---|---|---|
| JS/TS — lint | ESLint | paquete npm eslint-config-wiedii |
| JS/TS — formato | Prettier | paquete npm prettier-config-wiedii (spread para override) |
| CSS/SCSS/Sass | Stylelint | paquete npm stylelint-config-wiedii (extiende …-standard-scss) |
| PHP — análisis | PHPStan | paquete Composer (includes: en phpstan.neon) |
| PHP — formato/estilo | PHP-CS-Fixer (Pint en Laravel) | paquete Composer (ruleset base extendido) |
| PHP — refactor/upgrades | Rector | paquete Composer (sets); deliberado, no pre-commit |
| Python — lint+formato | Ruff (+ mypy) | sembrado por repo; extend para capas locales |
| Go — formato | gofmt / gofumpt | sin config (opinionado) |
| Go — lint | golangci-lint | .golangci.yaml sembrado por repo |
| TOML | taplo | --option en el hook de lefthook |
JavaScript / TypeScript
Las reglas viven en paquetes de config compartida de Wiedii (no se copian inline): eslint-config-wiedii (lint) y prettier-config-wiedii (formato). Instalar:
bun add -d eslint prettier eslint-config-wiedii prettier-config-wiedii sort-package-json
eslint.config.mjs (flat config) — extiende la config compartida:
import wiedii from "eslint-config-wiedii";
export default [ ...wiedii /*, { rules: { /* overrides del proyecto */ } } */ ];
Prettier — referenciar el paquete compartido en package.json:
{ "prettier": "prettier-config-wiedii" }
Prettier no tiene extends nativo: para sobrescribir una opción, usar .prettierrc.js con spread:
module.exports = { ...require("prettier-config-wiedii"), printWidth: 100 };
TypeScript: siempre strict en tsconfig.json:
{ "compilerOptions": { "strict": true } }
Python
Instalar via mise (versión exacta — verificar en mise-versions.jdx.dev):
mise use ruff@<version> mypy@<version>
pyproject.toml o ruff.toml:
[tool.ruff]
line-length = 100
[tool.ruff.lint]
select = ["E", "F", "I", "N", "W"]
Go
Instalar via mise (versión exacta — verificar en mise-versions.jdx.dev):
mise use golangci-lint@<version>
.golangci.yaml:
linters:
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
PHP
Aplica a todo PHP de Wiedii — apps web y CLI de PHP puro, Symfony, Laravel, etc. Las tres herramientas son agnósticas al framework; los add-ons específicos de cada uno se añaden por proyecto (ver "Add-ons por framework"). Roles (no se solapan):
- PHPStan — análisis estático (bugs, tipos) en
level: max. No formatea. - PHP-CS-Fixer — formateador/fixer de estilo (PSR-12) + reglas risky. Es el estándar de formato en todos los stacks PHP (puro, Symfony, Laravel), porque consume el config compartido
wiedii/coding-standardde forma uniforme. Pint (Laravel) es solo un wrapper de conveniencia con su propiapint.json; no reutiliza el ruleset compartido igual, así que para consistencia entre frameworks se prefiere PHP-CS-Fixer directo incluso en Laravel. - Rector — refactor automatizado: moderniza y actualiza el código entre versiones de PHP (
LevelSetList::UP_TO_PHP_8x) y aplica sets de calidad (deadCode,codeQuality,typeDeclarations…). Es transformador (reescribe el código), no un linter pasivo.
PHP no se instala por mise. En Wiedii PHP se trabaja en un VS Code Dev Container (
php:8.3-fpm-alpine); PHP, Composer y estas herramientas viven dentro del contenedor, no en el host. Ver stack-tecnologico y docker.
Instalar las herramientas como devDependencies de Composer dentro del dev container:
composer require --dev phpstan/phpstan friendsofphp/php-cs-fixer rector/rector
Config compartida — vía paquete Composer (registry privado)
Igual que JS usa paquetes npm, PHP comparte la config con un paquete Composer de Wiedii (p. ej. wiedii/coding-standard), publicado al registry privado. Cada repo lo require --dev y lo referencia:
- PHPStan:
includes:enphpstan.neonapuntando al.neondel paquete. - PHP-CS-Fixer: el
.php-cs-fixer.phphacerequiredel ruleset base y lo extiende (es código PHP: factory /array_merge). - Rector: el
rector.phpimporta el set base del paquete (->withSets([...])/->import(...)).
# phpstan.neon
includes:
- vendor/wiedii/coding-standard/phpstan.neon
parameters:
level: max
paths: [src]
// .php-cs-fixer.php — extiende el ruleset base de Wiedii
<?php
return Wiedii\CodingStandard\PhpCsFixer::create()->in(__DIR__ . '/src');
// rector.php — set base Wiedii + target de versión PHP (leída de composer.json)
<?php
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withPaths([__DIR__ . '/src'])
->withSets([/* set base Wiedii */])
->withPhpSets();
Add-ons por framework (por proyecto)
El paquete wiedii/coding-standard es agnóstico (PHP puro + reglas de calidad). Cada proyecto añade lo de su framework encima de la base:
- PHP puro (web/CLI): solo la base, sin add-ons.
- Symfony:
phpstan/phpstan-symfony(extensión de PHPStan) +rector/rector-symfony(sets de Symfony). - Laravel:
larastan/larastan(PHPStan para Laravel) +rector/rector-laravel; Pint opcional para formato (con la salvedad de consistencia de arriba).
Rector puede auto-seleccionar los sets según los paquetes realmente instalados con
->withComposerBased()— útil cuando el mismorector.phpbase sirve a proyectos de distinto framework.
Cadencia — Rector es distinto
- PHP-CS-Fixer y PHPStan corren en pre-commit (sobre staged) y en CI — rápidos y deterministas. Como PHP vive en el dev container (no en mise), se invocan con
phpdirecto dentro del contenedor (nomise exec):php-cs-fixer: { priority: 1, glob: '*.php', run: 'php vendor/bin/php-cs-fixer fix {staged_files}', stage_fixed: true }phpstan: { priority: 2, glob: '*.php', run: 'php vendor/bin/phpstan analyse {staged_files} --no-progress' } - Rector NO va en pre-commit con sets de upgrade completos — puede reescribir mucho código de golpe. Se usa deliberadamente (campañas de subida de versión de PHP) o con
--dry-runen CI para detectar; se aplica (rector process), se revisa el diff y se commitea. En pre-commit, a lo sumo un set mínimo o--dry-runadvisory.
CSS / SCSS / Sass
Reglas en el paquete compartido stylelint-config-wiedii, que extiende stylelint-config-standard-scss (incluye la sintaxis postcss-scss y el plugin stylelint-scss).
bun add -d stylelint stylelint-config-wiedii
.stylelintrc.json — extends nativo + overrides del proyecto:
{ "extends": ["stylelint-config-wiedii"], "rules": {} }
TOML
Taplo formatea archivos .toml y se gestiona via mise. No tiene mecanismo extends ni soporte de config remota — la configuración es siempre local.
Estrategia Wiedii — dos capas
Capa 1 — hook centralizado en wiedii-configs/base.yaml (siempre activa):
El hook toml en base.yaml pasa las opciones directamente via --option. No requiere .taplo.toml en el proyecto — las opciones viven en un solo lugar y se propagan a todos los repos al hacer lefthook install:
toml:
priority: 1
glob: '*.toml'
run: mise exec -- taplo fmt --option align_entries=true --option indent_entries=true --option reorder_arrays=true --option reorder_keys=true {staged_files}
stage_fixed: true
Capa 2 — .taplo.toml por proyecto (opcional):
Solo necesario si el proyecto usa taplo fuera del hook: extensión de VS Code (formato al guardar), taplo fmt manual, o CI que invoca taplo directamente sin lefthook. El hook de Capa 1 en wiedii-configs/base.yaml ya pasa las opciones correctas via --option — no se necesita el archivo para que los commits funcionen.
# .taplo.toml — agregar solo si se usa taplo fuera del hook lefthook
[formatting]
align_entries = true
indent_entries = true
reorder_arrays = true
reorder_keys = true
Taplo lo descubre automáticamente desde el directorio de trabajo; los --option del hook sobreescriben cualquier opción divergente.
Shell / Docker
Gestionados via mise (shfmt, shellcheck, hadolint) — sin configuración adicional más allá de mise.toml. Para el estándar de estilo de Bash (Google Shell Style Guide) y la matriz de qué herramienta verifica cada regla, ver scripting-bash.