PR Guard
Una CLI open source que dice cuántas personas deben revisar un pull request, con un modelo pequeño en el runner de tu CI.
pr-guard lee el diff y la descripción de un pull request, le hace al modelo
TS-PRGuard cinco preguntas sobre él, suma comprobaciones deterministas
(secretos, SQL destructivo, rutas sensibles, tamaño) y deja que una política en YAML decida: ningún revisor, uno o dos,
o bloqueado. Comenta en el pull request, le pone etiquetas y define un status pr-guard, en GitHub, GitLab o
Bitbucket.
Es open source (Apache-2.0): typestrict-lab/pr-guard. TS-PRGuard es un
modelo entrenado en typestrict.ai (150M de parámetros, un archivo ONNX de 8 bits de 165 MB, también Apache-2.0). En un
runner ubuntu-latest estándar, una comprobación tardó de 11 a 71 segundos y usó de 460 MB a 1,9 GB de memoria en pull
requests de 48 a 1.937 líneas cambiadas. La memoria deja de crecer cuando el diff llena lo que lee el modelo (5.000
caracteres por pregunta, 14.000 para breaking change).
Cero revisores no es un merge: la política no pide aprobación humana adicional. pr-guard comenta, pone labels y fija un
status, y nunca hace merge; auto_merge: true solo añade el label pr-guard:auto-merge para tu propia automatización.
Inicio rápido
# .github/workflows/pr-guard.yml
on: pull_request
permissions:
contents: read
pull-requests: write # el comentario y las etiquetas
statuses: write # el status pr-guard
jobs:
pr-guard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: typestrict-lab/pr-guard@v1@v1 es la versión major de la action; el binario que instala es v0.1.0. La action instala un binario publicado, guarda el modelo en caché y ejecuta pr-guard check con el token del workflow.
fetch-depth: 0 trae el historial, para que exista la base común con la rama de destino.
En tu portátil:
curl -fsSL https://raw.githubusercontent.com/typestrict-lab/pr-guard/main/install.sh | sh
pr-guard check # esta rama contra su base común
pr-guard check --staged --no-model # los cambios en stage, solo las reglas, al instanteShadow y enforce
Empieza en modo shadow: comenta en cada pull request, el status siempre pasa y dice lo que pediría. Cuando sus
respuestas te parezcan correctas en tu código, escribe mode: enforce en .github/pr-guard.yml y haz de pr-guard un
status obligatorio. En modo enforce el status falla cuando la política bloquea, y espera hasta que el pull request tenga
las aprobaciones que pide el veredicto.
Las preguntas y la política por defecto
El modelo responde cada pregunta con la probabilidad de cada respuesta, en una sola pasada en la CPU. Macro-F1 en ejemplos apartados del entrenamiento, según la ficha del modelo:
| Se le pregunta al modelo | TS-PRGuard | Jev | Por defecto en la política |
|---|---|---|---|
| ¿Hace lo que dice la descripción? | 0,928 | 0,807 | avisa por encima del 40% de que no, bloquea por encima del 70% |
| ¿Qué tan grande es para revisar? | 0,660 | 0,383 | avisa cuando es muy grande |
| ¿Rompe a quienes ya lo usan? | 0,870 | 0,910 | avisa por encima del 50% |
| ¿Los tests cubren el cambio? | 0,921 | 0,879 | avisa por encima del 50% de que no |
| ¿Introduce una vulnerabilidad? | 0,904 | 0,755 | avisa por encima del 70% |
Supera a Jev en 4 de 5 preguntas según el Cálculo de reembolso; en compatibilidad Jev va por delante.
Las respuestas pesan en una nota: 85% o más no necesita revisor, 60% o más necesita uno, por debajo dos. Un aviso pide al
menos un revisor, un bloqueo pide dos. El comentario muestra la cuenta de cada pull request. Todas las claves son
opcionales; pr-guard init imprime el valor por defecto completo, comentado:
mode: shadow # o enforce
model: pr-guard:1
reviewers: { none: 85%, one: 60% }
questions:
vulnerability: { weight: 3, warn: 70%, block: 90% }
rules:
secrets: block
sensitive_paths: { level: warn, paths: [infra/**, "**/auth/**"] }Cada clave se explica en docs/policy.md (en inglés).
Elegir el modelo
--model, si no $PR_GUARD_MODEL, si no model en la política:
| Valor | Qué es |
|---|---|
pr-guard:1 (por defecto) | TS-PRGuard v1 fijado: los archivos exactos con los que se probó esta versión de pr-guard, verificados por SHA-256. |
pr-guard:latest | El TS-PRGuard más reciente publicado en Hugging Face, antes de que una versión de pr-guard lo fije. |
hf:<owner>/<repo>[@<revision>] | Cualquier repositorio de Hugging Face con los mismos archivos, como tu propio modelo. $HF_TOKEN para uno privado. |
https://… | Una URL base que sirve decision_ai.json, tokenizer.json y onnx/model_8bit.onnx (una CDN o un espejo interno). |
| un directorio | Se usa tal cual. |
El modelo se descarga una vez, se verifica archivo por archivo contra su SHA-256 y se guarda en ~/.cache/pr-guard.
Tu propio modelo
TS-PRGuard aprendió de pull requests públicos. Para tener uno que aprenda de los tuyos, entrena un modelo en typestrict.ai con tus pull requests como datos (mira Entrenamientos) y apunta la política a él:
model: hf:tu-org/tu-modelo-de-prPublicar un modelo pone el paquete en un repositorio de Hugging Face con exactamente
los archivos que lee pr-guard. Para mantenerlo privado, descarga el paquete (typestrict pull <model>) y sírvelo desde
una URL tuya, o usa el directorio directamente.
Otros CI y hosts
La configuración completa de cada uno está en docs/ci.md y docs/hosts.md (en inglés):
- GitLab CI: un componente de CI/CD en los pipelines de merge request; los hallazgos van a Code Quality y al informe de tests.
- Bitbucket Pipelines: un pipe sobre la imagen Docker; el informe JUnit aparece en el pull request.
- CircleCI: un orb con
installycheck; pasa la rama de destino comobase. - Bitrise: un step que escribe el informe JUnit en la pestaña Tests.
- Jenkins: un ejemplo de Jenkinsfile que ejecuta la imagen Docker en los builds de pull request.
- pre-commit: un hook que ejecuta las reglas sobre los cambios en stage, sin el modelo.
- Cualquier otro: el script de instalación, Homebrew, Docker (
ghcr.io/typestrict-lab/pr-guard:0.1.0) o Cargo, y luegopr-guard check.
En GitLab necesita un GITLAB_TOKEN con el scope api, en Bitbucket un BITBUCKET_TOKEN; Bitbucket no tiene etiquetas.
Privacidad
Sin API, sin clave, sin telemetría. El modelo se ejecuta en el runner del CI, el código nunca sale de él, y las únicas llamadas que hace pr-guard son la descarga del modelo y el comentario, las etiquetas y el status en tu propio host. La action nunca ejecuta código del pull request: solo lee el diff que trajo el checkout.