Saltar al contenido principal

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> version para npm o mise 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:

  1. 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 paquete wiedii/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.
  2. 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).
  3. 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.

StackHerramientaMecanismo
JS/TS — lintESLintpaquete npm eslint-config-wiedii
JS/TS — formatoPrettierpaquete npm prettier-config-wiedii (spread para override)
CSS/SCSS/SassStylelintpaquete npm stylelint-config-wiedii (extiende …-standard-scss)
PHP — análisisPHPStanpaquete Composer (includes: en phpstan.neon)
PHP — formato/estiloPHP-CS-Fixer (Pint en Laravel)paquete Composer (ruleset base extendido)
PHP — refactor/upgradesRectorpaquete Composer (sets); deliberado, no pre-commit
Python — lint+formatoRuff (+ mypy)sembrado por repo; extend para capas locales
Go — formatogofmt / gofumptsin config (opinionado)
Go — lintgolangci-lint.golangci.yaml sembrado por repo
TOMLtaplo--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-standard de forma uniforme. Pint (Laravel) es solo un wrapper de conveniencia con su propia pint.json; no reutiliza el ruleset compartido igual, así que para consistencia entre frameworks se prefiere PHP-CS-Fixer directo incluso en Laravel.
  • Rectorrefactor 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: en phpstan.neon apuntando al .neon del paquete.
  • PHP-CS-Fixer: el .php-cs-fixer.php hace require del ruleset base y lo extiende (es código PHP: factory / array_merge).
  • Rector: el rector.php importa 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 mismo rector.php base 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 php directo dentro del contenedor (no mise 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-run en 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-run advisory.

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.jsonextends 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 --optionno 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.