Una puerta de commit para proyectos TypeScript.
Es dueño de la invocación de ESLint, react-doctor, fallow y Stryker: qué herramienta corre, en qué orden, acotada a qué y con qué techo de recursos. El veredicto es su código de salida, propagado sin tocarlo.
$ dharness sync dharness 1.7.5 · sync · ~/projects/your-app js project repository root package manager yarn test runner vitest owned files .dharness/ ■ 11 steps · 5 applied · 3 delegated · 3 satisfied · 0 failed 6.76s ── Applied (5) ── ✓ 1/11 install what this project is missing 6.73s │ ➤ YN0013: │ 33 packages were added to the project. │ installed [email protected] ~ package.json ~ yarn.lock ✓ 2/11 write the files dharness owns 0.03s + .dharness/lefthook.yml + .dharness/fallow.jsonc + .dharness/eslint.config.mjs + .dharness/rules.json ✓ 3/11 point .fallowrc.json at the file dharness owns 0.00s ✓ 6/11 point eslint.config.js at the file dharness owns 0.00s ✓ 8/11 give the agent fallow’s own tools 0.00s ── Left to you (3) ── ! 9/11 wire the gate into git nothing answers: there is no lefthook config, no .husky/ and no lefthook binary. Choosing a hook manager is a decision this project has not made, and not a default dharness gets to pick. … steps 10, 11 and the satisfied three elided … ✓ 5 applied · 3 delegated · 3 satisfied · 0 failed exit 0 next wire the gate into gitUna falla detiene la ejecución y omite todas las etapas que vienen atrás, y en una puerta que corre en cada commit ese corte es la mayor parte del ahorro. Cada etapa de abajo lleva la mediana con la que se midió y lo que la explica.
--no-warn-ignored <staged files>Lint sobre la lista exacta del índice, resuelto localmente
Se ejecuta desde la versión que tu proyecto instaló, sobre la lista exacta del índice y con la configuración que dharness posee, que ya trae el preset que tu framework recomienda.
Corre en cuanto tu proyecto lo instala
--staged --no-dead-code --no-score --no-supply-chain -ySemántica de React, solo sobre el cambio en el índice
Acotado a lo que realmente se está confirmando, y es la única etapa aquí de la que eso es cierto. Su análisis se queda en tu máquina.
audit --changed-since HEAD --diff-stdinEl grafo del repositorio, juzgado por lo que el cambio introduce
El diff del índice se le entrega por stdin, así que el grafo se juzga sobre el cambio que estás por confirmar. Sale con 1 ante un veredicto de fallo y limita la puerta a los hallazgos nuevos.
Corre en cuanto el repositorio tiene un commit contra el cual comparar
dupesEl techo de duplicación, aplicado sobre todo el repositorio
El techo vive en la configuración que dharness posee, donde tu proyecto puede leerlo y sobrescribirlo.
Corre en cuanto el repositorio tiene un commit contra el cual comparar
Medianas de tres ejecuciones cada una, un proyecto de referencia y la misma lista explícita de archivos preparados para cada etapa. 12 de agosto de 2026.
Primera fallaexit 1fallow audit¿Qué introduce este cambio?
exit 0fallow dupes¿Cuánta duplicación carga el repositorio?
exit 1El código de salida es la respuesta, propagado sin tocarlo. Una etapa que falla nombra todas las que omitió, así que siempre se rinde cuenta de las cuatro.
$ dharness checkno staged source files, nothing to check $ echo $?0Toda la superficie cabe en esta pantalla.
$ dharness syncDeja el proyecto listo, y lo mantiene así
EscribeCada ejecución deriva su plan completo del repositorio tal como está ahora mismo, así que ejecutarlo meses después reporta la deriva.
--format <human|json> (default human)eslint --print-configUna ruta por cada extensión de fuente, hasta ocho. Un sync en verde es uno cuya configuración ya se cargó y se releyó.
| Lo que hace la ejecución | Lo que deja un fallo |
|---|---|
| Paquetes instalados, archivos escritos en .dharness/ | Se quita exactamente lo que agregó esta ejecución |
| El manifiesto y el lockfile editados | Ambos restaurados byte por byte |
$ dharness checkLa puerta de commit propiamente dicha
No escribe nadaSe detiene en la primera falla, nombra todas las etapas que omitió y te entrega la ayuda de esa misma herramienta, en la forma que usa tu proyecto. También nombra qué tipo de falla obtuvo: un código de salida 2 de ESLint es una configuración que nunca cargó, así que no se analizó ningún archivo y la respuesta está en la configuración.
$ dharness mutate <path...>Averigua si las pruebas de estos archivos notarían que el código se rompe
No escribe nadaUna ruta puede nombrar líneas en lugar del archivo entero, como `src/thing.ts:12-40`, y el veredicto cubre exactamente esas líneas. Ejecuta el Stryker que tu proyecto instaló, el único capaz de resolver tu propio TypeScript.
--dry-run--concurrency <n> (default 2)Cada herramienta calcula su paralelismo sobre la máquina entera, y más workers se midieron más lentos en un alcance pequeño.
--upgrade--freshLos resultados se acumulan en `.git/dharness/`, así que la tabla de Stryker puede cubrir más archivos de los que pediste. Esta bandera mide solo las rutas que nombraste.
$ dharness versionImprime la versión
No escribe nadaLas versiones las corta release-please a partir de los commits convencionales en main, así que el número que imprime nombra una versión etiquetada con una entrada de changelog detrás.
Cuatro herramientas que ya existen, cada una dueña de un diagnóstico propio.
¿Este archivo sigue las reglas que recomienda este stack?
| Framework | Preset |
|---|---|
| Next.js | eslint-config-next/core-web-vitals |
| Next.js, en cuanto existe un tsconfig.json | eslint-config-next/typescript |
| Expo | eslint-config-expo/flat.js |
La versión sale del framework que publica el preset. Tu `eslint.config.js` gana una sola línea de referencia, dentro de una región marcada que se reescribe en cada sync, apuntando a `.dharness/eslint.config.mjs` o `.cjs`, según tu proyecto.
Visitar la herramienta¿Cómo es el grafo de este repositorio?
| Importación | En sus fronteras |
|---|---|
| Una importación solo de tipos | Cruza la zona |
| Una importación de un paquete externo | No cuenta como cruce |
Imprime los entry points que resolvió y avisa cuando una zona no coincide con nada.
Visitar la herramienta¿Este código React es semánticamente correcto?
Llega al proyecto por dos caminos: la CLI en la puerta y `eslint-plugin-react-doctor` en la configuración que dharness posee, así que el mismo análisis responde mientras escribes y otra vez en el commit. La severidad de sus reglas solo acepta `error`, `warn` u `off`, y esa única restricción produjo el paquete complementario de abajo.
Visitar la herramienta¿Las pruebas notarían que el código se rompe?
El veredicto sale del reporte que escribe, así que el número que decide una ejecución es uno que puedes leer.
Visitar la herramientadharness-eslint-pluginEl tamaño, la documentación y la forma de las carpetas necesitan un número o una política contra la cual verificarse, y este paquete es donde un proyecto la declara.
dharness/max-file-linesUn archivo que pasa el techo que fijó este proyecto.dharness/require-jsdocUna declaración en el tope de un archivo sin nada que diga para qué sirve.dharness/require-variable-jsdocUna variable de nivel superior sin JSDoc inmediatamente encima.dharness/pure-index-barrelUn barrel que hace algo distinto de re-exportar.dharness/role-file-shapeUna declaración que el nombre del archivo de rol no prometía.dharness/folder-ownershipUna carpeta que parte un módulo en archivos de rol y no publica un index.dharness pregunta `git ls-files -- */index.ts */index.tsx` y escribe esta regla como `error` donde el árbol ya publica un barrel, y como `off` donde no.{
"schema": "dharness.rules/v1",
"maxFileLines": 500,
"roleSuffixes": [".types.ts", ".constants.ts", ".helpers.ts", ".schema.ts"]
}Los números viven en `.dharness/rules.json`, así que un proyecto puede diferir de otro sin publicar una versión nueva. Un archivo ausente o ilegible cae a los valores por defecto, y todas las demás reglas siguen corriendo.
dharness/max-file-linesmaxFileLinesdharness/folder-ownershiproleSuffixesUn único registro `plugins: { dharness: plugin }` en la configuración que dharness posee es todo el cableado, y pone las seis reglas en cualquier lugar donde ESLint ya se ejecute en ese proyecto. El paquete publica una entrada CommonJS y otra ESM, así que carga en cualquiera de los dos sistemas de módulos.
Un único binario estático para Linux, macOS y Windows, en amd64 y arm64.
$ go install github.com/Disble/dharness/cmd/dharness@latestLa CLI en sí: su código, sus versiones etiquetadas y la bitácora fechada.
Las seis reglas que ESLint carga desde la configuración que dharness posee, publicadas con una entrada CommonJS y otra ESM.
El motor de mutación en Go con el que este repositorio revisa sus propios cambios preparados.