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