Ir al contenido

Nivel 4 · El arco, por traspasos

Seis hitos. Como en los niveles anteriores, los tres roles están presentes desde el primero: 🧭 Nerea arriba (portal · producto), 🛡️ Diego en medio (portal · calidad), 🧑‍💻 Marta a la derecha (CLI + git). La lección de este arco es ÁMBAR → VERDE —una falta de conclusión real y honesta que SÍ se resuelve en cuanto se mide con potencia real (OUT-OF-FOLD sobre las 1.000 filas, no un held-out de 200)— con un riesgo de proxy que aflora al revisar el modelo y se deja sin tratar, cerrando con una aprobación legítima que acepta conscientemente ese residual. Y un sexto hito nuevo: la revisión periódica que reabre esa aprobación y forma una cadena de aprobaciones con un aprobador efectivo — el último responsable del expediente.

Los datos duros de cada hito —los comandos, el mensaje de commit, el diff y el color de la barrera— no están escritos a mano: cada bloque GuionStep los lee del guion steps/ del repositorio publicado. Si un paso no existiera, el build fallaría; lo que lees aquí es exactamente lo que el repositorio hace.

1Declarar el sistema §5(b) + DORA y el riesgo de exclusión
🧭 Nerea

Nerea es la responsable de producto en NovaCredit, una entidad de crédito que despliega un modelo de puntuación. Abre el portal y ejecuta las misiones de autoría que generan el manifiesto de gobernanza froga.yaml. Tres cosas importan:

  1. El nivel es high, declarado por un humano, vía la ruta del uso. La misión classify-system rellena el bloque classification con la base: «Ley de IA de la UE Anexo III §5(b) (evaluación de solvencia crediticia / puntuación de crédito)» — más «DORA Art. 6 (riesgo TIC de la entidad financiera)». La activación de alto riesgo aquí es el Anexo III §5(b), no el Art. 6(1). El motor no lo infiere; Nerea lo declara y lo asume.
  2. Se declaran dos regímenes, y uno es la superposición. La misión declare-standards escribe applicable_standards con la columna vertebral (eu/ai-act@2024, eu/pren-18228@2026, iso/23894@2023) más eu/dora@2022 — la superposición DORA — con un bloque dora.entity (el LEI, el tipo de entidad credit_institution). Declarar eu/dora@2022 es lo que hace que el motor ensamble el Registro DORA más adelante.
  3. El riesgo es la exclusión crediticia injusta. La misión identify-risks añade risk.unfair-credit-exclusion«el modelo puede excluir injustamente a grupos protegidos al heredar patrones históricos de discriminación.» El control que confirmará el residual es la diferencia de paridad demográfica — una barrera de equidad bloqueante (< 0,092).

Las misiones abren un PR en el repositorio del sistema. El turno pasa a Diego, que lo revisa e integra. En el guion, la identidad, el encuadre y el programa de riesgos quedan como tres commits del manifiesto froga.yaml —el diff del último muestra los riesgos con sus barreras numéricas fijadas antes de que exista modelo:

Identidad del sistema (froga init + patch) Nerea
Contexto, estándares aplicables y encuadre (crédito Anexo III §5(b) + DORA) Nerea
Programa de riesgos con gates numéricos y firmantes (antes del modelo) Nerea
🛡️ Diego

Diego recibe el PR que abrieron las misiones de Nerea, revisa que el manifiesto sea correcto — nivel high por Anexo III §5(b) (evaluación de solvencia) más DORA Art. 6 (riesgo TIC), normas eu/ai-act@2024 + eu/pren-18228@2026 + iso/23894@2023 + eu/dora@2022 con bloque dora.entity, riesgo de exclusión crediticia injusta con vocabulario completo — e integra el PR. El froga.yaml declarado queda en el repositorio.

🧑‍💻 Marta

Todavía no hay nada que medir, pero Marta deja el reproductor listo en git: el proyecto uv + DVC, el dataset real Statlog German Credit (UCI #144, CC-BY-4.0) con su manifiesto Croissant y el paso de rasgos ya son commits del guion:

Repo, identidad, proyecto uv (uv init + deps), DVC, pubkey y README del reproductor Marta
Comandos
15
  • git init -q -b main
  • git config user.email marta@demo.seigarrena.dev
  • git config user.name "Marta Demo"
  • uv init --bare --name vldemo-loan-scoring --python 3.12
  • patch: pyproject-index.patch
  • uv add "dvc>=3" pyyaml froga "venturalitica==0.6.11" "mlcroissant>=1.0" pyarrow "scikit-learn==1.8.0" fairlearn pandas joblib
  • patch: gitignore.patch
  • patch: gitattributes.patch
  • patch: readme.patch
  • uv sync
  • uv run dvc init --no-scm -q
  • uv run dvc config core.analytics false
  • froga pubkey --out .froga/PUBKEY.txt
  • git add -A
  • git commit -m "init: repo, proyecto uv (deps reales) y README del reproductor"
Dataset German Credit + manifiesto Croissant + versionado DVC Marta
Pipeline de rasgos sobre German Credit — escribe Y corre (dvc repro) Marta

Con el manifiesto declarado y el andamiaje en git, el turno pasa a medir (hito 2).

Venturalíticademo.venturalitica.ai
DeclaradoSiguiente: ejecutar y medir
Venturalíticademo.venturalitica.ai
¿Qué categoría del Anexo III aplica?
¿Qué clase MDR aplica al dispositivo?
¿Algún régimen adicional?
Venturalíticademo.venturalitica.ai
Riesgos significativos
IDTítuloProbabilidadImpacto individualImpacto socialImpacto organizaciónAsignar tratamiento a (opcional)
1
2
3
4
5
2Medir la V1: ámbar honesto, infrapotenciado
🛡️ Diego

Esperando. Nerea ha declarado el sistema y Diego lo ha integrado; ahora Diego espera la primera medición de Marta. No toca la CLI: cuando Marta informe del color de la barrera, verá si la evidencia demuestra el residual o solo lo estima.

🧑‍💻 Marta

Marta mide el sistema tal como está — el riesgo inherente, sin tratar. Primero compila el contrato de la barrera —qué controles se van a medir y con qué umbral—:

Compilar el plan de evaluación OSCAL (antes del modelo) Marta
Comandos
  • froga compile
  • git add -A
  • git commit -m "compile: assessment plan OSCAL (contrato del gate, antes del modelo)"

Ahora añade el modelo base —una regresión logística simple, sin mitigación de equidad— y corre la evidencia:

Modelo logreg base V1 — escribe Y corre (gate ÁMBAR honesto, OOF n=1000) MartaVeredicto esperadoÁMBAR
📍 reproducir loan-v1.0.0-amber
git clone https://github.com/Venturalitica/vldemo-loan-scoring
cd vldemo-loan-scoring
git switch -c try loan-v1.0.0-amber
Comandos
  • patch: params.patch
  • patch: dvc-evaluate.patch
  • patch: train.patch
  • patch: evaluate.patch
  • patch: compliance-eval.patch
  • froga runpuede fallar
  • git add -A
  • git commit -m "modelo: logreg base V1 sin mitigación (train/evaluate + dvc.yaml) — run: V1 evidencia base (gate ÁMBAR infrapotenciado; seed=42)"

El control unfair-credit-exclusion vuelve ÁMBAR, y por qué es ámbar es toda la cuestión:

  • actual_value = 0,1050, barrera < 0,092 → la estimación puntual NO pasa (passed: false): el modelo sin tratar discrimina de verdad, medido con potencia real.
  • El bloque de potencia informa de un IC 95% bootstrap de [0,0425, 0,1702], medido OUT-OF-FOLD sobre las 1.000 filas (690 hombres, 310 mujeres; 5-fold StratifiedKFold — ninguna fila la predice un modelo que la vio entrenar). El extremo inferior, 0,0425, cae por debajo de la línea 0,092.

Así que el intervalo cruza el umbral (por debajo en un extremo, por encima en el otro): el motor no puede demostrar con certeza que la disparidad viole el límite, así que activa inconclusive()ÁMBAR, no un rojo concluyente. Esto es honesto en un sentido distinto al de un dato pequeño: con 1.000 filas la potencia ya es real — el intervalo cruza porque el residual está genuinamente indeciso en ese punto, no porque falten datos. El paquete se firma y ancla de todos modos — un resultado ÁMBAR es evidencia, registrada honestamente.

El riesgo es real y la evidencia inconclusa. Pero antes de tratar, Nerea vuelve a mirar el modelo — y encuentra algo que la barrera no vio.

Venturalíticademo.venturalitica.ai
Evaluado · ÁMBAR
3Revisar la V1: aflora un riesgo de proxy (sin tratar)
🧭 Nerea

Al revisar la evidencia V1, Nerea no mira solo el color de la barrera: mira el modelo. Y ve algo que la barrera de equidad no capturó — el código postal entra como variable. En zonas con segregación residencial, el código postal correlaciona con el origen étnico: el modelo puede aprender a discriminar por un atributo protegido sin usarlo explícitamente. Es el beat A.1.c del proceso ISO 23894 (§6.4.2, análisis del riesgo): un riesgo que aflora al examinar el sistema, no al declararlo de antemano.

Nerea lo declara en el froga.yaml como risk.proxy-discrimination — impacto individual ALTO, probabilidad PROBABLE —, y toma una decisión deliberada: no lo trata todavía. Retirar el código postal degradaría el modelo y hace falta más análisis antes de actuar; así que el riesgo queda identificado pero sin tratar, por encima del apetito individual (above-appetite):

Riesgo de discriminación por proxy identificado (above-appetite, sin tratar) Nerea

Fíjate en lo que no cambia: sin un bloque treat: ni una medida, el riesgo no aporta ningún control_result, así que el color de la barrera no se mueve — sigue ÁMBAR. Un riesgo above-appetite sin tratar no pinta la barrera de rojo por sí mismo; lo que hace es abrir una puerta en la aprobación: alguien tendrá que aceptarlo conscientemente, con motivo, o el sistema no se aprueba. Ese es el segundo residual que viajará hasta el hito de gobernanza.

🛡️ calidad
🧑‍💻 Marta

Esperando. La identificación del riesgo es un acto de gobernanza de la responsable de producto; Marta lo verá reflejado en el manifiesto y sabrá que la aprobación llevará una condición añadida. Su siguiente paso sigue siendo el tratamiento de la equidad.

Venturalíticademo.venturalitica.ai
1 residual para la decisión
Riesgo de proxy above-appetite, sin tratarproxy-discrimination (código postal como proxy de origen étnico) — individual ALTO × PROBABLE; sin measures → el color de la barrera no cambia
4Tratar el riesgo: el número mejora, la potencia no (sigue ámbar)
🛡️ Diego

Esperando. Diego ha visto el ÁMBAR — la barrera es inconclusa, medida OOF sobre las 1.000 filas. No toca git; espera la evidencia vuelta a medir, donde leerá si el tratamiento resuelve la falta de conclusión.

🧑‍💻 Marta

Este es el tratamiento (ISO 23894 §6.5). Como en el Nivel 2, el tratamiento reemplaza train.py: el estimador pasa de una regresión logística plana a un aprendizaje justo con la restricción DemographicParity de fairlearn (ExponentiatedGradient), un cambio de código versionado en git que el motor atribuye al tratamiento del riesgo. El diff es el tratamiento, y en el mismo paso Marta vuelve a correr la barrera:

Abre la rama de tratamiento + mitigación de paridad demográfica fairlearn (§6.5) — escribe Y corre (gate VERDE) MartaVeredicto esperadoÁMBAR
📍 reproducir loan-v2.0.0-green
git clone https://github.com/Venturalitica/vldemo-loan-scoring
cd vldemo-loan-scoring
git switch -c try loan-v2.0.0-green
Comandos
  • git checkout -b tratamiento/mitiga-paridad
  • patch: train.patch
  • froga runpuede fallar
  • git add -A
  • git commit -m "treatment: aplica mitigación de paridad demográfica (fairlearn DemographicParity) sobre el sexo — ISO 23894 §6.5"

Y esta vez la barrera pasa a VERDE, y la razón es el hallazgo honesto del nivel:

  • actual_value = 0,0065 — la estimación puntual cae muy por debajo del 0,1050 de V1, y muy por debajo de la barrera < 0,092.
  • El bloque de potencia: IC 95% bootstrap [0,0010, 0,0645] — el extremo superior queda por debajo del umbral 0,092.

El IC ya no cruza la línea: queda enteramente por debajo. El motor activa adequate()VERDE concluyente. Léelo con precisión: el tratamiento es una intervención real y versionada, y sobre las mismas 1.000 filas medidas OOF, el número baja Y la potencia lo demuestra. No hace falta más dato — el mismo tamaño de muestra que dejó V1 en ÁMBAR certifica V2 en VERDE, porque el residual tratado está genuinamente lejos del umbral.

Tratado, firmado, VERDE concluyente — y el riesgo de proxy sin tratar del hito 3 es lo único que queda para la decisión.

Venturalíticademo.venturalitica.ai
Indeclarado
Declarado
Asegurado
Evaluado
Tratado
Aprobado
Comercializable
5Gobernanza: aprobar con el doble residual en acta y cerrar
🛡️ Diego

Este es el cierre — y el contraste con la retina es la clave. La evidencia VERDE tratada y firmada de Marta está en el repositorio, con la solicitud ya emitida (columna de Marta). Diego revisa el paquete, verifica la firma de Marta y ve la equidad resuelta: el tratamiento demostró el residual, medido OOF sobre las 1.000 filas — ya no hay ámbar que aceptar. Pero quedan las dos condiciones de gobernanza que la barrera nunca mide: proxy-discrimination sigue above-appetite, sin tratar, y el residual de opacidad excede el apetito sin control técnico que lo acote.

Diego aprueba — la aprobación acepta esos dos residuales de gobernanza a la vez: el riesgo de proxy sin tratar y el residual de opacidad. La aprobación es un acto git-nativo y firmado: un acto DSSE .froga/acts/NNNN-approve.json —firmado ECDSA-P256 y verificado contra la clave de Diego declarada en signers:— registra quién aprobó; el commit que lo añade es texto plano, sin firma GPG (no esperes la insignia «Verified» al pincharlo en GitHub), pero el acto sí va criptográficamente firmado; el motivo que acepta ambos residuales queda en el acta del portal (la CLI no admite --reason y lo omite con aviso); y junto al acto va firmada la evidencia (bundle.json.sig y las conformidades). Con la aprobación en la historia, la conformidad se re-emite y la cláusula 11 de prEN 18228 (revisión de gestión de riesgo) pasa de Gap a Cubierta al leer el acto de aprobación:

Aprobar (aceptación consciente del doble residual) Diego
📍 reproducir loan-v2.0.0-approved
git clone https://github.com/Venturalitica/vldemo-loan-scoring
cd vldemo-loan-scoring
git switch -c try loan-v2.0.0-approved
🖊️ Diego aprueba

Motivo: «Aceptación consciente del riesgo residual: proxy-discrimination sigue above-appetite sin tratar (se acepta con motivo) y el residual de opacidad excede el apetito; la equidad medida OUT-OF-FOLD (n=1000) cierra VERDE tras el tratamiento fairlearn. Revisión P6M.»

El motor no borra ninguno de los dos residuales: los ancla en la aprobación, atribuibles y verificables. Esa es la diferencia entre aceptar conscientemente un residual y ocultarlo.

🧑‍💻 Marta

Marta cierra su parte del ciclo desde la CLI. Con la V2 en VERDE firmada, emite la conformidad y el reconstruct sobre las normas aplicables y solicita la aprobación:

Conformance + reconstruct firmados (entitlement de pago + 6 normas) Marta
Comandos
  • patch: entitlement.patch
  • froga conformance --standard eu/pren-18228@2026 --outpuede fallar
  • froga conformance --standard iso/23894@2023 --outpuede fallar
  • froga conformance --standard eu/ai-act@2024 --outpuede fallar
  • froga conformance --standard eu/dora@2022 --outpuede fallar
  • froga conformance --standard eu/pren-18283@2026 --outpuede fallar
  • froga conformance --standard eu/pren-18282@2026 --outpuede fallar
  • froga reconstruct --outpuede fallar
  • git add -A
  • git commit -m ".froga: conformance + reconstruct firmados"
Solicitar aprobación (gate verde; residual proxy/opacidad pendiente de aceptación) Marta
📍 reproducir loan-v2.0.0-request
git clone https://github.com/Venturalitica/vldemo-loan-scoring
cd vldemo-loan-scoring
git switch -c try loan-v2.0.0-request
git commitsolicitud de aprobación (el acto lo commitea froga request)

La aprobación es de Diego (arriba): Marta la solicitó con el acto anterior, no puede concederla ella misma. Cuando el acto firmado .froga/acts/NNNN-approve.json de Diego aterriza —con los dos residuales de gobernanza aceptados conscientemente—, Marta re-emite la conformidad para que froga derive el ciclo de la historia git, ahora con la aprobación real:

Re-emitir conformance tras aprobar (cl.11 = Approved) Marta
Comandos
  • froga conformance --standard eu/pren-18228@2026 --outpuede fallar
  • froga conformance --standard iso/23894@2023 --outpuede fallar
  • froga conformance --standard eu/ai-act@2024 --outpuede fallar
  • froga conformance --standard eu/dora@2022 --outpuede fallar
  • froga conformance --standard eu/pren-18283@2026 --outpuede fallar
  • froga conformance --standard eu/pren-18282@2026 --outpuede fallar
  • froga reconstruct --outpuede fallar
  • git add -A
  • git commit -m ".froga: re-emisión de conformance + reconstruct tras aprobar (cl.11 = Approved)"

El sistema queda declarado, tratado, VERDE, solicitado y aprobado con el doble residual de gobernanza (proxy + opacidad) en acta: el final del arco, con la aprobación de Diego anclada en la etiqueta loan-v2.0.0-approved de arriba.

Venturalíticademo.venturalitica.ai
Indeclarado
Declarado
Asegurado
Evaluado
Tratado
Aprobado
Comercializable
Venturalíticademo.venturalitica.ai

Aprobar con el doble residual en acta

Equidad ya VERDE (tratamiento demostrado, OOF sobre las 1.000 filas) — quedan dos residuales de gobernanza: proxy-discrimination above-appetite sin tratar + opacidad por encima del apetito. Diego acepta ambos de forma consciente, con motivo (autodeclaración Anexo III §5(b)).
Proxy sin tratarproxy-discrimination sigue above-appetite — requiere aceptación consciente con motivo.
OpacidadEl residual de opacidad excede el apetito, sin control técnico que lo acote — requiere aceptación consciente.
6Revisión periódica: la cadena de aprobaciones y el aprobador efectivo
🛡️ Diego

El froga.yaml de crédito declaró review_interval: P6M: una revisión semestral (ISO 23894 §6.6, la supervisión continua del Art. 14). Pasados los seis meses, el portal ofrece la revisión y Diego la ejecuta — y, como en cualquier revisión, reabre el ciclo:

Revisión periódica P6M (la aprobación queda suspendida) Diego
📍 reproducir loan-v2.0.0-review
git clone https://github.com/Venturalitica/vldemo-loan-scoring
cd vldemo-loan-scoring
git switch -c try loan-v2.0.0-review
🖊️ Diego revisa

El motor deriva «en revisión periódica» (froga status: «Sistema en revisión periódica (ISO 23894 §6.6). Compliance debe re-aprobar el sistema.»): la aprobación de arriba queda suspendida. Pero aquí el arco es distinto al del Nivel 2: la evidencia no cambia. No hay nada que re-medir —el doble residual (proxy sin tratar + opacidad) es una decisión de gobernanza, no un número que re-correr—, así que no hay froga run entre medias. Diego revisa el mismo bundle V2 y lo re-aprueba tal cual:

Re-aprobar sobre el mismo bundle (cadena con aprobador efectivo, #667) Diego
📍 reproducir loan-v2.0.0-reapproved
git clone https://github.com/Venturalitica/vldemo-loan-scoring
cd vldemo-loan-scoring
git switch -c try loan-v2.0.0-reapproved
🖊️ Diego aprueba

Motivo: «Re-aprobación tras la revisión periódica (P6M) sobre la MISMA evidencia vigente: se re-confirma la aceptación consciente del doble residual (proxy-discrimination above-appetite sin tratar + opacidad por encima del apetito). El aprobador efectivo del expediente pasa a ser esta re-aprobación (cadena aprobar→revisar→re-aprobar).»

El sistema vuelve a «aprobado», ahora con la cadena completa en el expediente y el aprobador efectivo anclado en la etiqueta loan-v2.0.0-reapproved de arriba.

🧑‍💻 Marta

Esperando — y esta vez el turno de Marta es no actuar. La revisión de un residual de gobernanza (el proxy sin tratar, la opacidad) no exige re-medir: no hay parámetro que cambiar ni barrera que re-correr, la evidencia V2 sigue siendo la vigente. Toda la acción del hito vive en el portal, entre la revisión y la re-aprobación de Diego. Marta lo verá reflejado en la cadena de aprobaciones del expediente, sin un commit suyo de por medio — el contraste exacto con el Nivel 2, donde la revisión devolvió a medir.

Venturalíticademo.venturalitica.ai
1 revisión pendiente
Revisión periódica del riesgo (P6M vencida)El froga.yaml declara review_interval: P6M. Han pasado seis meses desde la aprobación; el portal ofrece la revisión. Al revisar, el ciclo pasa a «en revisión»: la aprobación queda suspendida hasta re-aprobar.
Venturalíticademo.venturalitica.ai

Re-aprobar sobre la misma evidencia

La revisión no cambió la evidencia: el mismo bundle V2, el mismo doble residual. Diego re-confirma la aceptación consciente — y con ello se convierte en el aprobador efectivo del expediente.
Doble residual re-confirmadoproxy-discrimination above-appetite sin tratar + opacidad por encima del apetito — re-aceptados conscientemente con motivo en la re-aprobación.