Árboles de Evaluación de Requisitos (RET)

Entender la semántica de evaluación de Resultado-Error-Timeout.

En esta página Sección actual: A primera vista

A primera vista

Qué: Álgebra de requisitos binaria y tri-valuada con un primitivo de umbral explícito Por qué: Hacer que la lógica de compuerta sea explícita, auditable y determinista - sin reglas ocultas Quién: Desarrolladores y operadores que redactan requisitos complejos de compuerta Requisitos previos: Comprensión básica de condiciones (ver condition_authoring.md)

Backend AOT/Bajado (RET)

RET ahora proporciona un backend aditivo reducido/AOT en ret-logic:

  • Compilar una vez: Requirement<P> -> CompiledRequirement<K>
  • Evalúa las rutas rápidas en tiempo de ejecución:
    • CompiledRequirement::eval
    • CompiledRequirement::eval_block
    • CompiledRequirement::eval_tristate (+ variante de traza)
  • Exporta las dependencias deterministas de claves de predicado:
    • CompiledRequirement::predicate_keys()
  • Calcula vistas residuales y de progreso orientadas a la explicación:
    • Requirement::residual
    • CompiledRequirement::residual
  • Conserva la compatibilidad:
    • Tree-walk Requirement::eval* se mantiene soportado y sin cambios.

Esto es independiente del dominio: los dominios proporcionan un mapeo de claves determinista (PredicateRegistry) y ejecución de claves en tiempo de ejecución (PredicateRuntime). La explicación residual/progreso requiere además implementaciones de progreso a nivel de condición o predicado a través de ConditionProgressEval y PredicateProgressRuntime.

Ingesta en Tiempo de Compilación vs en Tiempo de Ejecución

La ingesta de fuentes (RON, JSON, DSL, cargas útiles de MCP, etc.) no cambia la semántica de RET. La diferencia es el ciclo de vida:

  • Ingesta en tiempo de compilación/carga: analizar + validar + compilar una vez, almacenar el artefacto compilado.
  • Ingesta en tiempo de ejecución: analizar + validar + compilar cuando llegue la puerta, luego ejecutar el artefacto compilado.

Ambos caminos convergen en el mismo comportamiento de álgebra y evaluador compilado cuando los requisitos de entrada son equivalentes.


¿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: El código a medida aún puede ser determinista y revisable, pero cada implementación debe establecer independientemente su ley, identidad de versión, semántica de seguimiento y conformidad. El flujo de control es más difícil de inspeccionar y comparar como un álgebra cerrada.

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
  • Inspeccionable: La ley de requisitos es datos explícitos en lugar de flujo de control oculto.
  • Determinista: El mismo requisito validado y la asignación de verdad exacta de las hojas producen el mismo resultado RET.
  • Reevaluables: La ley de requisitos canónicos retenidos y las entradas de hojas pueden evaluarse fuera de línea sin volver a consultar a los proveedores. Esta propiedad RET no establece por sí sola la reproducción semántica completa de Decision Gate, el historial de confirmaciones aceptadas, la autenticidad de la evidencia o la no repudio.

[Security]: Explicit gate logic narrows the hidden-control-flow surface; it does not prove that provider, comparator, admission, policy, transition, or dispatch behavior is benign. Current runpacks provide bounded integrity and auditar/exportar solo evidencia.


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

Tabla de verdad (2 operandos):

IzquierdaDerechaResultado
truetruetrue
truefalsefalse
trueunknownunknown
false(cualquiera)false
unknowntrueunknown
unknownunknownunknown

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

Tabla de verdad (2 operandos):

IzquierdaDerechaResultado
true(cualquiera)true
falsefalsefalse
falseunknownunknown
unknownfalseunknown
unknownunknownunknown

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

Tabla de verdad:

EntradaResultado
truefalse
falsetrue
unknownunknown

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:

  • true -> false
  • false -> true
  • 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)

Ejemplos de tabla de verdad:

ResultadosminResultadoRazón
[true, true, false]2true2 verdaderos >= min (quórum alcanzado)
[true, unknown, unknown]2unknown1 verdadero, no se puede alcanzar min aún
[true, false, false]2false1 verdadero, el máximo posible es 1 < min
[true, true, unknown]2true2 verdaderos >= min (ya cumplido)
[false, false, false]2false0 verdaderos, 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 RawScenarioSpec.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]220true (mínimo alcanzado)
[T, U, U]212unknown (máx 3, se necesitan 2)
[T, F, F]210false (máx 1 < min)
[U, U, U]203unknown (máx 3, se necesitan 2)
[F, F, F]200false (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

Requisito Simple: Ambas Condiciones

Escenario: Desplegar si las pruebas pasaron Y la cobertura está por encima del 85%

{
  "And": [
    { "Condition": "tests_ok" },
    { "Condition": "coverage_ok" }
  ]
}

Requisito de Quórum: 2 de 3 Revisores

Escenario: Fusionar PR si al menos 2 de 3 revisores aprobaron

{
  "RequireGroup": {
    "min": 2,
    "reqs": [
      { "Condition": "alice_approved" },
      { "Condition": "bob_approved" },
      { "Condition": "carol_approved" }
    ]
  }
}

Requisito de Exclusión: NO en la Lista Negra

Escenario: Desplegar si NO está en la lista negra

{
  "Not": { "Condition": "blocklist_hit" }
}

Requisito Complejo: (A Y B) O C

Escenario: Desplegar si (pruebas aprobadas Y cobertura OK) O anulación manual

{
  "Or": [
    {
      "And": [
        { "Condition": "tests_ok" },
        { "Condition": "coverage_ok" }
      ]
    },
    { "Condition": "manual_override" }
  ]
}

RET en Topología Monotona-DAG

La topología del escenario no es un enrutador de resultados. Cada etapa no raíz lleva una ley de RET monótona sobre los IDs de etapa completados. Esos átomos son la única fuente de sus bordes de dependencia entrantes. Por ejemplo, ship se vuelve listo después de que build y ya sea security_review o operator_override han completado:

{
  "kind": "requires",
  "requirement": {
    "And": [
      { "Condition": "build" },
      {
        "Or": [
          { "Condition": "security_review" },
          { "Condition": "operator_override" }
        ]
      }
    ]
  }
}

Los requisitos de topología y las leyes de finalización de escenario aceptan solo el refinamiento monótono de RET: sin negación y sin expresión que pueda volverse falsa a medida que crece el conjunto de etapas completadas. Los requisitos de finalización de etapas retienen el RET completo, incluyendo la negación legal, porque evalúan una observación de evidencia más que el progreso gráfico monótono.

Cuando una finalización hace que varios hermanos estén listos, todos permanecen independientemente ready_unopened. El operador puede abrir cualquiera o todos ellos. Abrir uno no elige una rama exclusiva ni cancela, asigna o reserva otro.


Modos Lógicos

La construcción actual de MCP utiliza el valor predeterminado de ControlPlaneConfig de Strong Kleene. La biblioteca RET subyacente y la configuración del plano de control programático también soportan Bochvar. La identidad del evaluador/modo lógico es, por lo tanto, parte de la entrada semántica y debe ser retenida para cualquier reclamación de repetición.

Propiedades clave de Strong Kleene:

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)

Bochvar hace que unknown sea infeccioso para And y Or, incluyendo casos que Strong Kleene puede resolver a través de un valor absorbente. RequireGroup utiliza la misma regla de conteo/límites en ambos modos actuales.

Por qué Strong Kleene es el valor predeterminado actual:

  • 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. Causas habituales:
    • no se admitió ningún candidato de evidencia para una condición requerida;
    • los candidatos estaban presentes pero fallaron en la garantía, frescura, acuerdo o política de quórum;
    • la adquisición local falló operativamente y por lo tanto no se acuñó evidencia.

Un error de integridad por desajuste de tipo/predicado de post-validación no es unknown semántico.


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: Un Hermano Listo No Se Abrió Automáticamente

Síntomas: Completar un padre hace que varios hijos estén listos, pero ninguno comienza a trabajar.

Causa: La preparación y apertura son deliberadamente separadas. DG deriva la frontera lista canónica; no elige la política del operador ni implica ramificación.

Solución: Seleccionar una etapa ready_unopened explícita y llamar a scenario_open_stage con la cabeza aceptada exacta. Un arnés de coordinación puede seleccionar varios hermanos, pero la asignación, arrendamientos, exclusividad y afinidad de agentes son autoridad separada.


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

  • Decision Gate 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. Mantener la topología y las leyes de evidencia distintas

  • Utilizar el RET de ID de etapa monótona para requisitos previos y finalización de escenario.
  • Utilizar el RET de ID de condición completa para la ley de finalización de evidencia de una etapa.
  • No reclamar enrutamiento de resultado ordinario false o unknown.
  • Revisa esta guía solo después de que se cierre la decisión de transición bloqueante y exista evidencia de implementación.

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: semánticas tri-valuadas seleccionadas de And/Or/Not más un primitivo de umbral RequireGroup distinto 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.