English · Español
becwright es un motor chico que corre checks sobre tus archivos y decide si un commit puede proceder. Es agnóstico al lenguaje: nunca parsea tu código — filtra archivos por su ruta y corre un comando.
La versión en una frase: por cada regla, becwright elige los archivos a los que aplica y corre un programita (el "check"); si ese programa reporta un problema, una regla blocking frena el commit. Todo lo de abajo es esa misma idea en detalle — los componentes, el flujo exacto y el contrato que un check debe cumplir. El resto de esta página es para los curiosos y para quien escriba sus propios checks.
| Módulo | Responsabilidad |
|---|---|
cli.py |
CLI con argparse: init / list / check / check-msg / install / uninstall / export / import / add / search |
rules.py |
El modelo Rule (incl. severity, target) y la carga de .bec/rules.yaml |
engine.py |
Matching de rutas por glob, corre los checks (archivos o mensaje del commit), decide pasa/no-pasa |
git.py |
Raíz del repo, archivos en staging, los hooks pre-commit y commit-msg nativos |
checks/ |
Checks incluidos (un módulo cada uno) |
bundle.py |
Export/import de BECs (el .bec.yaml portable) |
El motor se distribuye como paquete instalado; el repo vigilado solo aporta su
propio .bec/rules.yaml. Ese desacople es lo que permite instalar becwright una
vez y usarlo en muchos repos.
flowchart TD
A[git commit] --> B["el hook pre-commit corre 'becwright check'"]
B --> C[carga .bec/rules.yaml en Rules]
C --> D[obtiene los archivos en staging de git]
D --> E{por cada regla}
E --> F[matchea archivos contra rule.paths]
F --> G["corre rule.check como comando de shell, archivos por stdin"]
G --> H{código de salida}
H -->|0| I[PASS]
H -->|no-cero| J{severidad}
J -->|blocking| K[BLOCK: commit rechazado, exit 1]
J -->|warning| L[WARN: commit permitido]
J -->|advisory| M[ADVISORY: best-effort, commit permitido]
- Un commit dispara el hook
pre-commit, que correbecwright check. - becwright carga las reglas de
.bec/rules.yaml. - Le pide a git los archivos en staging.
- Por cada regla con
target: files, filtra los archivos por los globs depathsy corre el comandocheckde la regla, pasándole los archivos que matchean por stdin. - El código de salida del check decide el resultado:
0pasa; no-cero falla. - Si alguna regla blocking falló, el commit se rechaza (exit 1). Los hallazgos
warningyadvisoryse imprimen pero nunca frenan (advisoryva etiquetado como best-effort, para checks no-deterministas como un revisor LLM).
Un hook commit-msg aparte corre becwright check-msg, que aplica las reglas con
target: commit-msg al mensaje del commit del mismo modo (el mensaje se le pasa al
check por stdin en vez de las rutas de archivos).
El motor corre rule.check como comando de shell desde la raíz del repo, y le
pasa las rutas relevantes (una por línea) por stdin — stdin es simplemente la
entrada estándar del programa, el canal por el que un comando lee. Un check:
- lee la lista de archivos por stdin,
- imprime las violaciones por stdout (se muestran bajo "Found in:"),
- sale 0 si todo está bien, no-cero si encontró una violación.
Como el contrato es solo "archivos por stdin, código de salida", un check se puede escribir en cualquier lenguaje. Ver writing-checks.es.md.
A diferencia de una nota en CLAUDE.md que le pide a un agente que se porte
bien, el check de una BEC corre sobre el código real en cada commit y devuelve
pasa/no-pasa sin importar quién o qué produjo el cambio. La regla lleva su
intención y su por qué (la parte "bound"), el check la vuelve ejecutable, y
un bundle la vuelve portable — ver portability.es.md.