Documentos de Decision Gate

Evaluación de puertas determinista, reproducible con decisiones auditables.

Documentación de Asset Core

Á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:

  1. Las condiciones de los nodos se evalúan en un estado tri-estado (verdadero/falso/desconocido)
  2. Los nodos operadores combinan los resultados de los hijos a través de lógica de tres estados
  3. 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):

LeftRightResult
truetruetrue
truefalsefalse
trueunknownunknown
false(any)false
unknowntrueunknown
desconocidodesconocidodesconocido

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):

LeftRightResult
true(any)true
falsefalsefalse
falseunknownunknown
unknownfalseunknown
desconocidodesconocidodesconocido

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:

InputResult
truefalse
falsetrue
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 -> falso
  • falso -> verdadero
  • unknown -> 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 resultados true requeridos
  • reqs: 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:

OutcomesminResultReason
[true, true, false]2true2 true >= min (quorum reached)
[true, unknown, unknown]2unknown1 true, can’t reach min yet
[true, false, false]2false1 true, max possible is 1 < min
[true, true, unknown]2true2 true >= min (already met)
[falso, falso, falso]2falso0 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

OperandosResultadoRazón
And(true, true, true)trueTodos los requisitos satisfechos
And(true, false, true)falseUno falla -> And falla
And(true, unknown, true)unknownNo se puede confirmar que todos sean verdaderos aún
And(false, unknown)falseUno falla (circuito corto)
And(unknown, unknown)unknownEvidencia pendiente

Regla: false domina; todos los true producen true; de lo contrario unknown


O Propagación

OperandosResultadoRazón
Or(false, false, false)falseTodos los requisitos fallaron
Or(true, false, false)trueUno tiene éxito -> Or tiene éxito
Or(false, unknown, false)unknownNo se puede confirmar que todos sean falsos aún
Or(true, unknown)trueUno tiene éxito (circuito corto)
Or(unknown, unknown)unknownEvidencia pendiente

Regla: true domina; todos false producen false; de lo contrario unknown


Propagación RequireGroup

Resultadosminconteo verdaderoconteo desconocidoResultado
[T, T, F]220verdadero (mínimo alcanzado)
[T, U, U]212desconocido (máx 3, se necesitan 2)
[T, F, F]210falso (máx 1 < min)
[U, U, U]203desconocido (máx 3, se necesitan 2)
[F, F, F]200falso (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:

  1. Evaluar la puerta env_gate
  2. Verificar el resultado contra las ramas (de arriba hacia abajo)
  3. La primera rama coincidente gana
  4. Si no hay coincidencia y default es 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 unknown a 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:

  1. Verifique el seguimiento de la puerta para ver qué condiciones son unknown
  2. Solucionar los problemas subyacentes de las condiciones (ver condition_authoring.md)
  3. 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:

  1. Verificar el valor de min frente al número de condiciones
  2. Verificar los resultados de condición en el seguimiento de la puerta
  3. Asegúrese de que al menos min condiciones puedan ser true simultá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:

  1. Agregar ramas para todos los posibles resultados (verdadero/falso/desconocido)
  2. O establece default a una etapa de respaldo
  3. 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_ok no pred1
  • 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 unknown para revisión manual
  • Ruta false para alertar/negar
  • Route true para 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.