Documentación / Calidad y gobierno
Contrato de calidad
Las reglas de calidad viven en un archivo versionado del repositorio, no en el prompt, y valen igual para personas y agentes.
El contrato de calidad es el archivo .ai/contract.json de tu proyecto. Define cuánto rigor exige el equipo: umbrales de medición, cobertura, complejidad, tamaño de los cambios, rutas protegidas y excepciones.
Lo aplican el gate del motor, los hooks de Git, la CI y los agentes. El resultado no depende de quién escriba el código: una persona, Yuli, Claude Code, Codex, Kiro o Antigravity.
Si el archivo no existe o no es válido, Yuli usa los valores por defecto (criticidad Negocio). Cada campo es opcional, así que un contrato parcial también funciona.
Dónde se edita
Abre el Centro de Gobierno (riel derecho → Más herramientas, o la paleta de comandos con Abrir el Centro de Gobierno) y entra en la pestaña Contrato.
Al guardar con Guardar y firmar, Yuli registra el cambio con tu git config user.name. Puedes ver todos los cambios en Historial del contrato.
Criticidad
La criticidad elige un perfil completo de umbrales. Hay cuatro niveles:
| Valor en el archivo | Etiqueta en Yuli | Cuándo usarlo |
|---|---|---|
low |
Baja | Prototipos, herramientas internas, experimentos. |
business |
Negocio | Aplicaciones de negocio. Es el valor por defecto. |
regulated |
Regulada | Sistemas sujetos a auditoría o regulación. |
safety |
Seguridad crítica | Software donde un fallo tiene consecuencias graves. |
Perfiles
| Umbral | Baja | Negocio | Regulada | Seguridad crítica |
|---|---|---|---|---|
| Puntaje de aceptación | 80 | 90 | 92 | 95 |
| Rondas de medición | 2 | 3 | 4 | 5 |
| Cobertura mínima | 50 % | 70 % | 80 % | 90 % |
| Complejidad cognitiva máx. | 20 | 15 | 15 | 10 |
| Complejidad ciclomática máx. | 15 | 10 | 10 | 8 |
| Mutación mínima | 0 % | 0 % | 60 % | 75 % |
| Archivos por cambio | 60 | 40 | 25 | 15 |
| Líneas por cambio | 2000 | 1000 | 600 | 400 |
| Revisión independiente | No | No | Sí | Sí |
| Bloquear trampas en tests | No | Sí | Sí | Sí |
| Aplicación estricta | No | No | Sí | Sí |
Puedes reemplazar un umbral concreto en gates. Solo cambia ese campo; el resto sigue saliendo del perfil. Bloquear trampas en tests y Aplicación estricta dependen solo de la criticidad y no se pueden reemplazar.
El puntaje de aceptación y las rondas del contrato reemplazan los ajustes locales de la fase de Medición.
Estructura del archivo
{
"schemaVersion": 1,
"criticality": "business",
"gates": { "minCoverage": 75, "maxCyclomatic": null },
"changeLimits": { "maxFiles": 40, "maxLines": 1000 },
"protectedPaths": ["db/migrations/**"],
"waivers": []
}
| Campo | Qué define |
|---|---|
criticality |
low, business, regulated o safety. |
gates |
acceptanceScore, maxMeasureRounds, minCoverage, maxCognitive, maxCyclomatic, requireIndependentReview, minMutationScore. null toma el valor del perfil. |
changeLimits |
maxFiles y maxLines por cambio. |
protectedPaths |
Globs extra, que se suman a los protegidos por defecto. |
waivers |
Excepciones con vencimiento. |
architecture |
Capas (layers con name, paths, mayDependOn) y forbidCycles. |
slos |
Objetivos de servicio: latencyP95Ms, availability o errorRate. |
licensePolicy |
Licencias permitidas (allow) y prohibidas (deny), por SPDX o por familia, como strong-copyleft. |
reviewer |
Revisor independiente: requireOtherFamily, provider, model. |
dataClassification |
Patrones de datos con su nivel: public, internal, confidential o restricted. |
finops |
Presupuesto mensual por servicio y su responsable. |
Límites de cambio
El tamaño de un cambio se mide con git diff --numstat. Los archivos de bloqueo (package-lock.json, yarn.lock, Cargo.lock, go.sum y similares) cuentan como archivos, pero sus líneas no.
Superar el límite bloquea con aplicación estricta (Regulada y Seguridad crítica). En los demás perfiles es un aviso.
Rutas protegidas
Un agente no puede editar estos archivos, aunque se lo pidan:
.ai/contract.json,.ai/quality.jsony.ai/state/**.claude/settings.jsony.claude/settings.local.json.githooks/**.github/workflows/**,.gitlab-ci.ymlyJenkinsfileCODEOWNERSy.github/CODEOWNERS
La comparación ignora mayúsculas. Agrega tus propias rutas en protectedPaths. Un cambio al contrato guardado desde Yuli queda en la auditoría y cuenta como aprobado.
Excepciones (waivers)
Una excepción permite saltar una regla de forma temporal y justificada.
| Campo | Contenido |
|---|---|
id |
Identificador de la excepción. |
rule |
Regla que se exceptúa: secrets, protectedPaths, testIntegrity, un tipo de trampa concreto o *. |
path |
Glob al que aplica. Vacío significa cualquier ruta. |
reason |
Motivo. |
approvedBy |
Quién la aprobó. |
expires |
Fecha de vencimiento, AAAA-MM-DD. |
ticket |
Referencia opcional. |
Una excepción vale hasta el día de expires, inclusive. Una fecha ausente o mal escrita cuenta como vencida. Al vencer, la regla vuelve a regir y el gate lo avisa.
En la interfaz cada excepción muestra su estado: Vigente, Vence pronto, Vencida o Fecha inválida.
testIntegrity exceptúa todas las detecciones de trampas en tests a la vez. Úsala con una ruta acotada y una fecha cercana.
Auditoría
Cada guardado agrega una línea a .ai/state/contract-audit.jsonl con la fecha, el autor, el hash SHA-256 y un resumen (por ejemplo, «criticality business→regulated; waivers +1»).
El autor es siempre una persona: el nombre indicado o tu git config user.name. «Yuli» y «Yuli Code» se rechazan como autores.
Siguiente paso
- Medición contra N−1: cómo se aplican el puntaje de aceptación y las rondas.
- Gate y Centro de gobierno: cómo se hace cumplir el contrato en cada commit.