Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ pip install -e ".[dev]"
pytest
```

## Map of the code

Everything lives under `src/becwright/` — [architecture.md](documentation/architecture.md)
has the full picture and the exact check flow; this is the one-paragraph version:

| Module | Owns |
|---|---|
| `cli.py` | argparse commands; each `_cmd_*` is one subcommand |
| `engine.py` | glob matching + running checks (subprocess per rule) |
| `rules.py` | the `Rule` model and validated loading of `.bec/rules.yaml` |
| `git.py` | repo root, staged files, staged snapshot, native hooks |
| `bundle.py` / `catalog.py` | export/import bundles; the packaged catalog |
| `report.py` | shared JSON payloads (`check --json`, `why --json`, MCP) |
| `checks/` | built-in checks (each one file, shared skeleton) |
| `becs/` | catalog bundles (`<id>.bec.yaml`) |

becwright is dogfooded: this repo's own [.bec/rules.yaml](.bec/rules.yaml)
gates every commit. After `pip install -e ".[dev]"`, run `becwright check --all`
here to see it police itself.

## Workflow

`main` is protected: changes land via pull request with CI green.
Expand Down
62 changes: 57 additions & 5 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Con becwright, el commit no llega a existir:
> **Velo vos mismo en 5 segundos** — sin configurar nada, sin git, sin tocar tu
> máquina:
> ```bash
> npx becwright demo # sin instalar · o: pipx run becwright demo
> npx becwright demo # sin instalar · o: uvx becwright demo · pipx run becwright demo
> ```

## Empezar
Expand All @@ -54,6 +54,10 @@ becwright init # detecta tu lenguaje, escribe .bec/rules.yaml, inst
Listo. A partir de ahora cada `git commit` corre los chequeos solo y frena un
commit que rompa una regla blocking. No volvés a llamar a becwright a mano.

> **¿Cuál instalación?** `npm install -g` para probarlo o para uso individual;
> `npm install --save-dev becwright` para un repo de equipo, así la versión
> queda fijada en `package.json` y el hook lo encuentra en `node_modules/.bin`.

- **¿Código existente con deuda?** `becwright init --baseline` arranca en
`warning` las reglas que *ya* tienen violaciones (no se frena nada legítimo) y
en `blocking` las limpias. Limpiá la deuda con el tiempo y graduá cada regla.
Expand All @@ -67,7 +71,7 @@ commit que rompa una regla blocking. No volvés a llamar a becwright a mano.

```bash
pnpm add -g becwright
pipx install becwright # o: pip install becwright
pipx install becwright # o: pip install becwright / uv tool install becwright
npm install --save-dev becwright # local al proyecto; el hook lo encuentra en node_modules/.bin
```

Expand All @@ -76,6 +80,26 @@ Por npm/pnpm **no hace falta Python** — viene un binario autónomo por platafo
cualquier otra plataforma, usá `pipx install becwright`.
</details>

### Sentilo frenar, en 90 segundos

La forma más rápida de confiar en un guardia es verlo frenarte una vez:

```bash
cd tu-proyecto && becwright init # reglas + hook, un comando

echo 'api_key = "AKIAIOSFODNN7EXAMPLE"' >> demo_leak.py
git add demo_leak.py && git commit -m "probar el guardia"
# BLOCK no-hardcoded-secrets (blocking)
# Why it matters: un secreto en el repo queda en la historia de git para siempre...
# >>> Commit BLOCKED: a blocking rule was broken.

git reset demo_leak.py && rm demo_leak.py # deshacer el experimento
git commit -m "..." # los commits normales pasan sin más
```

Ese ciclo — violar, ser frenado *con el porqué*, arreglar, commitear — es todo
lo que becwright hace, para siempre, automáticamente.

## Por qué un guardia, no un cartel

Un agente de IA escribe un módulo y deja una nota: *"esto nunca debe loguear
Expand Down Expand Up @@ -264,7 +288,29 @@ Cada check es un módulo que se invoca desde el campo `check`. Funcionan
buscando texto en tus archivos con un patrón — simples y predecibles a
propósito; el verdadero valor está en atar cada regla a su *por qué*. Para
análisis más profundo, apuntá una regla a cualquier herramienta que ya uses
(gitleaks, ruff, semgrep) como su check.
como su check — la regla lleva el *por qué*, la herramienta hace la detección:

```yaml
- id: no-secrets-gitleaks
intent: >
Ningún secreto puede commitearse, según el ruleset completo de gitleaks.
why_it_matters: >
Una credencial filtrada en la historia de git queda expuesta para siempre,
incluso después de un revert.
paths: ["**/*"]
check: "gitleaks detect --no-git --redact --exit-code 1"
severity: blocking

- id: python-passes-ruff
intent: "El código Python debe pasar el ruleset de ruff del equipo antes del commit."
why_it_matters: "Un lint consistente mantiene el review enfocado en la lógica, no en el estilo."
paths: ["**/*.py"]
check: "xargs ruff check --force-exclude"
severity: warning
```

Más patrones listos (semgrep, eslint, rutas congeladas, límites de
arquitectura, CI): **[recetas](documentation/recipes.es.md)**.

| Check | Qué detecta | Lenguaje | Severidad sugerida |
|---|---|---|---|
Expand Down Expand Up @@ -351,6 +397,8 @@ La documentación completa vive en [`documentation/`](documentation/README.es.md

- **Recién empezás:** [uso](documentation/usage.es.md) — instalación, los
comandos, códigos de salida y cómo escribir una regla.
- **Reglas para copiar y pegar** (gitleaks/ruff/semgrep como checks, rutas
congeladas, límites de arquitectura, CI): [recetas](documentation/recipes.es.md).
- **Querés agregar tu propia regla:** [escribir checks](documentation/writing-checks.es.md).
- **Compartir reglas entre proyectos:** [portabilidad](documentation/portability.es.md).
- **Curiosidad por cómo funciona adentro:** [arquitectura y flujo](documentation/architecture.es.md).
Expand Down Expand Up @@ -404,8 +452,12 @@ de pre-commit — ver más arriba.
**¿Necesito Python?** No. `npm i -g becwright` instala un binario autónomo;
`pipx install becwright` también funciona.

**¿Funciona en Windows?** Sí, vía Git Bash (el hook es un script `sh`, que Git
para Windows provee). La CLI `becwright` en sí es multiplataforma.
**¿Funciona en Windows?** En beta. La CLI y el hook corren bajo Git Bash (que
Git para Windows provee), pero Windows todavía no se ejercita en CI — los
huecos conocidos están en
[#31](https://github.com/DataDave-Dev/becwright/issues/31) y el soporte de
primera clase es el milestone v1.3. Hasta entonces, tratá Windows como
best-effort.

**¿Cómo ignoro una línea?** Poné un comentario `becwright: ignore` en ella.

Expand Down
61 changes: 56 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ With becwright, the commit never happens:
> **See it yourself in 5 seconds** — no setup, no git, nothing on your machine is
> touched:
> ```bash
> npx becwright demo # zero-install · or: pipx run becwright demo
> npx becwright demo # zero-install · or: uvx becwright demo · pipx run becwright demo
> ```

## Get started
Expand All @@ -53,6 +53,10 @@ becwright init # detects your language, writes .bec/rules.yaml, ins
That's it. From now on every `git commit` runs the checks by itself and stops a
commit that breaks a blocking rule. You never call becwright by hand again.

> **Which install?** `npm install -g` to try it out or for solo use;
> `npm install --save-dev becwright` for a team repo, so the version is pinned
> in `package.json` and the hook finds it in `node_modules/.bin`.

- **Existing codebase with debt?** `becwright init --baseline` starts
already-violated rules as `warning` (nothing legitimate is blocked) and clean
rules as `blocking`. Fix the debt over time, then graduate each rule.
Expand All @@ -66,7 +70,7 @@ commit that breaks a blocking rule. You never call becwright by hand again.

```bash
pnpm add -g becwright
pipx install becwright # or: pip install becwright
pipx install becwright # or: pip install becwright / uv tool install becwright
npm install --save-dev becwright # project-local; the hook finds it in node_modules/.bin
```

Expand All @@ -75,6 +79,26 @@ platform (`linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64`, `win32-x64`)
On any other platform, use `pipx install becwright`.
</details>

### Feel it block, in 90 seconds

The fastest way to trust a guard is to watch it stop you once:

```bash
cd your-project && becwright init # rules + hook, one command

echo 'api_key = "AKIAIOSFODNN7EXAMPLE"' >> demo_leak.py
git add demo_leak.py && git commit -m "test the guard"
# BLOCK no-hardcoded-secrets (blocking)
# Why it matters: a secret in the repo stays in git history forever...
# >>> Commit BLOCKED: a blocking rule was broken.

git reset demo_leak.py && rm demo_leak.py # undo the experiment
git commit -m "..." # normal commits just pass
```

That loop — violate, get blocked *with the why*, fix, commit — is everything
becwright does, forever, automatically.

## Why a guard, not a sign

An AI agent writes a module and notes *"this must never log session tokens."*
Expand Down Expand Up @@ -256,7 +280,29 @@ constraint, not the whole style guide re-read into context.
Each check is a module invoked from the `check` field. They work by searching
the text of your files for a pattern — simple and predictable on purpose; the
real value is in tying each rule to its *why*. For deeper analysis, point a
rule at any tool you already trust (gitleaks, ruff, semgrep) as its check.
rule at any tool you already trust as its check — the rule carries the *why*,
the tool does the detection:

```yaml
- id: no-secrets-gitleaks
intent: >
No secret may ever be committed, as judged by gitleaks' full ruleset.
why_it_matters: >
A leaked credential in git history is exposed forever, even after a revert.
paths: ["**/*"]
check: "gitleaks detect --no-git --redact --exit-code 1"
severity: blocking

- id: python-passes-ruff
intent: "Python code must pass the team's ruff ruleset before commit."
why_it_matters: "Consistent lint keeps review focused on logic, not style."
paths: ["**/*.py"]
check: "xargs ruff check --force-exclude"
severity: warning
```

More ready-made patterns (semgrep, eslint, frozen paths, architecture
boundaries, CI): **[recipes](documentation/recipes.md)**.

| Check | What it detects | Language | Suggested severity |
|---|---|---|---|
Expand Down Expand Up @@ -342,6 +388,8 @@ Full docs live in [`documentation/`](documentation/):

- **Just getting started:** [usage](documentation/usage.md) — install, the
commands, exit codes, and how to write a rule.
- **Copy-paste rules for common jobs** (gitleaks/ruff/semgrep as checks, frozen
paths, architecture boundaries, CI): [recipes](documentation/recipes.md).
- **Want to add your own rule:** [writing checks](documentation/writing-checks.md).
- **Sharing rules between projects:** [portability](documentation/portability.md).
- **Curious how it works inside:** [architecture & flow](documentation/architecture.md).
Expand Down Expand Up @@ -393,8 +441,11 @@ rule that carries its *why* and travels between repos. You can even run becwrigh
**Do I need Python?** No. `npm i -g becwright` installs a self-contained binary;
`pipx install becwright` also works.

**Does it work on Windows?** Yes, via Git Bash (the git hook is a `sh` script,
which Git for Windows provides). The `becwright` CLI itself is cross-platform.
**Does it work on Windows?** In beta. The CLI and hook run under Git Bash
(which Git for Windows provides), but Windows is not yet exercised in CI —
known gaps are tracked in
[#31](https://github.com/DataDave-Dev/becwright/issues/31) and first-class
support is the v1.3 milestone. Until then, treat Windows as best-effort.

**How do I ignore a single line?** Add a `becwright: ignore` comment on it.

Expand Down
1 change: 1 addition & 0 deletions documentation/README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ lenguaje simple y después profundiza, así que podés parar donde deje de serte
**Empezá acá**

- [Uso](usage.es.md) — instalación, comandos y cómo escribir una regla. Leé esto primero.
- [Recetas](recipes.es.md) — reglas para copiar y pegar: gitleaks/ruff/semgrep como checks, rutas congeladas, límites de arquitectura, CI, Husky.
- [Escribir checks](writing-checks.es.md) — el atajo sin código `forbid` y luego checks propios en cualquier lenguaje.
- [Portabilidad](portability.es.md) — compartir una regla entre proyectos con export/import.

Expand Down
1 change: 1 addition & 0 deletions documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ prior background assumed.
**Start here**

- [Usage](usage.md) — install, the commands, and how to write a rule. Read this first.
- [Recipes](recipes.md) — copy-paste rules for common jobs: gitleaks/ruff/semgrep as checks, frozen paths, architecture boundaries, CI, Husky.
- [Writing checks](writing-checks.md) — the no-code `forbid` shortcut, then custom checks in any language.
- [Portability](portability.md) — share a rule between projects with export/import.

Expand Down
Loading
Loading