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::evalCompiledRequirement::eval_blockCompiledRequirement::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::residualCompiledRequirement::residual
- Conserva la compatibilidad:
- Tree-walk
Requirement::eval*se mantiene soportado y sin cambios.
- Tree-walk
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:
- 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
Tabla de verdad (2 operandos):
| Izquierda | Derecha | Resultado |
|---|---|---|
| true | true | true |
| true | false | false |
| true | unknown | unknown |
| false | (cualquiera) | false |
| unknown | true | unknown |
| unknown | unknown | unknown |
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):
| Izquierda | Derecha | Resultado |
|---|---|---|
| true | (cualquiera) | true |
| false | false | false |
| false | unknown | unknown |
| unknown | false | unknown |
| unknown | unknown | unknown |
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:
| Entrada | Resultado |
|---|---|
| true | false |
| false | true |
| unknown | unknown |
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->falsefalse->trueunknown->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)
Ejemplos de tabla de verdad:
| Resultados | min | Resultado | Razón |
|---|---|---|---|
| [true, true, false] | 2 | true | 2 verdaderos >= min (quórum alcanzado) |
| [true, unknown, unknown] | 2 | unknown | 1 verdadero, no se puede alcanzar min aún |
| [true, false, false] | 2 | false | 1 verdadero, el máximo posible es 1 < min |
| [true, true, unknown] | 2 | true | 2 verdaderos >= min (ya cumplido) |
| [false, false, false] | 2 | false | 0 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
| 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 | true (mínimo alcanzado) |
| [T, U, U] | 2 | 1 | 2 | unknown (máx 3, se necesitan 2) |
| [T, F, F] | 2 | 1 | 0 | false (máx 1 < min) |
| [U, U, U] | 2 | 0 | 3 | unknown (máx 3, se necesitan 2) |
| [F, F, F] | 2 | 0 | 0 | false (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:
- Verifique el seguimiento de la puerta para ver qué condiciones son
unknown - Solucionar los problemas subyacentes de las condiciones (ver condition_authoring.md)
- 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:
- 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: 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_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
- 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
falseounknown. - 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.