becwright

Conceptos

Arquitectura

Cómo el motor matchea archivos, corre checks y decide si un commit puede proceder.

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 seguir.

El resto de esta página es para los curiosos y para quien escriba sus propios checks.

Componentes

MóduloResponsabilidad
cli.pyCLI con argparse: init / list / check / install / uninstall / export / import
rules.pyEl modelo Rule y la carga de .bec/rules.yaml
engine.pyMatching de rutas por glob, corre los checks, decide pasa/no-pasa
git.pyRaíz del repo, archivos en staging, el hook pre-commit nativo
checks/Checks incluidos (un módulo cada uno)
bundle.pyExport/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.

El flujo de chequeo

  1. Un commit dispara el hook pre-commit, que corre becwright check.
  2. becwright carga las reglas de .bec/rules.yaml.
  3. Le pide a git los archivos en staging.
  4. Por cada regla, filtra los archivos por los globs de paths y corre el comando check de la regla, pasándole los archivos que matchean por stdin.
  5. El código de salida del check decide el resultado: 0 pasa; no-cero falla.
  6. Si alguna regla blocking falló, el commit se rechaza (exit 1). Los avisos se imprimen pero nunca frenan.
git commit
   └─▸ hook pre-commit → becwright check
         ├─ carga .bec/rules.yaml en Rules
         ├─ obtiene los archivos en staging de git
         └─ por cada regla:
              ├─ matchea archivos contra rule.paths
              ├─ corre rule.check (archivos por stdin)
              └─ código de salida 0 .... PASS
                 código no-cero
                    ├─ blocking ......... BLOCK (commit rechazado, exit 1)
                    └─ warning .......... WARN  (commit permitido)

El contrato del check

El motor corre rule.check como comando de shell con cwd en 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 Escribir checks.

Por qué es determinista

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 Portabilidad.