Imported from Yosoyepa/write-check-trust (
AGENTS.md). Install upstream withnpx skills add Yosoyepa/write-check-trust. Copyright stays with the author.
Write, Check, Trust (WCT) Contract
These rules are provider-neutral. Commands and non-zero exit codes are authoritative.
Profile: strict. Run uv run wct gate --tier fast before handoff.
Arquitectura y dependencias
-
ARCH-001 — Respeta la Dependency Rule. Las capas, de más alto a más bajo nivel, son: entrypoints → adapters → application → domain. Una capa solo puede importar capas por debajo de ella.
domainno importa ninguna otra capa del proyecto. Verified by:G-ARCH. -
ARCH-002 — No importes frameworks, ORMs, clientes HTTP ni SDKs de nube dentro de
domain/niapplication/. La lista exacta está en governance/policy.yaml → architecture.forbidden_external. Verified by:G-ARCH, G-SAST-SEMGREP. -
ARCH-003 — Cero ciclos de importación entre módulos hermanos. Verified by:
G-ARCH-CYCLE. -
ARCH-004 — No filtres tipos de infraestructura por los límites de capa. Un caso de uso no retorna filas de ORM, respuestas HTTP, ni objetos de framework: retorna tipos del dominio. Verified by:
G-ARCH, G-SAST-SEMGREP, human. -
ARCH-005 — Define los puertos (interfaces) en la capa que los USA, no en la que los implementa. Un
Protocolque describe persistencia vive enapplication/, yadapters/lo implementa. Verified by:G-ARCH, G-ARCHMETRICS. -
ARCH-006 — Ningún paquete debe entrar en la Zona de Dolor (concreto y estable) ni en la Zona de Inutilidad (abstracto e inestable). Mide con
wct archmetrics. Verified by:G-ARCHMETRICS. -
ARCH-007 — Un símbolo cuenta como abstracción solo si es indirección real:
typing.Protocol,abc.ABCcon@abstractmethod,TypeVarcon bound, ofunctools.singledispatch. Declararlo en un archivo de configuración no cuenta. Verified by:G-ARCHMETRICS. -
ARCH-008 — Separa los módulos testeables de los ambientalmente inadecuados (abren GUIs, dependen de dispositivos, cuelgan bajo automatización). Maximiza el código testeable y minimiza esa frontera. Solo los módulos testeables participan en coverage, mutación, CRAP y DRY. Verified by:
G-ARCH, human. -
ARCH-009 — Toda dependencia usada debe estar declarada, y toda dependencia declarada debe usarse. Nada de imports transitivos. Verified by:
G-DEPS.
Tests y verificación
-
TEST-001 — Usa TDD: escribe primero un test enfocado que exprese el comportamiento observable pedido y que FALLARÍA ante una implementación plausiblemente incorrecta. Luego implementa el mínimo que lo hace pasar. Verified by:
G-MUT, G-COV-DIFF. -
TEST-002 — Cero mutantes sobrevivientes en el código que cambiaste. Un mutante que sobrevive es un cambio de comportamiento que ningún test detecta. Verified by:
G-MUT. -
TEST-003 — Las aserciones deben trazar al System Under Test. Un test cuya única aserción es
mock.assert_called_once_with(...), sin aserción alguna sobre el valor que retorna el SUT, no verifica comportamiento: verifica su propio andamiaje. Verified by:G-INTROVERT. -
TEST-004 — Cobertura de rama mínima del 90 % sobre las líneas nuevas o modificadas. La cobertura total del repo es un ratchet: puede subir, nunca bajar. Verified by:
G-COV-DIFF, G-COV-TOTAL. -
TEST-005 — Si
wct mutatereporta código UNCOVERED, cúbrelo con tests antes de volver a mutar. No gastes ciclos mutando código sin cobertura. Verified by:G-MUT, G-COV-DIFF. -
TEST-006 — Los tests deben pasar en orden aleatorio. Si fallan con
-p randomly, hay estado compartido entre tests. Verified by:G-TEST-RANDOM. -
TEST-007 — Si un archivo fuente cambiado tiene más de 100 sitios de mutación, pártelo preservando comportamiento antes de entregar. La partición canónica es el patrón fachada: el archivo original queda como fachada que re-exporta, y cada grupo cohesionado de funciones migra a un submódulo propio. Los imports públicos no cambian; los tests no se tocan. Verified by:
G-MUT-SITES. -
TEST-008 — Mantén los property tests separados de la verificación normal. No los incluyas en coverage, mutación, CRAP ni en las corridas de aceptación. Márcalos con
@pytest.mark.property. Verified by:G-PROP, G-TEST. -
TEST-009 — No edites a mano los manifests de mutación (
governance/mutation-manifest.json) ni los del pipeline de aceptación. Solo las herramientas los actualizan, como parte de su corrida normal. Verified by:G-META-1. -
TEST-010 — Cada feature con comportamiento observable por el usuario necesita un escenario Gherkin, y ese escenario debe usar parámetros para todo campo que pueda variar. Verified by:
G-ACCEPT, G-ACCEPT-MUT. -
TEST-011 — Corre
pytest --collect-only -qdespués de tocar archivos de test. Un test que no se colecciona no falla: simplemente no existe. Verified by:G-TEST.
Minimalismo — la escalera
-
MIN-001 — Antes de escribir código nuevo, recorre esta escalera en orden y detente en el primer peldaño que aplique: (1) ¿Necesita construirse esto? Si no, no lo construyas. (2) ¿Ya existe en este codebase? Reúsalo. (3) ¿Lo hace la biblioteca estándar? Úsala. (4) ¿Lo cubre una feature nativa de la plataforma? Úsala. (5) ¿Lo resuelve una dependencia ya instalada? Úsala — sujeto a MIN-002. (6) ¿Cabe en una línea? Escribe una línea. (7) Solo entonces: escribe el mínimo que funciona. Verified by:
G-DRY, G-DEAD, G-DEPS, human. -
MIN-002 — OVERRIDE 1 — El peldaño 5 está subordinado a la Dependency Rule. "Usa la dependencia ya instalada" NO aplica dentro de
domain/niapplication/. En esas capas, úsala desdeadapters/, detrás de un puerto. Verified by:G-ARCH. -
MIN-003 — OVERRIDE 2 — Queda ANULADA la cláusula de ponytail que permite dejar "un solo check ejecutable, sin frameworks ni fixtures" como verificación de lógica no trivial. Rige TEST-001: tests que fallarían ante una implementación plausiblemente incorrecta, con cero mutantes sobrevivientes. Verified by:
G-MUT, G-COV-DIFF. -
MIN-004 — OVERRIDE 3 — Si difieres trabajo, el marcador debe llevar owner e issue:
# ponytail(owner=<usuario>, issue=#<n>): <texto>. Un marcador sin ambos es rechazado. El conteo total tiene ratchet. Verified by:G-TODO. -
MIN-005 — OVERRIDE 4 — El modo
ultrano está permitido. Solooff,liteyfull(governance/policy.yaml → minimalism_mode). Verified by:G-META-2. -
MIN-006 — Antes de crear cualquier función, clase o módulo nuevo, busca en el codebase por comportamiento equivalente (no por nombre) y corre
wct dry --against <archivo>contra lo que propones. Verified by:G-DRY. -
MIN-007 — No introduzcas una capa de abstracción con un solo implementador salvo que exista un puerto real que cruzar. Una interfaz con una sola implementación y sin frontera de IO es boilerplate. Verified by:
G-ARCHMETRICS, human. -
MIN-008 — Al deduplicar, NO colapses tablas de casos de test. Muchos ejemplos pequeños y estructuralmente idénticos son una matriz de cobertura, no duplicación dañina.
wct drylos marcaLEAVE_ALONE; respétalo. Verified by:G-DRY, G-COV-TOTAL.
Estilo, complejidad y claridad
-
STYLE-001 —
ruffes el motor único de lint, formato y orden de imports. Correruff formatyruff check --fixantes de entregar. No añadas configuración de flake8, isort ni black: el perfil legacy existe en governance/lint/legacy/ y se activa conwct config --lint-profile legacy. Verified by:G-LINT, G-FMT, G-IMPORT-ORDER. -
STYLE-002 — CRAP ≤ 6 en toda función que escribas o modifiques. CRAP = CC² × (1 − cobertura)³ + CC. En la práctica: funciones pequeñas Y cobertura por rama casi total, simultáneamente. Verified by:
G-CRAP. -
STYLE-003 — Si CRAP está alto, primero pregunta cuál de los dos factores lo causa. CC alto → parte la función. Cobertura baja → añade tests. No apliques la remediación equivocada. Verified by:
G-CRAP. -
STYLE-004 — Complejidad ciclomática máxima de 10 por función. Cuenta:
if,for,while,except,with, cláusulas dematch, comprehensions con condición,and,or, y expresiones ternarias. Verified by:G-CC. -
STYLE-005 — Cero duplicación estructural nueva.
wct drycompara la FORMA del código ignorando nombres y literales: dos funciones con la misma estructura y nombres distintos son duplicación, aunque ningún detector de tokens las vea. Verified by:G-DRY, G-DRY-TOK. -
STYLE-006 — Elimina el código muerto que introduzcas. Una función no alcanzada, una rama imposible o un import sin uso son deuda inmediata, no futura. Verified by:
G-DEAD, G-LINT. -
STYLE-007 — Anotaciones de tipo en toda función pública.
mypycorre en modo estricto. Verified by:G-TYPE. -
STYLE-008 — Toda supresión (
# noqa,# type: ignore,# pragma: no cover,# nosec) debe llevar código de regla y justificación en la misma línea, con al menos 12 caracteres de texto. El conteo total de supresiones tiene ratchet: solo puede bajar. Verified by:G-SUPPRESS, G-LINT. -
STYLE-009 — Los nombres deben decir qué hace la cosa, no cómo está implementada ni de qué tipo es.
usuariosen vez delista_usuarios;pendientesen vez defiltrar_resultado_2. Verified by:human. -
STYLE-010 — Docstring en toda función y clase pública, consistente con la firma (parámetros, retorno, excepciones). La cobertura de docstrings es un ratchet. Verified by:
G-DOC. -
STYLE-011 — Ningún archivo fuente pasa de 500 líneas de código (sin blancos ni comentarios). La deuda existente vive en governance/baselines/file-size.json y solo puede bajar; un archivo NUEVO sobre el límite bloquea siempre. Tests y código generado quedan fuera: sus tablas son matrices de cobertura (MIN-008). Verified by:
G-SIZE. -
STYLE-012 — Complejidad cognitiva ≤ 15 por función en src/. La anidación profunda que la CC ciclómatica perdona — una función con CC 8 y cuatro niveles de if anidados pasa STYLE-004 — aquí cuesta: cada nivel de profundidad encarece el siguiente. Verified by:
G-COGNITIVE.
Seguridad y cadena de suministro
-
SEC-001 — Nunca escribas credenciales, tokens, claves privadas ni cadenas de conexión en el código, ni siquiera como valor de ejemplo o placeholder realista. Usa variables de entorno leídas en la capa de entrypoints. Verified by:
G-SECRET. -
SEC-002 — Cero findings de severidad alta o media en
banditysemgrep. Verified by:G-SAST, G-SAST-SEMGREP. -
SEC-003 — Cero CVEs críticos o altos en las dependencias.
pip-auditcorre en cada commit. Verified by:G-CVE. -
SEC-004 — No añadas una dependencia nueva sin recorrer los peldaños 3, 4 y 5 de la escalera primero. Si la añades, declárala explícitamente con versión acotada y justifica qué peldaño no la cubría. Verified by:
G-DEPS, G-CVE, human. -
SEC-005 — No modifiques archivos de gobernanza (governance/, .claude/settings.json, .pre-commit-config.yaml, .importlinter, .github/workflows/, pyproject.toml) como parte de una tarea de implementación. Si un umbral está mal, dilo y espera autorización humana explícita. Verified by:
G-META-1. -
SEC-006 — No uses
git commit --no-verify,--no-gpg-signni ninguna bandera que salte los hooks. No corras subconjuntos de la suite (pytest -k) como evidencia de que el gate pasa. Verified by:G-META-1, G-HOOKS-WIRED. -
SEC-007 — Valida y normaliza toda entrada en la frontera (entrypoints/adapters), no dentro del dominio. El dominio asume tipos válidos y lo hace explícito en sus firmas. Verified by:
G-ARCH, human. -
SEC-008 — Las licencias de las dependencias deben ser compatibles con la del proyecto. Se genera SBOM en cada release. Verified by:
G-SBOM.
Proceso, entrega y roles
-
PROC-001 — No termines un turno con el árbol en rojo. Corre
wct gate --tier fastantes de entregar; el hook de Stop lo corre de todas formas y te devolverá el fallo. Si el DEADLOCK GUARD te deja pasar tras bloqueos repetidos, el árbol sigue rojo: decláralo así en el handoff; pasar la válvula no es pasar el gate. Verified by:G-LINT, G-TYPE, G-TEST-FAST. -
PROC-002 — Trabaja en incrementos pequeños y revisables. Prefiere el diseño más simple que soporte el comportamiento actual y deje opciones claras para el siguiente paso. Verified by:
human. -
PROC-003 — Para features no triviales: especifica primero en Gherkin, obtén aprobación humana explícita del escenario, y solo entonces implementa. Verified by:
G-ACCEPT, human. -
PROC-004 — El orden de verificación pesada es: mutación → mutación de Gherkin → CRAP → DRY. Arregla lo que cada herramienta encuentre antes de correr la siguiente. Verified by:
G-MUT, G-ACCEPT-MUT, G-CRAP, G-DRY. -
PROC-005 — El que escribe no verifica. Si ejecutas un gate sobre código que tú escribiste en este mismo turno, no eres el verificador: pide el subagente
verifier, que no tiene permiso de escritura. Verified by:G-REDTEAM, human. -
PROC-006 — Mensajes de commit en formato conventional commits (
feat:,fix:,refactor:,test:,chore:…). Cuando trabajes en un rol de la pipeline, incluye el bylineBy <rol>.al final del mensaje. Verified by:G-COMMIT-MSG. -
PROC-007 — Usa
./build/tmp/dentro del repo para archivos temporales. No uses/tmp. Verified by:G-LINT, human. -
PROC-008 — Si un ratchet te bloquea, mejora la métrica. No subas el umbral. Subirlo requiere
wct ratchet raise --reason ... --approved-by <humano>y queda registrado en governance/ratchet-log.md. Verified by:G-META-1. -
PROC-009 — Si difieres trabajo, regístralo con owner e issue (
# TODO(owner=<usuario>, issue=#<n>): <texto>). Un marcador sin ambos es rechazado por el gate. Verified by:G-TODO. -
PROC-010 — No edites CLAUDE.md, AGENTS.md ni nada bajo governance/generated/. Edita governance/rules/*.yaml y corre
wct rules build. Verified by:G-RULES-SYNC. -
PROC-011 — Al arrancar en un rol de la pipeline, lee tu sección "Owns" y "Does Not Own" y respétala. No hagas el trabajo de otro rol aunque lo veas roto: repórtalo en el handoff. Verified by:
human. -
PROC-012 — Reporta el resultado real. Si un gate falló, dilo con su salida. Si saltaste un paso, dilo. No describas como verificado lo que no corriste. Verified by:
human. -
PROC-013 — Registra todo test flaky en cuanto lo veas: nombre del test, corrida (job y fecha) y si pasó al reintentar. Un flake sin registro es deuda invisible que erosiona la confianza en CI. El registro habilita decidir después, con datos, si corresponde un presupuesto de reintentos acotado o aislar el test; ninguno de los dos se hace en el momento. Verified by:
G-TEST-RANDOM, human.
