Requirement Evaluation Trees (RET)
A Simple Vista
Què: Àlgebra booleana per a portes, amb gestió d’incògnites (lògica de tres estats) Per què: Fer que la lògica de les portes sigui explícita, auditable i determinista - sense regles ocultes Qui: Desenvolupadors i operadors que redacten requisits complexos de portes Requisits previs: Comprensió bàsica de les condicions (vegeu condition_authoring.md)
Backend Baixat/AOT (RET)
RET ara proporciona un backend additiu rebaixat/AOT a ret-logic:
- Compila una vegada:
Requirement<P> -> CompiledRequirement<K> - Evaluate fast paths at runtime:
CompiledRequirement::evalCompiledRequirement::eval_blockCompiledRequirement::eval_tristate(+ variant de traç)
- Export deterministic predicate-key dependencies:
CompiledRequirement::predicate_keys()
- Compute explanation-oriented residual/progress views:
Requirement::residualCompiledRequirement::residual
- Preserve compatibility:
- Tree-walk
Requirement::eval*es manté suportat i sense canvis.
- Tree-walk
Això és independent del domini: els dominis subministren un mapeig de claus determinista (PredicateRegistry) i una execució de claus en temps d’execució (PredicateRuntime). L’explicació residual/progrés requereix addicionalment implementacions de progrés a nivell de condició o predicat a través de ConditionProgressEval i PredicateProgressRuntime.
Ingesta en temps de compilació vs en temps d’execució
La ingesta de fonts (RON, JSON, DSL, càrregues MCP, etc.) no canvia la semàntica de RET. La diferència és el cicle de vida:
- Compile-time/load-time ingestion: parse + validate + compile once, store artifact compilat.
- Runtime ingestion: parse + validate + compile when the gate arrives, then executar artefacte compilat.
Ambdós camins convergeixen en el mateix comportament d’àlgebra i avaluador compilat quan els requisits d’entrada són equivalents.
Per què RET?
Problema: Com es poden combinar múltiples verificacions d’evidència en una única decisió de porta?
Escenari d’exemple: “Vull desplegar a producció si:
- L’entorn és ‘producció’ I
- Les proves han passat I
- La cobertura és superior al 85% I
- Almenys 2 de 3 revisors han aprovat
Sense RET: Hauries d’escriure codi personalitzat per a cada Decision Gate, que és:
- No auditable (la lògica està oculta en el codi)
- No determinista (el codi pot canviar entre execucions)
- Difícil de verificar fora de línia (no es pot reproduir sense tornar a executar el codi)
Amb RET: Expreseu la lògica com una estructura d’arbre:
{
"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" }
]
}
}
]
}
}
Beneficis:
- Explícit: La lògica és visible en l’especificació de l’escenari
- Auditable: Cada avaluació es rastreja en el runpack
- Determinista: Mateixa evidència -> mateix resultat
- Repetible: Pot verificar-se offline sense tornar a consultar els proveïdors
[Seguretat]: La lògica de porta explícita impedeix portes posteriors ocultes. Tota la lògica es declara en l’especificació de l’escenari i es rastreja en el paquet d’execució per a auditoria.
Model Mental: Arbre d’Avaluació RET
Aquí teniu com es valora un arbre de requisits:
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)
Ordre d’avaluació:
- Les condicions de fulla s’avaluen en un estat de tres valors (veritable/fals/desconegut)
- Els nodes operadors combinen resultats fills mitjançant lògica de tres estats
- L’outcome del node arrel determina el resultat de la porta
Tri-State Outcomes
RET utilitza lògica de tres estats (no només veritable/fals):
true: Passis d’accés (tots els requisits satisfets)false: La porta falla (requisits contradits)unknown: Retencions de porta (requisits inconclusos)
Per què tri-estat? Les portes fallan tancades: una porta només es permet passar quan el requisit s’avalua com a true. Els resultats unknown impedeixen que les portes passin fins que l’evidència estigui completa.
Exemple:
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)
Operadors Bàsics
I
Semàntica: Tots els nens han de ser true
Truth table (2 operands):
| Left | Right | Result |
|---|---|---|
| true | true | true |
| true | false | false |
| true | unknown | unknown |
| false | (any) | false |
| unknown | true | unknown |
| desconegut | desconegut | desconegut |
Exemple:
{
"requirement": {
"And": [
{ "Condition": "tests_ok" },
{ "Condition": "coverage_ok" }
]
}
}
Cas d’ús: Tant les proves com la cobertura han de passar
Comportament:
- Tot
true->true(passis de porta) - Any
false->false(la porta falla) - Altrament -> unknown (la porta es manté)
O bé
Semàntica: Qualsevol fill pot ser true
Truth table (2 operands):
| Left | Right | Result |
|---|---|---|
| true | (any) | true |
| false | false | false |
| false | unknown | unknown |
| unknown | false | unknown |
| desconegut | desconegut | desconegut |
Exemple:
{
"requirement": {
"Or": [
{ "Condition": "manual_override" },
{ "Condition": "tests_ok" }
]
}
}
Cas d’ús: O bé sobreescriptura manual O bé proves automatitzades han de passar
Comportament:
- Any
true->true(passos de porta) - Tot
false->false(la porta falla) - Altrament -> unknown (la porta es manté)
No
Semàntica: Invertir l’outcome del fill
Truth table:
| Input | Result |
|---|---|
| true | false |
| false | true |
| Taula de veritat: | Entrada |
Exemple:
{
"requirement": {
"And": [
{ "Condition": "tests_ok" },
{ "Not": { "Condition": "blocklist_hit" } }
]
}
}
Cas d’ús: Les proves han de passar I la llista negra NO ha de ser activada
Comportament:
true->falsefals->certunknown->desconegut(fail-closed: no es pot confirmar l’absència)
RequireGroup (Quorum)
Semàntica: Almenys N de M nens han de ser true
Paràmetres:
min: Nombre mínim de resultatstruerequeritsreqs: Array de requisits fills
Exemple:
{
"requirement": {
"RequireGroup": {
"min": 2,
"reqs": [
{ "Condition": "alice_approved" },
{ "Condition": "bob_approved" },
{ "Condition": "carol_approved" }
]
}
}
}
Cas d’ús: Almenys 2 de 3 revisors han d’aprovar
Comportament:
- Comptar resultats
true - Si el compte >=
min->true(quorum assolit) - Si count + unknowns <
min->false(quòrum impossible) - Altrament -> unknown (quorum pendent)
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) |
| [fals, fals, fals] | 2 | fals | 0 vertader, impossible |
[Desenvolupador]: Vegeu ret-logic crate per a la implementació. RequireGroup compta veritable/fals de manera independent (desconegut no és ni veritable ni fals).
Condició (Fulla)
Semàntica: Referència a una condició per clau
Exemple:
{
"requirement": { "Condition": "tests_ok" }
}
Cas d’ús: Porteria simple amb una única condició
Comportament:
- Avalua el resultat tri-estat de la condició
- La condició ha d’existir a
ScenarioSpec.conditions
Regles de Propagació Tri-Estat
Com es propaguen els resultats unknown a través dels operadors:
I Propagació
| Operands | Result | Reason |
|---|---|---|
And(true, true, true) | true | Tots els requisits satisfets |
And(true, false, true) | false | Un falla -> And falla |
And(true, unknown, true) | unknown | No es pot confirmar que tots siguin true encara |
And(false, unknown) | false | Un falla (curtcircuit) |
And(unknown, unknown) | unknown | Evidència pendent |
Regla: false domina; tot true dóna true; altrament unknown
O Propagació
| Operands | Resultat | Raó |
|---|---|---|
Or(false, false, false) | false | Tots els requisits han fallat |
Or(true, false, false) | true | Un té èxit -> Or té èxit |
Or(false, unknown, false) | unknown | No es pot confirmar que tots siguin falsos encara |
Or(true, unknown) | true | Un té èxit (curtcircuit) |
Or(unknown, unknown) | unknown | Evidència pendent |
Regla: true domina; tot false dóna false; altrament unknown
RequireGroup Propagation
| Resultats | min | comptatge veritable | comptatge desconegut | Resultat |
|---|---|---|---|---|
| [T, T, F] | 2 | 2 | 0 | veritable (min assolit) |
| [T, U, U] | 2 | 1 | 2 | desconegut (max 3, necessiten 2) |
| [T, F, F] | 2 | 1 | 0 | fals (max 1 < min) |
| [U, U, U] | 2 | 0 | 3 | desconegut (max 3, necessiten 2) |
| [F, F, F] | 2 | 0 | 0 | fals (impossible) |
Regla:
- Si
true_count >= min->true(quòrum assolit) - Si
true_count + unknown_count < min->false(quòrum impossible) - Altrament -> unknown (quorum pendent)
[LLM Agent]: Quan RequireGroup retorna
unknown, necessites més proves. Comprova quines condicions són desconegudes i treballa per satisfer-les.
Casos d’ús pràctics
Simple Gate: Ambdues Condicions
Escenari: Desplegar si les proves han passat I la cobertura és superior al 85%
{
"gate_id": "quality_gate",
"requirement": {
"And": [
{ "Condition": "tests_ok" },
{ "Condition": "coverage_ok" }
]
}
}
Quorum Gate: 2 de 3 Revisors
Escenari: Fusionar PR si almenys 2 de 3 revisors han aprovat
{
"gate_id": "review_gate",
"requirement": {
"RequireGroup": {
"min": 2,
"reqs": [
{ "Condition": "alice_approved" },
{ "Condition": "bob_approved" },
{ "Condition": "carol_approved" }
]
}
}
}
Exclusió Porta: NO a la llista negra
Escenari: Desplegar si NO està a la llista negra
{
"gate_id": "blocklist_gate",
"requirement": {
"Not": { "Condition": "blocklist_hit" }
}
}
Complex Gate: (A I B) O C
Escenari: Desplegar si (les proves han passat I la cobertura és correcta) O sobreescriptura manual
{
"gate_id": "deploy_gate",
"requirement": {
"Or": [
{
"And": [
{ "Condition": "tests_ok" },
{ "Condition": "coverage_ok" }
]
},
{ "Condition": "manual_override" }
]
}
}
Ramificació en Resultats de Portes
Podeu dirigir-vos a diferents etapes en funció dels resultats de les portes utilitzant 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
}
}
Com funciona:
- Avaluar el gate
env_gate - Comprovar el resultat contra les branques (de dalt a baix)
- La primera branca coincident guanya
- Si no hi ha coincidència i
defaultés nul -> error
Casos d’ús:
- Cert: Avançar al desplegament en producció
- Desconegut: Esperar revisió manual
- Fals: Rebutjar i notificar
[Seguretat]: Utilitzeu ramificacions per implementar alternatives de seguretat. Per exemple, rutegeu
unknowna revisió manual en comptes d’avançar automàticament.
Logic Mode: Strong Kleene
Decision Gate utilitza lògica Kleene forta (tres estats):
Propertats clau:
And(true, unknown)->unknown(no es pot confirmar que tot sigui cert)Or(false, unknown)->unknown(no es pot confirmar que tot sigui fals)Not(unknown)->unknown(no es pot invertir la incertesa)
Alternativa (no utilitzada): Lògica de Bochvar (qualsevol desconegut -> desconegut)
Per què Kleene?
- Més intuïtiu per a proves parcials
- Curt-circuits quan sigui possible (
And(false, unknown)->false) - Els equilibris fallen tancats amb usabilitat
[Desenvolupador]: Vegeu crates/ret-logic/src/lib.rs per a l’algorisme d’avaluació.
Casos d’ús
Primari: Portes complexes que requereixen combinacions booleanes (I, O, quòrum) Secundari: Portes simples amb condicions úniques (només node de condició) Antipatró: No anideu RETs massa profundament - preferiu condicions enfocades i arbres plans
Solució de problemes
Problema: Porta enganxada en unknown
Síntomes: La porta mai passa, sempre retorna unknown
Causa: Una o més condicions s’estan avaluant com a unknown
Solució:
- Comproveu el rastre de la porta per veure quines condicions són
unknown - Solucioneu els problemes de condicions subjacents (vegeu condition_authoring.md)
- Common causes:
- Error del proveïdor (per exemple, fitxer absent per al proveïdor json)
- JSONPath no trobat (desajustament de l’eina)
- Incompatibilitat de tipus per a un comparador sensible al tipus
Problema: RequireGroup Mai Passa
Síntomes: RequireGroup sempre retorna false o unknown
Causa: min és massa alt, o massa condicions estan fallant
Solució:
- Comprovar el valor
minen comparació amb el nombre de condicions - Verifiqueu els resultats de condició en el rastre de la porta
- Assegureu-vos que almenys
mincondicions poden sertruesimultàniament
Exemple:
// 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 branca no coincideix
Síntomes: Error d’evaluació de la porta: “No hi ha cap branca coincident”
Causa: El resultat de la porta no coincideix amb cap branca, i default és nul
Solució:
- Afegiu branques per a tots els possibles resultats (veritable/fals/desconegut)
- OR estableix
defaulta una etapa de reserva - Exemple:
{
"branches": [
{ "gate_id": "gate1", "outcome": "true", "next_stage_id": "ship" },
{ "gate_id": "gate1", "outcome": "false", "next_stage_id": "deny" }
],
"default": "hold" // Fallback for unknown
}
Consells d’autoria
1. Mantingueu les claus de condició estables i descriptives
- Utilitzeu
tests_oknopred1 - Les claus es referencien en runpacks per a auditoria
2. Utilitzeu RequireGroup per a comprovacions de tipus quorum
- Exemple: “2 de 3 revisors”, “3 de 5 comprovacions de datacenter”
- Alternativa: Múltiples condicions And (però menys flexibles)
3. Preferir arbres més petits amb condicions enfocades
- Més fàcil d’auditar i entendre
- Més fàcil de depurar quan fallen les portes
4. Validar l’estructura RET durant la definició de l’escenari
- La Decision Gate valida els RETs en el moment de
scenario_define - Fallida ràpida si l’estructura és invàlida (per exemple, referenciant condicions inexistents)
5. Utilitzeu ramificacions per a solucions de seguretat en cas de fallada
- Rutar
unknowna revisió manual - Ruta
falseper alertar/denegar - Route
trueper avançar
Camins d’Aprenentatge de Referència Creuada
Camí de Nou Usuari: getting_started.md -> condition_authoring.md -> AQUESTA GUIA -> integration_patterns.md
Camí de Lògica Avançada: AQUESTA GUIA -> evidence_flow_and_execution_model.md -> Entendre com s’integren els RETs en el pipeline d’avaluació
Camí de Seguretat: AQUESTA GUIA -> security_guide.md -> Apreneu com la lògica explícita evita portes enrere
Glossari
I: Operador que requereix que tots els nens siguin true.
Porta: Punt de decisió en un escenari, avaluat mitjançant RET contra proves.
O: Operador que requereix que qualsevol fill sigui true.
Nota: Operador que inverteix el resultat del fill (true <-> false).
Condició: Definició de comprovació d’evidències: consulta + comparador + valor esperat.
RequireGroup: Operador de quòrum que requereix almenys N de M fills per ser true.
RET: Arbre d’Avaluació de Requisits, àlgebra booleana (I/O/No/RequerirGrup) per a portes.
TriState: Resultat de l’avaluació: true (aprovat), false (suspendre) o unknown (en espera).
Lògica Kleene Forta: Mode de lògica de tres estats on And(true, unknown) -> unknown.