Árboles de Evaluación de Requisitos (RET)
A primera vista
Qué: Álgebra booleana para puertas, con manejo de desconocidos (lógica de tres estados) Por qué: Hacer la lógica de las puertas explícita, auditable y determinista - sin reglas ocultas Quién: Desarrolladores y operadores que redactan requisitos complejos de puertas Requisitos previos: Comprensión básica de condiciones (ver condition_authoring.md)
¿Por qué RET?
Problema: ¿Cómo se combinan múltiples verificaciones de evidencia en una única decisión de puerta?
Escenario de ejemplo: “Quiero desplegar en producción si:
- El entorno es ‘producción’ Y
- Pruebas aprobadas Y
- La cobertura es superior al 85% Y
- Al menos 2 de 3 revisores aprobaron
Sin RET: Tendrías que escribir código personalizado para cada puerta, que es:
- No auditable (la lógica está oculta en el código)
- No determinista (el código puede cambiar entre ejecuciones)
- Difícil de verificar sin conexión (no se puede reproducir sin volver a ejecutar el código)
Con RET: Expresas la lógica como una estructura de árbol:
{
"requirement": {
"And": [
{ "Condition": "env_is_prod" },
{ "Condition": "tests_ok" },
{ "Condition": "coverage_ok" },
{
"RequireGroup": {
"min": 2,
"reqs": [
{ "Condition": "alice_approved" },
{ "Condition": "bob_approved" },
{ "Condition": "carol_approved" }
]
}
}
]
}
}
Beneficios:
- Explícito: La lógica es visible en la especificación del escenario
- Auditable: Cada evaluación está registrada en el runpack
- Determinista: Mismas evidencias -> mismo resultado
- Repetible: Puede verificar sin conexión sin volver a consultar a los proveedores
[Seguridad]: La lógica de puerta explícita previene puertas traseras ocultas. Toda la lógica se declara en la especificación del escenario y se rastrea en el paquete de ejecución para auditoría.
Modelo Mental: Árbol de Evaluación RET
Aquí está cómo se evalúa un árbol de requisitos:
RET EVALUATION TREE (simplified)
Gate Requirement (tree structure)
And
|-- Pred(A) -> true
|-- Pred(B) -> unknown
|-- Not(C) -> false
`-- RequireGroup (min: 2)
|-- Pred(D) -> true
|-- Pred(E) -> true
`-- Pred(F) -> false
Strong Kleene Logic: And(true, unknown, true, true) -> unknown
(gate holds)
Orden de evaluación:
- Las condiciones de los nodos se evalúan en un estado tri-estado (verdadero/falso/desconocido)
- Los nodos operadores combinan los resultados de los hijos a través de lógica de tres estados
- El resultado del nodo raíz determina el resultado de la puerta
Resultados de Tri-State
RET utiliza lógica de tres estados (no solo verdadero/falso):
true: Pases de acceso (todos los requisitos satisfechos)false: La puerta falla (requisitos contradichos)unknown: Las puertas se mantienen (requisitos inconclusos)
¿Por qué triestado? Las puertas fallan cerradas: una puerta solo se abre cuando el requisito se evalúa como true. Los resultados unknown impiden que las puertas se abran hasta que la evidencia esté completa.
Ejemplo:
Gate: And(tests_ok, coverage_ok)
Conditions:
- tests_ok: true (tests passed)
- coverage_ok: unknown (coverage report missing)
Outcome: unknown (gate holds until coverage is available)
Operadores Básicos
Y
Semántica: Todos los hijos deben ser true
Truth table (2 operands):
| Left | Right | Result |
|---|---|---|
| true | true | true |
| true | false | false |
| true | unknown | unknown |
| false | (any) | false |
| unknown | true | unknown |
| desconocido | desconocido | desconocido |
Ejemplo:
{
"requirement": {
"And": [
{ "Condition": "tests_ok" },
{ "Condition": "coverage_ok" }
]
}
}
Caso de uso: Tanto las pruebas como la cobertura deben pasar
Comportamiento:
- Todos
true->true(pases de puerta) - Cualquier
false->false(la puerta falla) - De lo contrario -> unknown (la puerta se mantiene)
O
Semántica: Cualquier hijo puede ser true
Truth table (2 operands):
| Left | Right | Result |
|---|---|---|
| true | (any) | true |
| false | false | false |
| false | unknown | unknown |
| unknown | false | unknown |
| desconocido | desconocido | desconocido |
Ejemplo:
{
"requirement": {
"Or": [
{ "Condition": "manual_override" },
{ "Condition": "tests_ok" }
]
}
}
Caso de uso: Debe pasar ya sea la anulación manual O las pruebas automatizadas
Comportamiento:
- Cualquier
true->true(pases de puerta) - Todos
false->false(la puerta falla) - De lo contrario -> unknown (la puerta se mantiene)
No
Semántica: Invertir resultado del hijo
Truth table:
| Input | Result |
|---|---|
| true | false |
| false | true |
| Tabla de verdad: | Entrada |
Ejemplo:
{
"requirement": {
"And": [
{ "Condition": "tests_ok" },
{ "Not": { "Condition": "blocklist_hit" } }
]
}
}
Caso de uso: Las pruebas deben pasar Y la lista de bloqueo NO debe ser activada
Comportamiento:
verdadero->falsofalso->verdaderounknown->unknown(cerrado por defecto: no se puede confirmar la ausencia)
RequireGroup (Quorum)
Semántica: Al menos N de M hijos deben ser true
Parámetros:
min: Número mínimo de resultadostruerequeridosreqs: Array de requisitos secundarios
Ejemplo:
{
"requirement": {
"RequireGroup": {
"min": 2,
"reqs": [
{ "Condition": "alice_approved" },
{ "Condition": "bob_approved" },
{ "Condition": "carol_approved" }
]
}
}
}
Caso de uso: Al menos 2 de 3 revisores deben aprobar
Comportamiento:
- Contar resultados
true - Si count >=
min->true(quórum alcanzado) - Si count + unknowns <
min->false(quórum imposible) - De lo contrario -> unknown (quorum pendiente)
Truth table examples:
| Outcomes | min | Result | Reason |
|---|---|---|---|
| [true, true, false] | 2 | true | 2 true >= min (quorum reached) |
| [true, unknown, unknown] | 2 | unknown | 1 true, can’t reach min yet |
| [true, false, false] | 2 | false | 1 true, max possible is 1 < min |
| [true, true, unknown] | 2 | true | 2 true >= min (already met) |
| [falso, falso, falso] | 2 | falso | 0 verdadero, imposible |
[Desarrollador]: Consulta el crate ret-logic para la implementación. RequireGroup cuenta verdadero/falso de manera independiente (desconocido no es ninguno de los dos).
Condición (Hoja)
Semántica: Referenciar una condición por clave
Ejemplo:
{
"requirement": { "Condition": "tests_ok" }
}
Caso de uso: Puerta simple con una única condición
Comportamiento:
- Evalúa el resultado de triestado de la condición
- La condición debe existir en
ScenarioSpec.conditions
Reglas de Propagación Tri-Estatal
Cómo unknown resultados se propagan a través de operadores:
Y Propagación
| Operandos | Resultado | Razón |
|---|---|---|
And(true, true, true) | true | Todos los requisitos satisfechos |
And(true, false, true) | false | Uno falla -> And falla |
And(true, unknown, true) | unknown | No se puede confirmar que todos sean verdaderos aún |
And(false, unknown) | false | Uno falla (circuito corto) |
And(unknown, unknown) | unknown | Evidencia pendiente |
Regla: false domina; todos los true producen true; de lo contrario unknown
O Propagación
| Operandos | Resultado | Razón |
|---|---|---|
Or(false, false, false) | false | Todos los requisitos fallaron |
Or(true, false, false) | true | Uno tiene éxito -> Or tiene éxito |
Or(false, unknown, false) | unknown | No se puede confirmar que todos sean falsos aún |
Or(true, unknown) | true | Uno tiene éxito (circuito corto) |
Or(unknown, unknown) | unknown | Evidencia pendiente |
Regla: true domina; todos false producen false; de lo contrario unknown
Propagación RequireGroup
| Resultados | min | conteo verdadero | conteo desconocido | Resultado |
|---|---|---|---|---|
| [T, T, F] | 2 | 2 | 0 | verdadero (mínimo alcanzado) |
| [T, U, U] | 2 | 1 | 2 | desconocido (máx 3, se necesitan 2) |
| [T, F, F] | 2 | 1 | 0 | falso (máx 1 < min) |
| [U, U, U] | 2 | 0 | 3 | desconocido (máx 3, se necesitan 2) |
| [F, F, F] | 2 | 0 | 0 | falso (imposible) |
Regla:
- Si
true_count >= min->true(quórum alcanzado) - Si
true_count + unknown_count < min->false(quórum imposible) - De lo contrario -> unknown (quorum pendiente)
[LLM Agent]: Cuando RequireGroup devuelve
unknown, necesitas más evidencia. Verifica qué condiciones son desconocidas y trabaja para satisfacerlas.
Casos de Uso Prácticos
Puerta Simple: Ambas Condiciones
Escenario: Desplegar si las pruebas pasaron Y la cobertura está por encima del 85%
{
"gate_id": "quality_gate",
"requirement": {
"And": [
{ "Condition": "tests_ok" },
{ "Condition": "coverage_ok" }
]
}
}
Quorum Gate: 2 de 3 Revisores
Escenario: Fusionar PR si al menos 2 de 3 revisores aprobaron
{
"gate_id": "review_gate",
"requirement": {
"RequireGroup": {
"min": 2,
"reqs": [
{ "Condition": "alice_approved" },
{ "Condition": "bob_approved" },
{ "Condition": "carol_approved" }
]
}
}
}
Exclusion Gate: NO en la lista negra
Escenario: Desplegar si NO está en la lista negra
{
"gate_id": "blocklist_gate",
"requirement": {
"Not": { "Condition": "blocklist_hit" }
}
}
Puerta Compleja: (A Y B) O C
Escenario: Desplegar si (pruebas aprobadas Y cobertura OK) O anulación manual
{
"gate_id": "deploy_gate",
"requirement": {
"Or": [
{
"And": [
{ "Condition": "tests_ok" },
{ "Condition": "coverage_ok" }
]
},
{ "Condition": "manual_override" }
]
}
}
Ramificación en Resultados de Puerta
Puedes enrutar a diferentes etapas basadas en los resultados de las puertas utilizando advance_to.branch:
{
"advance_to": {
"kind": "branch",
"branches": [
{ "gate_id": "env_gate", "outcome": "true", "next_stage_id": "ship" },
{ "gate_id": "env_gate", "outcome": "unknown", "next_stage_id": "hold" },
{ "gate_id": "env_gate", "outcome": "false", "next_stage_id": "deny" }
],
"default": null
}
}
Cómo funciona:
- Evaluar la puerta
env_gate - Verificar el resultado contra las ramas (de arriba hacia abajo)
- La primera rama coincidente gana
- Si no hay coincidencia y
defaultes nulo -> error
Casos de uso:
- Verdadero: Avanzar a la implementación en producción
- Desconocido: Mantener para revisión manual
- Falso: Rechazar y notificar
[Seguridad]: Utilice ramificaciones para implementar alternativas de seguridad. Por ejemplo, dirija
unknowna revisión manual en lugar de avanzar automáticamente.
Logic Mode: Fuerte Kleene
Decision Gate utiliza lógica Kleene fuerte (triestado):
Propiedades clave:
And(true, unknown)->unknown(no se puede confirmar que todo sea verdadero)Or(false, unknown)->unknown(no se puede confirmar que todo sea falso)Not(unknown)->unknown(no se puede invertir la incertidumbre)
Alternativa (no utilizada): lógica de Bochvar (cualquier desconocido -> desconocido)
¿Por qué Kleene?
- Más intuitivo para evidencia parcial
- Cortocircuitos cuando es posible (
And(false, unknown)->false) - Los balances fallan cerrados con usabilidad
[Desarrollador]: Consulta crates/ret-logic/src/lib.rs para el algoritmo de evaluación.
Casos de Uso
Primario: Puertas complejas que requieren combinaciones booleanas (Y, O, quórum) Secundario: Puertas simples con condiciones individuales (solo nodo de condición) Antipatrones: No anidar RETs demasiado profundamente - preferir condiciones enfocadas y árboles planos
Solución de problemas
Problema: Puerta Atascada en unknown
Síntomas: La puerta nunca pasa, siempre regresa unknown
Causa: Una o más condiciones están evaluando a unknown
Solución:
- Verifique el seguimiento de la puerta para ver qué condiciones son
unknown - Solucionar los problemas subyacentes de las condiciones (ver condition_authoring.md)
- Common causes:
- Error del proveedor (por ejemplo, archivo faltante para el proveedor json)
- JSONPath no encontrado (desajuste de salida de la herramienta)
- Desajuste de tipo para un comparador sensible al tipo
Problema: RequireGroup Nunca Pasa
Síntomas: RequireGroup siempre devuelve false o unknown
Causa: min es demasiado alto, o demasiadas condiciones están fallando
Solución:
- Verificar el valor de
minfrente al número de condiciones - Verificar los resultados de condición en el seguimiento de la puerta
- Asegúrese de que al menos
mincondiciones puedan sertruesimultáneamente
Ejemplo:
// BAD: min is 3, but only 2 conditions
{
"RequireGroup": {
"min": 3,
"reqs": [
{ "Condition": "a" },
{ "Condition": "b" }
]
}
}
// GOOD: min <= number of conditions
{
"RequireGroup": {
"min": 2,
"reqs": [
{ "Condition": "a" },
{ "Condition": "b" },
{ "Condition": "c" }
]
}
}
Problema: La rama no coincide
Síntomas: Error de evaluación de la puerta: “No hay una rama coincidente”
Causa: El resultado de la puerta no coincide con ninguna rama, y default es nulo
Solución:
- Agregar ramas para todos los posibles resultados (verdadero/falso/desconocido)
- O establece
defaulta una etapa de respaldo - Ejemplo:
{
"branches": [
{ "gate_id": "gate1", "outcome": "true", "next_stage_id": "ship" },
{ "gate_id": "gate1", "outcome": "false", "next_stage_id": "deny" }
],
"default": "hold" // Fallback for unknown
}
Consejos de Autoría
1. Mantener las claves de condición estables y descriptivas
- Utiliza
tests_oknopred1 - Las claves se referencian en los runpacks para auditoría
2. Utilizar RequireGroup para verificaciones de estilo quórum
- Ejemplo: “2 de 3 revisores”, “3 de 5 verificaciones de centro de datos”
- Alternativa: Múltiples condiciones “Y” (pero menos flexibles)
3. Preferir árboles más pequeños con condiciones específicas
- Más fácil de auditar y entender
- Más fácil de depurar cuando fallan las puertas
4. Validar la estructura RET durante la definición del escenario
- La puerta de decisión valida los RET en el momento de
scenario_define - Falla rápidamente si la estructura es inválida (por ejemplo, al hacer referencia a condiciones no existentes)
5. Utiliza ramificaciones para soluciones de respaldo a prueba de fallos
- Rote
unknownpara revisión manual - Ruta
falsepara alertar/negar - Route
truepara avanzar
Rutas de Aprendizaje de Referencia Cruzada
Ruta para Nuevos Usuarios: getting_started.md -> condition_authoring.md -> ESTE MANUAL -> integration_patterns.md
Ruta de Lógica Avanzada: ESTE MANUAL -> evidence_flow_and_execution_model.md -> Comprender cómo encajan los RET en la tubería de evaluación
Ruta de Seguridad: ESTE MANUAL -> security_guide.md -> Aprenda cómo la lógica explícita previene puertas traseras
Glosario
Y: Operador que requiere que todos los hijos sean true.
Puerta: Punto de decisión en un escenario, evaluado a través de RET contra evidencia.
O: Operador que requiere que cualquier hijo sea true.
Nota: Operador que invierte el resultado del hijo (true <-> false).
Condición: Definición de verificación de evidencia: consulta + comparador + valor esperado.
RequireGroup: Operador de quórum que requiere al menos N de M hijos para ser true.
RET: Árbol de Evaluación de Requisitos, álgebra booleana (Y/O/NO/RequerirGrupo) para compuertas.
TriState: Resultado de la evaluación: verdadero (aprobado), falso (fallido) o desconocido (en espera).
Lógica Kleene Fuerte: Modo de lógica de tres estados donde And(true, unknown) -> unknown.