Level 4 · The arc, by handoffs
The arc, by handoffs
Section titled “The arc, by handoffs”Six beats. As in previous levels, all three roles are present from the first: 🧭 Nerea at the top (portal · product), 🛡️ James in the middle (portal · quality), 🧑💻 Martha on the right (CLI + git). The lesson of this arc is AMBER → GREEN —a real, honest inconclusiveness that genuinely resolves once measured with real power (OUT-OF-FOLD over all 1,000 rows, not a 200-row held-out)— with a proxy risk that surfaces when reviewing the model and is left untreated, closing with a legitimate approval that consciously accepts that residual. And a new sixth beat: the periodic review that reopens that approval and forms an approval chain with an effective approver — the party of record ultimately accountable.
The hard data in each beat —the commands, the commit message, the diff and the gate colour— is not hand-written: every GuionStep block reads it from the repository’s steps/ script. Were a step to not exist, the build would fail; what you read here is exactly what the repository does. The commands and commit messages are the verbatim Spanish artefacts of the repo you clone.
Nerea is the Product Owner at NovaCredit, a credit institution deploying a scoring model. She opens the portal and runs the authoring missions that generate the governance manifest froga.yaml. Three things matter:
- The tier is
high, declared by a human, via the use route. Theclassify-systemmission fills in theclassificationblock with the basis: “EU AI Act Annex III §5(b) (creditworthiness evaluation / credit scoring)” — plus “DORA Art. 6 (ICT risk of the financial entity)”. The high-risk trigger here is Annex III §5(b), not Art. 6(1). The engine does not infer it; Nerea declares it and owns it. - Two regimes are declared, and one is the overlay. The
declare-standardsmission writesapplicable_standardswith the spine (eu/ai-act@2024,eu/pren-18228@2026,iso/23894@2023) pluseu/dora@2022— the DORA overlay — with adora.entityblock (the LEI, the entity typecredit_institution). Declaringeu/dora@2022is what makes the engine assemble the DORA Register later. - The risk is unfair credit exclusion. The
identify-risksmission addsrisk.unfair-credit-exclusion— “the model may unjustly exclude protected groups by inheriting historical patterns of discrimination.” The control that will confirm the residual is demographic-parity difference — a blocking fairness gate (< 0.092).
The missions open a PR in the system’s repository. The turn passes to James, who reviews and merges it. In the script, the identity, the framing and the risk programme land as three froga.yaml manifest commits —the diff of the last one shows the risks with their numeric gates fixed before any model exists:
James receives the PR opened by Nerea’s missions, reviews that the manifest is correct — tier high via Annex III §5(b) (creditworthiness) plus DORA Art. 6 (ICT risk), standards eu/ai-act@2024 + eu/pren-18228@2026 + iso/23894@2023 + eu/dora@2022 with a dora.entity block, unfair-credit-exclusion risk in full vocabulary — and merges it. The declared froga.yaml is now in the repository.
There is nothing to measure yet, but Martha leaves the reproducer ready in git: the uv + DVC project, the real Statlog German Credit dataset (UCI #144, CC-BY-4.0) with its Croissant manifest, and the featurization step are already script commits:
15
git init -q -b maingit config user.email marta@demo.seigarrena.devgit config user.name "Marta Demo"uv init --bare --name vldemo-loan-scoring --python 3.12patch: pyproject-index.patchuv add "dvc>=3" pyyaml froga "venturalitica==0.6.11" "mlcroissant>=1.0" pyarrow "scikit-learn==1.8.0" fairlearn pandas joblibpatch: gitignore.patchpatch: gitattributes.patchpatch: readme.patchuv syncuv run dvc init --no-scm -quv run dvc config core.analytics falsefroga pubkey --out .froga/PUBKEY.txtgit add -Agit commit -m "init: repo, proyecto uv (deps reales) y README del reproductor"
With the manifest declared and the scaffolding in git, the turn passes to measuring (beat 2).
Waiting. Nerea has declared the system and James has merged it; now James waits for Martha’s first measurement. He does not touch the CLI: when Martha reports the gate colour, he will see whether the evidence proves the residual or only estimates it.
Martha measures the system as it stands — the inherent risk, untreated. First she compiles the gate contract —which controls will be measured and with what threshold—:
froga compilegit add -Agit commit -m "compile: assessment plan OSCAL (contrato del gate, antes del modelo)"
Now she adds the base model —a plain logistic regression with no fairness mitigation— and runs the evidence:
patch: params.patchpatch: dvc-evaluate.patchpatch: train.patchpatch: evaluate.patchpatch: compliance-eval.patchfroga runmay failgit add -Agit commit -m "modelo: logreg base V1 sin mitigación (train/evaluate + dvc.yaml) — run: V1 evidencia base (gate ÁMBAR infrapotenciado; seed=42)"
The unfair-credit-exclusion control comes back AMBER, and why it is amber is the whole point:
actual_value = 0.1050, gate< 0.092→ the point estimate fails (passed: false): the untreated model genuinely discriminates, measured with real power.- The power block reports a bootstrap 95% CI of
[0.0425, 0.1702], measured OUT-OF-FOLD over all 1,000 rows (690 men, 310 women; 5-foldStratifiedKFold— every row is predicted by a model that never saw it train). The lower edge, 0.0425, falls below the 0.092 line.
So the interval straddles the threshold from both sides: the engine cannot prove with certainty that the disparity breaches the limit, so it fires inconclusive() → AMBER, not a conclusive red. This is honest in a different sense than a small sample: with 1,000 rows the power is real — the interval straddles because the untreated residual is genuinely close to the threshold, not because data is missing. The bundle is signed and anchored regardless — an AMBER result is evidence, recorded honestly.
The risk is real and the evidence inconclusive. But before treating, Nerea takes another look at the model — and finds something the gate did not see.
Reviewing the V1 evidence, Nerea does not just look at the gate colour: she looks at the model. And she sees something the fairness gate did not capture — the postal code enters as a feature. In areas with residential segregation, the postal code correlates with ethnic origin: the model can learn to discriminate on a protected attribute without using it explicitly. This is the A.1.c beat of the ISO 23894 process (§6.4.2, risk analysis): a risk that surfaces when you examine the system, not when you declare it up front.
Nerea declares it in froga.yaml as risk.proxy-discrimination — individual impact HIGH, likelihood LIKELY —, and makes a deliberate choice: she does not treat it yet. Removing the postal code would degrade the model and it needs more analysis before acting; so the risk stays identified but untreated, above the individual appetite (above-appetite):
Note what does not change: with no treat: block and no measure, the risk contributes no control_result, so the gate colour does not move — it stays AMBER. An above-appetite untreated risk does not paint the gate red by itself; what it does is open a gate in the approval: someone will have to accept it consciously, with a reason, or the system is not approved. That is the second residual that will travel to the governance beat.
Waiting. Identifying the risk is a governance act by the Product Owner; Martha will see it reflected in the manifest and know the approval will carry an added condition. Her next step is still the fairness treatment.
Waiting. James has seen the AMBER — the gate is inconclusive, measured OOF over all 1,000 rows. He does not touch git; he waits for the re-measured evidence, where he will read whether the treatment resolves the inconclusiveness.
This is the treatment (ISO 23894 §6.5). As in Level 2, the treatment replaces train.py: the estimator goes from a plain logistic regression to a fairness-aware learner with fairlearn’s DemographicParity constraint (ExponentiatedGradient), a versioned code change in git that the engine attributes the risk treatment to. The diff is the treatment, and the same step runs the gate again:
git checkout -b tratamiento/mitiga-paridadpatch: train.patchfroga runmay failgit add -Agit commit -m "treatment: aplica mitigación de paridad demográfica (fairlearn DemographicParity) sobre el sexo — ISO 23894 §6.5"
And this time the gate turns GREEN, and the reason is the honest finding of the level:
actual_value = 0.0065— the point estimate drops far below V1’s 0.1050, and far below the< 0.092gate.- The power block: bootstrap 95% CI
[0.0010, 0.0645]— the upper edge sits below the 0.092 threshold.
The CI no longer crosses the line: it lands entirely below it. The engine fires adequate() → conclusive GREEN. Read it precisely: the treatment is a real, versioned intervention, and on the same 1,000 rows measured OOF, the number drops AND the power proves it. No extra data was needed — the same sample size that left V1 in AMBER certifies V2 GREEN, because the treated residual sits genuinely far from the threshold.
Treated, signed, conclusively GREEN — and the untreated proxy risk from beat 3 is the only thing left for the decision.
This is the close — and the contrast with retina is the point. Martha’s treated, signed GREEN evidence is in the repo, with the request already emitted (Martha’s column). James reviews the bundle, verifies Martha’s signature, and sees fairness resolved: the treatment demonstrated the residual, measured OOF over all 1,000 rows — no amber left to accept. But two governance conditions remain, the ones the gate never measures: proxy-discrimination stays above-appetite, untreated, and the opacity residual exceeds appetite with no technical control bounding it.
James approves — the approval accepts those two governance residuals at once: the untreated proxy risk and the opacity residual. The approval is a git-native, signed act: a DSSE act .froga/acts/NNNN-approve.json —signed ECDSA-P256 and verified against James’s key declared in signers:— records who approved; the commit that adds it is plain text, no GPG signature (do not expect the «Verified» badge when you click it on GitHub), but the act itself is cryptographically signed; the reason that accepts both residuals lives in the portal record (the CLI does not take --reason and drops it with a warning); and alongside the act the evidence is signed (bundle.json.sig and the conformances). With the approval in history, conformance is re-emitted and prEN 18228 clause 11 (risk management review) turns from Gap to Covered on reading the approval act:
Reason: «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.»
The engine erases neither residual: it anchors them in the approval, attributable and verifiable. That is the difference between consciously accepting a residual and hiding it.
Martha closes her part of the cycle from the CLI. With V2 GREEN signed, she emits the conformance and reconstruct over the applicable standards and requests approval:
patch: entitlement.patchfroga conformance --standard eu/pren-18228@2026 --outmay failfroga conformance --standard iso/23894@2023 --outmay failfroga conformance --standard eu/ai-act@2024 --outmay failfroga conformance --standard eu/dora@2022 --outmay failfroga conformance --standard eu/pren-18283@2026 --outmay failfroga conformance --standard eu/pren-18282@2026 --outmay failfroga reconstruct --outmay failgit add -Agit commit -m ".froga: conformance + reconstruct firmados"
solicitud de aprobación (el acto lo commitea froga request)The approval is James’s (above): Martha requested it with the act before, she cannot grant it herself. Once James’s signed act .froga/acts/NNNN-approve.json lands —with both governance residuals consciously accepted—, Martha re-emits conformance so that froga derives the cycle from the git history, now with the real approval:
froga conformance --standard eu/pren-18228@2026 --outmay failfroga conformance --standard iso/23894@2023 --outmay failfroga conformance --standard eu/ai-act@2024 --outmay failfroga conformance --standard eu/dora@2022 --outmay failfroga conformance --standard eu/pren-18283@2026 --outmay failfroga conformance --standard eu/pren-18282@2026 --outmay failfroga reconstruct --outmay failgit add -Agit commit -m ".froga: re-emisión de conformance + reconstruct tras aprobar (cl.11 = Approved)"
The system ends up declared, treated, GREEN, requested and approved with the double governance residual (proxy + opacity) on record: the end of the arc, with James’s approval anchored at the loan-v2.0.0-approved tag above.
Approve with the double residual on record
Fairness is now GREEN (treatment demonstrated, OOF over all 1,000 rows) — two governance residuals remain: above-appetite untreated proxy-discrimination + opacity above appetite. James accepts both consciously, with a reason (Annex III §5(b) self-declaration).The credit froga.yaml declared review_interval: P6M: a semi-annual review (ISO 23894 §6.6, the continual oversight of Art. 14). Past the six months, the portal offers the review and James runs it — and, as with any review, it reopens the cycle:
The engine derives «under periodic review» (froga status: the system is under periodic review (ISO 23894 §6.6); compliance must re-approve it): the approval above is suspended. But here the arc differs from Level 2’s: the evidence does not change. There is nothing to re-measure —the double residual (untreated proxy + opacity) is a governance decision, not a number to re-run—, so there is no froga run in between. James reviews the same V2 bundle and re-approves it as is:
Reason: «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).»
The system returns to «approved», now with the full chain in the record and the effective approver anchored at the loan-v2.0.0-reapproved tag above.
Waiting — and this time Martha’s turn is not to act. Reviewing a governance residual (the untreated proxy, the opacity) does not require re-measuring: there is no parameter to change nor gate to re-run, the V2 evidence is still current. All of the beat’s action lives in the portal, between James’s review and re-approval. Martha will see it reflected in the record’s approval chain, with no commit of her own in between — the exact contrast with Level 2, where the review did send you back to measure.