Skip to content

Energy · Research 004 · distributed wind

Wind power that proves its decisions. Assurance for every turbine’s supervisor.

A distributed wind system decides all day: charge, export, curtail, protect the critical load. We build the component that checks every one of those decisions against the turbine’s real limits before it is acted on, and hands back a certificate anyone can re-check.

Proof network · 149 modules · 818 checked dependencies

Agda 2.8.0 · --safe · --without-K

Target 01 · Curtailment, bounded

curtailed ≥ supply − headroom

Wind is curtailed only for a proved reason; a full battery is never counted as a sink.

Proved · for every state

Drag to turn it. Each node is a module of the toolkit, sized by its length, and each line is an import the proof kernel re-checks; wind & storage in verdigris. The neighbourhood coordinator is checked with everything else and drawn as one sealed node: its engine is not published.

21 of 48 phases closed · allocation in progress · proposed to NLR’s 2026 Competitiveness Improvement Project with Uprise Energy

01 · For turbine makers

More of your turbine’s energy, used safely, with the evidence attached.

Distributed wind is sold on reliability. Every curtailment, export and reserve decision is a place where a controller can be wrong in a way no one sees until a battery overcharges or a limit trips. The component makes each decision provably admissible and leaves an audit trail a utility, insurer or certification body can read.

  • A full battery is never treated as a sink

    The checker refuses any dispatch that counts on storage that cannot absorb. Curtailment is bounded below by what the loads and the battery genuinely cannot take, so wind is never curtailed for an unproved reason and never sent where it cannot go.

    The theorem: curtail-lower-bound ↓
  • The power curve, read correctly across an interval

    A forecast is a range of wind speeds, not a number. Reading the power curve only at the range’s two ends is wrong near cut-out: a storm interval’s lower end gives full power while its upper end gives none. The toolkit computes the true envelope, and proves it is both sound and tight.

    The theorem: gen-sound ↓
  • Absorption within the limit, from every state

    Every modelled state of the wind, storage and load system is either within the absorption limit already, or one absorb step brings it there. Not on the cases we tried: for all of them.

    The theorem: modelledAbsorptionWithinLimit ↓
  • Your protection stays yours

    The component is advisory and sits beside the controller, never in place of it. The OEM keeps protection, interlocks and deployment authority; the checker only decides which proposed actions are admissible, and records why.

  • Evidence a certification body can read

    Every requirement links to a proof, test, analysis or stated limitation, with the edition of each standard recorded. A qualification roadmap maps ANSI/ACP 101-1, IEC 61400-2 and the applicable UL requirements to the future integration, so the next engineering step is clear before it is taken.

  • Reusable across turbines, without borrowing safety

    The same typed interface serves other distributed-wind architectures, cutting duplicated schema validation, negative tests and evidence work. Each new turbine brings its own model contract and limits; nothing is transferred by assumption.


02 · The power curve, under uncertainty

Near cut-out, the obvious arithmetic is wrong.

A supervisor plans on a forecast, and a forecast is a range. Reading the curve at the range’s two ends looks reasonable and fails exactly in a storm, where one end gives full power and the other gives none. Try it: this is the toolkit’s own curve, evaluated exactly in your browser.

A forecast is a range of wind speeds. Choose one:

0 kW4 kW8 kW12 kW051015202530wind speed at the hub, m/scut-out
The modelled 12-kW-class curve: cut-in 3 m/s, rated 11 m/s, cut-out 25 m/s, in exact integer arithmetic, as in the proved model. Stipple: the forecast interval. Right edge: the true envelope (verdigris) and the ends-only reading (brass).

Generation the supervisor can count on

0 kW – 12 kW

the proved envelope: it contains every outcome, and its top is reached

Reading only the ends

12 kW – 0 kW

Wrong: it promises at least 12 kW, but a wind inside this range shuts the turbine down. A plan built on it would fall short exactly when it matters.


03 · How it works

One untrusted proposer. One independent checker.

The design separates finding a good action from deciding that it is safe. Anything may propose; only a small, proved checker admits, and every admission carries a certificate an open verifier re-checks.

  1. 01

    Wind · storage · loads · EV

    turbine, battery, critical loads, chargers

    Chora.Wind* · GEC.Model.*

  2. 02

    Typed snapshot

    every reading an interval, with units, sign, time and epoch

    GEC.Verify.Format · HomeFormat

  3. 03

    Proposer

    deterministic policy, forecast or AI model

    GEC.Home.Allocate* · Fill

  4. 04

    Independent checker

    proved in safe Agda, extracted to native code

    GEC.Verify.Proposal · Cert

  5. 05

    Admitted, with a certificate

    or refused, with its named reason and a safe fallback

    GEC.Home.Protect* · Recover*

  6. 06

    Open verifier & evidence ledger

    anyone re-checks; evidence typed and invalidated on change

    GEC.Verify.Evidence · Profile · Log

Demonstrator A · the 12-kW reference

A wind, storage and critical-load system anchored to Uprise Energy’s 12-kW Mobile Power Station, with high wind, a full battery and no sink among its named scenarios.

Demonstrator B · a public feeder

An EVI-DiST distribution feeder with wind, storage, EV charging and other demand, on public SMART-DS data, so anyone can reproduce it.

The neighbourhood coordinator

Above the homes, a coordinator shares a transformer between them. It is proved and checked with the rest; its engine stays with us, and its every decision is re-checkable with the open verifier.


04 · Safe AI integration

Let the AI propose. Let the mathematics decide.

Forecasting and optimisation models can find value a fixed rule leaves on the table. The architecture keeps that value and removes the risk: an AI may estimate generation and demand or propose a dispatch, but it cannot change the admissibility rules, the evidence format or the protection envelope.

In practice

  • A proposal is checked against every world consistent with the measured intervals, not one guess.
  • The checker is exact: no refusal on a corner case is a false alarm, and forced refusals are named.
  • A universal safe fallback passes whenever any proposal could; if it fails, the system says the envelope itself must change.
  • A deterministic proposer and the AI path share one interface, so their outcomes are compared on identical inputs.

05 · Cyber-resilience

Stale, replayed or forged inputs cannot buy authority.

Many attacks on control systems do not break cryptography; they replay an old message, reorder readings or exploit the gap between a command received and a command executed. The model checks these by construction.

In practice

  • Messages from an obsolete configuration epoch cannot authorise a new action.
  • Duplicate requests are idempotent; a reservation persists until its release event.
  • An acknowledgement is not treated as execution: caps stay in flight until the shed is confirmed.
  • Inconsistent units or power signs, out-of-range values and missing readings yield an explicit refusal, never a silent guess.

06 · On NLR’s EVI-DiST

We ran the laboratory’s own tool, and proved what it does.

EVI-DiST co-simulates EV charging with the distribution grid. We integrated it unmodified, reproduced its results exactly, and turned what it guarantees, and where it stops, into theorems.

Share of the EV energy asked for that is delivered
RegionEVI-DiST smart policiesSound ledger budget
GSO54.8–54.9%97.4–97.5%
AUS58.4–58.5%97.4%
SFO50.2–51.5%98.4%

Public NREL SMART-DS feeders (Greensboro, Austin, San Francisco), EVI-DiST pinned at a released revision. The ledger column is the ceiling a sound budget reaches under the same policies: the bound the controller rounds are built to approach.

Integrated, unmodified, reproduced exactly

EVI-DiST was pinned at a released revision and run as published on public NREL SMART-DS feeders. A gridless model written from its own allocation code reproduces every EV’s delivered energy to 10⁻¹¹ kWh across nine smart runs, and every transformer’s loading exactly.

The smart policies are open-loop

They subtract a fixed published base load from each transformer’s rating and receive no feedback from the grid; a closed-loop variant, a different ordering and a different floor each fail to reproduce the runs.

The obvious fix overloads; the proved one does not

Taking the measured load naively delivers all the energy but overloads 6–63 transformers, through a base-load ramp landing on an allocation made a step earlier. Under compliance latency 1–3 the proved ledger has zero model overloads, against 6–64 for the obvious rule, and the only physical residual left is line losses, at most 0.432 kVA.

A season the reference tool could not simulate

Its smart policies silently starve on any day but 1 January; season-faithful runs of six world-and-weather scenarios, from a cold snap to a heat wave, run 3.5–7.4× faster, value for value.


07 · Better science, better models

Sensor data you can trust makes predictive models you can trust.

Every reading enters as an interval with its source, time and epoch. Evidence keeps its class: a formal proof, a measurement and a third-party fact can never be promoted into one another, which is a theorem of the shipped checker. When a model weight, calibration or standard edition changes, everything that depended on it is invalidated until it is re-checked.

In practice

  • Training and forecasting data carry their provenance, so a model is only as confident as its inputs allow.
  • Predictive models are scored against the same certified record the controller uses.
  • The same discipline underpins our verifiable sensor data research at the apiary.

08 · Interpretability by construction

Every verdict explains itself, in mathematics.

Because the system is written in a formal language, its decisions are not opaque outputs to be explained afterwards. Each admitted or refused action carries the requirement it was checked against, the assumptions it relied on and a certificate an independent verifier re-checks. The statements themselves render as mathematics a reviewer can read.

In practice

  • Open verifier: anyone can re-check a decision without trusting the code that made it.
  • Requirement profiles are data, checked by one generic, proved verifier.
  • Semantic integration: the same formal objects connect protocols, devices and models, so meaning survives each interface.

09 · The proofs

24 statements, each for every case.

Open any one. Each is a theorem checked by the Agda proof kernel in safe mode, typeset as mathematics by our certified renderer wherever its certificate verifies, with its module, its dependencies and the hash of the source it came from.

24 published statements · 12 typeset from certificates verified for this page; the other 12 shown verbatim from source, each with the renderer’s reason

Wind & storage

The turbine’s power curve, absorption and curtailment.

01pc-boundThe modelled turbine never produces more than its rated power, at any wind speed.proved · shown verbatim
pc-bound :
  (v : Nat) → WM.powerCurve v ≤ WM.prated

Shown verbatim: the renderer does not yet read this module’s qualified imports (error:no_sir_line). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.ChoraBridge · line 169
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
7 modules, every one checked
Source
sha256 974b2a099284d02c…
Rendering
no certificate yet
02gen-soundFor any interval of wind speeds, the computed power bounds contain the turbine’s output at every speed in it.proved · shown verbatim
gen-sound :
  (I : WS.Interval) (v : Nat) → v WS.∈ I → (genLo I ≤ WM.powerCurve v) × (WM.powerCurve v ≤ genHi I)

Shown verbatim: the renderer does not yet read this module’s qualified imports (error:no_sir_line). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.ChoraBridge · line 211
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
7 modules, every one checked
Source
sha256 974b2a099284d02c…
Rendering
no certificate yet
03genHi-attainedThe upper bound is not loose: some wind speed in the interval actually produces it.proved · shown verbatim
genHi-attained :
  (I : WS.Interval) → lo I ≤ hi I → Σ Nat (λ v → Within v I × (WM.powerCurve v ≡ genHi I))

Shown verbatim: the renderer does not yet read this module’s qualified imports (error:no_sir_line). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.ChoraBridge · line 222
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
7 modules, every one checked
Source
sha256 974b2a099284d02c…
Rendering
no certificate yet
04naive-lo-unsoundReading the curve only at an interval’s ends is wrong near cut-out: one end gives 12 kW, the other end 0.proved · shown verbatim
naive-lo-unsound :
  (WM.powerCurve (lo stormI) ≡ 12000) × (WM.powerCurve 26000 ≡ 0) × ((hi stormI <ᵇ 26000) ≡ false)

Shown verbatim: the renderer does not yet read this module’s qualified imports (error:no_sir_line). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.ChoraBridge · line 342
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
7 modules, every one checked
Source
sha256 974b2a099284d02c…
Rendering
no certificate yet
05absorb-soundFrom every state, the absorb action meets the absorption contract at the generation cap.proved · shown verbatim
absorb-sound :
  (s : EState) → AbsorbOK (absorbS s) (just (capS s))

Shown verbatim: the renderer does not yet read this module’s qualified imports (error:no_sir_line). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.Signed · line 436
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
3 modules, every one checked
Source
sha256 4ee72ebeee95d006…
Rendering
no certificate yet
06curtail-lower-boundAny admissible absorption curtails at least the local supply that the headroom cannot take.proved · shown verbatim
curtail-lower-bound :
  (t : EState) (mc : Maybe Nat) → AbsorbOK t mc → localSupply t - headroom t ≤ curtailed t mc

Shown verbatim: the renderer does not yet read this module’s qualified imports (error:no_sir_line). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.Signed · line 444
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
3 modules, every one checked
Source
sha256 4ee72ebeee95d006…
Rendering
no certificate yet
07modelledAbsorptionWithinLimitEvery state is within the absorption limit, or one absorb step brings it there.proved · shown verbatim
modelledAbsorptionWithinLimit :
  (x : SState) → AbsOK x ⊎ Σ SState (λ y → (sstep x absorb ≡ just y) × AbsOK y)

Shown verbatim: the renderer’s display probe declined this statement (refuse:probe_rejected). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.SignedHome · line 131
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
13 modules, every one checked
Source
sha256 1c6cfa7a284b7eac…
Rendering
no certificate yet

The independent checker

What any proposer, AI included, must pass.

08proposal-soundAn accepted proposal meets its guarantee in every world consistent with the measured intervals.proved · certified rendering
∀(pol:GEC.Verify.Proposal.Policy),∀(h:GEC.Verify.Proposal.HomeCert),∀(pr:GEC.Verify.Proposal.Proposal),∀(w:GEC.Verify.Proposal.World),(GEC.Verify.Proposal.InBoxhprw)→GEC.Verify.Proposal.Guarantee(pol.GEC.Verify.Proposal.Policy.band)(h.GEC.Verify.Proposal.HomeCert.cap)(h.GEC.Verify.Proposal.HomeCert.E)w(GEC.Verify.Proposal.checkProposalpolhpr)piVRWCxpolGEC.Verify.Proposal.PolicypiVRWCxhGEC.Verify.Proposal.HomeCertpiVRWCxprGEC.Verify.Proposal.ProposalpiVRWCxwGEC.Verify.Proposal.WorldpiVRWCx_GEC.Verify.Proposal.InBoxhVRWCxprVRWCxwVRWCxGEC.Verify.Proposal.GuaranteepolGEC.Verify.Proposal.Policy.bandVRWCxhGEC.Verify.Proposal.HomeCert.capVRWCxhGEC.Verify.Proposal.HomeCert.EVRWCxwVRWCxGEC.Verify.Proposal.checkProposalpolVRWCxhVRWCxprVRWCxVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
proposal-sound :
  (pol : Policy) (h : HomeCert) (pr : Proposal) (w : World) → InBox h pr w → Guarantee (band pol) (cap h) (E h) w (checkProposal pol h pr)
Module
GEC.Verify.Proposal · line 440
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
1 module, every one checked
Source
sha256 53b2f98a4fdc3793…
Rendering
certificate 4e410206bb2cfe80… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Proposal.agda sha256 53b2f98a4fdc3793
09imp-boundThe checker’s worst-case grid import bounds the import of every consistent world.proved · certified rendering
∀(h:GEC.Verify.Proposal.HomeCert),∀(pr:GEC.Verify.Proposal.Proposal),∀(w:GEC.Verify.Proposal.World),(GEC.Verify.Proposal.InBoxhprw)→GEC.Verify.Base._≤_(GEC.Verify.Proposal.impWw)(GEC.Verify.Proposal.impWorsthpr)piVRWCxhGEC.Verify.Proposal.HomeCertpiVRWCxprGEC.Verify.Proposal.ProposalpiVRWCxwGEC.Verify.Proposal.WorldpiVRWCx_GEC.Verify.Proposal.InBoxhVRWCxprVRWCxwVRWCxGEC.Verify.Base._≤_GEC.Verify.Proposal.impWwVRWCxVRWCxGEC.Verify.Proposal.impWorsthVRWCxprVRWCxVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
imp-bound :
  (h : HomeCert) (pr : Proposal) (w : World) → InBox h pr w → impW w ≤ impWorst h pr
Module
GEC.Verify.Proposal · line 249
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
1 module, every one checked
Source
sha256 53b2f98a4fdc3793…
Rendering
certificate 369660e617603c14… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Proposal.agda sha256 53b2f98a4fdc3793
10checkSoundAny step certificate the checker accepts describes a valid step.proved · certified rendering
∀(c:GEC.Verify.Format.StepCert),((GEC.Verify.Cert.checkc)≡true)→GEC.Verify.Cert.ValidStepcpiVRWCxcGEC.Verify.Format.StepCertpiVRWCx_Agda.Builtin.Equality._≡_levellmax0HRWCxAgda.Builtin.Bool.BoolHRWCxGEC.Verify.Cert.checkcVRWCxVRWCxAgda.Builtin.Bool.Bool.trueVRWCxGEC.Verify.Cert.ValidStepcVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
checkSound :
  (c : StepCert) → check c ≡ true → ValidStep c
Module
GEC.Verify.Cert · line 59
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
2 modules, every one checked
Source
sha256 154518ace2eb0c05…
Rendering
certificate 7295fcbf6108bc19… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Cert.agda sha256 154518ace2eb0c05
11runSafeA run of checked certificates, with a plant that follows them, keeps the budget at every step.proved · certified rendering
GEC.Verify.Cert.RunSafeWithGEC.Verify.Cert.checkGEC.Verify.Cert.PlantFollowsGEC.Verify.Cert.RunSafeWithGEC.Verify.Cert.checkVRWCxGEC.Verify.Cert.PlantFollowsVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
runSafe :
  RunSafeWith check PlantFollows
Module
GEC.Verify.Cert · line 153
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
2 modules, every one checked
Source
sha256 154518ace2eb0c05…
Rendering
certificate b6317f764e64007e… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Cert.agda sha256 154518ace2eb0c05
12noRamp-unsafeA checker that ignores load ramps is provably not safe: the ramp clause is necessary.proved · certified rendering
GEC.Verify.Base.¬_(GEC.Verify.Cert.RunSafeWithGEC.Verify.Cert.checkNoRampGEC.Verify.Cert.PlantFollows)GEC.Verify.Base.¬_GEC.Verify.Cert.RunSafeWithGEC.Verify.Cert.checkNoRampVRWCxGEC.Verify.Cert.PlantFollowsVRWCxVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
noRamp-unsafe :
  ¬ RunSafeWith checkNoRamp PlantFollows
Module
GEC.Verify.Cert · line 224
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
2 modules, every one checked
Source
sha256 154518ace2eb0c05…
Rendering
certificate c95eccc08a34418e… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Cert.agda sha256 154518ace2eb0c05

Evidence & requirements

Evidence that cannot be promoted, and goes stale when it should.

13no-promotionNo rule can turn formal and physical evidence into a third-party fact: evidence classes never promote.proved · certified rendering
GEC.Verify.Base.¬_(∀(reg:GEC.Verify.Evidence.Registry),∀(now:ℕ),∀(cfg:ℕ),GEC.Verify.Evidence.Formal→GEC.Verify.Evidence.Physical→GEC.Verify.Evidence.Externalregnowcfg)GEC.Verify.Base.¬_piVRWCxregGEC.Verify.Evidence.RegistrypiVRWCxnowAgda.Builtin.Nat.NatpiVRWCxcfgAgda.Builtin.Nat.NatpiVRWCx_GEC.Verify.Evidence.FormalpiVRWCx_GEC.Verify.Evidence.PhysicalGEC.Verify.Evidence.ExternalregVRWCxnowVRWCxcfgVRWCxVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
no-promotion :
  ¬ ((reg : Registry) (now cfg : Nat) → Formal → Physical → External reg now cfg)
Module
GEC.Verify.Evidence · line 57
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
1 module, every one checked
Source
sha256 58ab03e50aa4039c…
Rendering
certificate 9714eba04e599ae7… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Evidence.agda sha256 58ab03e50aa4039c
14invalidation-soundChanging any input invalidates every result that depends on it.proved · certified rendering
∀(g:GEC.Verify.Evidence.Graph),∀(ch:Listℕ),(GEC.Verify.Evidence.Topog)→∀{x:ℕ},∀{c:ℕ},(GEC.Verify.Evidence.Depgxc)→(GEC.Verify.Base._∈_{ℕ}cch)→(GEC.Verify.Evidence.invalidgchx)≡truepiVRWCxgGEC.Verify.Evidence.GraphpiVRWCxchAgda.Builtin.List.Listlevellmax0HRWCxAgda.Builtin.Nat.NatVRWCxpiVRWCx_GEC.Verify.Evidence.TopogVRWCxpiHRWCxxAgda.Builtin.Nat.NatpiHRWCxcAgda.Builtin.Nat.NatpiVRWCx_GEC.Verify.Evidence.DepgVRWCxxVRWCxcVRWCxpiVRWCx_GEC.Verify.Base._∈_Agda.Builtin.Nat.NatHRWCxcVRWCxchVRWCxAgda.Builtin.Equality._≡_levellmax0HRWCxAgda.Builtin.Bool.BoolHRWCxGEC.Verify.Evidence.invalidgVRWCxchVRWCxxVRWCxVRWCxAgda.Builtin.Bool.Bool.trueVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
invalidation-sound :
  (g : Graph) (ch : List Nat) → Topo g → {x c : Nat} → Dep g x c → c ∈ ch → invalid g ch x ≡ true
Module
GEC.Verify.Evidence · line 220
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
1 module, every one checked
Source
sha256 58ab03e50aa4039c…
Rendering
certificate 903e67321fec8312… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Evidence.agda sha256 58ab03e50aa4039c
15checkProfileSoundThe requirement-profile checker reports exactly each clause’s entry, and each is faithful to the stream.proved · certified rendering
∀(p:GEC.Verify.Profile.Profile),∀(s:GEC.Verify.Profile.Stream),∀(es:ListGEC.Verify.Profile.Entry),((GEC.Verify.Profile.checkProfileps)≡(GEC.Verify.Profile.Outcome.reportedes))→GEC.Verify.Base._×_(es≡(GEC.Verify.Base.map{GEC.Verify.Profile.Clause}{GEC.Verify.Profile.Entry}(GEC.Verify.Profile.entryOfs)(p.GEC.Verify.Profile.Profile.clauses)))(GEC.Verify.Base.All{GEC.Verify.Profile.Clause}(GEC.Verify.Profile.Faithfuls)(p.GEC.Verify.Profile.Profile.clauses))piVRWCxpGEC.Verify.Profile.ProfilepiVRWCxsGEC.Verify.Profile.StreampiVRWCxesAgda.Builtin.List.Listlevellmax0HRWCxGEC.Verify.Profile.EntryVRWCxpiVRWCx_Agda.Builtin.Equality._≡_levellmax0HRWCxGEC.Verify.Profile.OutcomeHRWCxGEC.Verify.Profile.checkProfilepVRWCxsVRWCxVRWCxGEC.Verify.Profile.Outcome.reportedesVRWCxVRWCxGEC.Verify.Base._×_Agda.Builtin.Equality._≡_levellmax0HRWCxAgda.Builtin.List.Listlevellmax0HRWCxGEC.Verify.Profile.EntryVRWCxHRWCxesVRWCxGEC.Verify.Base.mapGEC.Verify.Profile.ClauseHRWCxGEC.Verify.Profile.EntryHRWCxGEC.Verify.Profile.entryOfsVRWCxVRWCxpGEC.Verify.Profile.Profile.clausesVRWCxVRWCxVRWCxGEC.Verify.Base.AllGEC.Verify.Profile.ClauseHRWCxGEC.Verify.Profile.FaithfulsVRWCxVRWCxpGEC.Verify.Profile.Profile.clausesVRWCxVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
checkProfileSound :
  (p : Profile) (s : Stream) (es : List Entry) → checkProfile p s ≡ reported es → (es ≡ map (entryOf s) (clauses p)) × All (Faithful s) (clauses p)
Module
GEC.Verify.Profile · line 967
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
4 modules, every one checked
Source
sha256 0409565626ed0e5d…
Rendering
certificate bc40318529cdb310… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Verify/Profile.agda sha256 0409565626ed0e5d

The home supervisor

Import limits, reserve, recovery, and a proved design limit.

16supervisorRespectsImportLimitAn invariant holds from the start, survives every supervisor step, and keeps grid import within the cap.proved · shown verbatim
supervisorRespectsImportLimit :
   Σ (FState → Bool) (λ I′ → (I′ initP ≡ true) × (((y : PEv) (x : FState) {x′ : FState} → prstep x y ≡ just x′ → Inv x → Inv x′) × (((x : FState) → ReachP x → I′ x ≡ true) × (((x : FState) → I′ x ≡ true → BudgetSettled x ≡ true → 3 - DE.exportCapOf (vw x) ≤ importCapOf (vw x) → OverCap x ≡ false) × ((x : FState) → I′ x ≡ true → BudgetPending x ≡ true → covered x ≡ true)))))

Shown verbatim: declared inside an anonymous module, which the renderer does not yet display (refuse:name_in_anonymous_module). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Home.ProtectCert · line 171
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
18 modules, every one checked
Source
sha256 5b4faa3fa103b467…
Rendering
no certificate yet
17reserve-protectedWith a margin of m, the battery stays above its reserve through m stale readings.proved · shown verbatim
reserve-protected :
  (b : BatterySpec) → batterySpecOf em ≡ just b → (w : List PEv) (h : FState) {h′ : FState} → ν h ≡ 0 → rLoss h w ≤ m → runP h w ≡ just h′ → isUp (grid (vw h′)) ≡ true → BatterySpec.reserve b ≤ soc (vw h′)

Shown verbatim: declared inside an anonymous module, which the renderer does not yet display (refuse:name_in_anonymous_module). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Home.ProtectReserve · line 295
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
17 modules, every one checked
Source
sha256 1f9e58845ae0e7b1…
Rendering
no certificate yet
18trilemmaIf a paused EV’s demand exceeds both grid envelopes, no command can keep both: a proved design limit.proved · shown verbatim
trilemma :
  (sP : EState) (ds : List Nat) (d : Nat) → sum ds ≡ sum (evDraw sP) + d → importCapOf sP + DE.exportCapOf sP < d → (b : BattFlow) (mc : Maybe Nat) → (DE.exportCapOf sP < D.exportS (cmd sP b) mc) ⊎ (importCapOf sP < U.importS (cmd (resumed sP ds) b) mc)

Shown verbatim: declared inside an anonymous module, which the renderer does not yet display (refuse:name_in_anonymous_module). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Home.Trilemma · line 121
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
4 modules, every one checked
Source
sha256 f373fe7fa75a30ff…
Rendering
no certificate yet
19homeRecoveryEvery home state either recovers within 4 + n supervisor commands, or is provably stuck.proved · shown verbatim
homeRecovery :
  (x : FState) → Len x → ((Recovers x × (length (recoverW x) ≤ 4 + nOf n)) × (allB isSup (recoverW x) ≡ true)) ⊎ Stuck x

Shown verbatim: declared inside an anonymous module, which the renderer does not yet display (refuse:name_in_anonymous_module). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Home.Recover · line 471
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
19 modules, every one checked
Source
sha256 51062957b8bbe00f…
Rendering
no certificate yet

Chargers & the feeder

OCPP charger behaviour and what we found in the reference tool.

20energy-occupiedA charger delivering energy always reports its connector as occupied.proved · shown verbatim
energy-occupied :
  (t : CState) → invB t ≡ true → energy t ≡ true → connectorStatus t ≡ Occupied

Shown verbatim: the renderer’s display probe declined this statement (refuse:probe_rejected). The statement is proved either way; only its typeset rendering waits.

Module
GEC.Model.Charger · line 1463
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
1 module, every one checked
Source
sha256 1c2321dcef805163…
Rendering
no certificate yet
21invCount-correctA closed formula counts the charger’s reachable states exactly, for every configuration.proved · certified rendering
∀(cfg:GEC.Model.Charger.TxCfg),(GEC.Model.ChargerReach.invCountcfg)≡(GE.Core.Prelude.length{GEC.Model.Charger.CState}(GE.Core.Prelude.filter{GEC.Model.Charger.CState}(GEC.Model.ChargerReach.Invcfg)GEC.Model.ChargerReach.allStates))piVRWCxcfgGEC.Model.Charger.TxCfgAgda.Builtin.Equality._≡_levellmax0HRWCxAgda.Builtin.Nat.NatHRWCxGEC.Model.ChargerReach.invCountcfgVRWCxVRWCxGE.Core.Prelude.lengthGEC.Model.Charger.CStateHRWCxGE.Core.Prelude.filterGEC.Model.Charger.CStateHRWCxGEC.Model.ChargerReach.InvcfgVRWCxVRWCxGEC.Model.ChargerReach.allStatesVRWCxVRWCxVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
invCount-correct :
  (cfg : TxCfg) → invCount cfg ≡ length (filter (Inv cfg) allStates)
Module
GEC.Model.ChargerReach · line 53
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
6 modules, every one checked
Source
sha256 8c1e996f594f6cd6…
Rendering
certificate 8c791f7040d9d7bc… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Model/ChargerReach.agda sha256 8c1e996f594f6cd6
22floor-starvesA budget below the charging floor gives every EV nothing: starvation, proved for every policy.proved · certified rendering
∀(floor:ℕ),∀(bud:ℕ),∀(as:Listℕ),(GE.Core.Prelude._<_budfloor)→(GEC.Model.EviBudget.SemiCflooras)→(GE.Core.Prelude._≤_(GE.Core.Prelude.sumas)bud)→GEC.Model.EviBudget.AllZeroaspiVRWCxfloorAgda.Builtin.Nat.NatpiVRWCxbudAgda.Builtin.Nat.NatpiVRWCxasAgda.Builtin.List.Listlevellmax0HRWCxAgda.Builtin.Nat.NatVRWCxpiVRWCx_GE.Core.Prelude._<_budVRWCxfloorVRWCxpiVRWCx_GEC.Model.EviBudget.SemiCfloorVRWCxasVRWCxpiVRWCx_GE.Core.Prelude._≤_GE.Core.Prelude.sumasVRWCxVRWCxbudVRWCxGEC.Model.EviBudget.AllZeroasVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
floor-starves :
  (floor bud : Nat) (as : List Nat) → bud < floor → SemiC floor as → sum as ≤ bud → AllZero as
Module
GEC.Model.EviBudget · line 141
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
4 modules, every one checked
Source
sha256 ba89306fc9384d75…
Rendering
certificate 04fc104760008916… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Model/EviBudget.agda sha256 ba89306fc9384d75
23shed-boundWhen EVs shed as commanded, a ledger within budget keeps the next draw within budget.proved · certified rendering
∀(B:ℕ),∀(es:ListGEC.Model.EviLatency.EV),(GEC.Model.EviLatency.AllGEC.Model.EviLatency.Shedes)→(GE.Core.Prelude._≤_(GEC.Model.EviLatency.Σledgeres)B)→GE.Core.Prelude._≤_(GEC.Model.EviLatency.Σnextes)BpiVRWCxBAgda.Builtin.Nat.NatpiVRWCxesAgda.Builtin.List.Listlevellmax0HRWCxGEC.Model.EviLatency.EVVRWCxpiVRWCx_GEC.Model.EviLatency.AllGEC.Model.EviLatency.ShedVRWCxesVRWCxpiVRWCx_GE.Core.Prelude._≤_GEC.Model.EviLatency.ΣledgeresVRWCxVRWCxBVRWCxGE.Core.Prelude._≤_GEC.Model.EviLatency.ΣnextesVRWCxVRWCxBVRWCx

Typeset by the renderer’s display map from the certified LaTeX; the certified Content MathML is embedded in the formula.

The Agda statement
shed-bound :
  (B : Nat) (es : List EV) → All Shed es → Σledger es ≤ B → Σnext es ≤ B
Module
GEC.Model.EviLatency · line 123
Checked under
Agda 2.8.0 · --safe --without-K · no postulates
Rests on
2 modules, every one checked
Source
sha256 cabe02e94152f1b8…
Rendering
certificate 76eb6b7cd3e88076… · table tbl0-stdlib · stock Agda 2.8.0 accepted CertMain, CertBind and 4 probe programs (--safe); every literal bound; core f328acc5bfe3c002; theorem source ./GEC/Model/EviLatency.agda sha256 cabe02e94152f1b8

10 · The dependency tree

Everything a result rests on, one click away.

The whole system, by family. Open a module to see what it rests on and what rests on it; every link is an import the kernel re-checks whenever the system is checked.

Wind & storage6 modules · 2,404 lines
Models18 modules · 11,395 lines
Home supervisor25 modules · 9,452 lines
Open verifier10 modules · 4,354 lines
EVI-DiST analysis4 modules · 723 lines
Neighbourhood coordinator7 modules · 2,290 lines
Visual emitters1 module · 252 lines
Gluing Engine core37 modules · 21,254 lines
Kernel probes41 modules · 12,666 lines

The module graph as JSON · drawn from a frozen snapshot of the toolkit; the private coordinator appears as one node.


11 · The development record

21 of 48 phases closed, each with its gate.

A phase closes only when its gate passes: proofs checked, seeded mistakes caught, results reproduced. This record grows here as each one lands.

Foundations

  1. P0aOCPP 2.0.1 / 2.1 witnessed
  2. P0bFrozen contract corpus
  3. V0Visuals emitted by Agda

Charger

  1. H1OCPP charger model
  2. H1bEvery reachable state, counted

Home, wind & storage

  1. H2Home supervisor
  2. S1Independent simulator
  3. SASigned flows · wind absorption
  4. H3Certified decision order
  5. H4PROTECT supervisor
  6. H5aVerifier bound, measured
  7. H5Recovery
  8. H6Minimal telemetry
  9. H7Allocation
  10. H8Device monitors

NLR EVI-DiST

  1. E1Public scenario replicated
  2. E1bThree regions
  3. E4EV plant with latency
  4. ST1The night everyone plugged in
  5. E2Its policies certified
  6. E3HELICS adapter
  7. E5Upstream package

Neighbourhood

  1. N1Coordinator ledger
  2. N2Proved street rule
  3. N3
  4. N4
  5. N5

Verifier & profiles

  1. VF1Open verifier · checkProposal
  2. PR1Requirement profiles
  3. PR2Reporting exports

Simulation, devices & close-out

  1. S2–S4Campaigns
  2. D1–D4Device builds
  3. T1–T2Tooling
  4. C1–C3Close-out & landing

closed   ·   brass: in progress   ·   dashed: planned


12 · The CIP proposal

Auditable Supervisory Assurance for Distributed Wind.

Our proposal to NLR’s 2026 Competitiveness Improvement Project turns this toolkit into a component a U.S. turbine maker can integrate: advisory in Phase 1, beside the existing protections, with public artifacts at the end of one bounded phase.

Topic4 · Component Innovation · six months · Phase 1
ManufacturerUprise Energy, 12-kW Mobile Power Station (signed participation letter)
Demonstrator APublic/synthetic wind–storage–critical-load system anchored to the 12-kW reference
Demonstrator BA public EVI-DiST feeder with wind, storage, EV charging and other demand
AcceptanceCore proofs check in the pinned environment; ≥ 100 named scenarios; ≥ 10 safeguard mutations; zero unexplained checker/reference differences; clean-room reproduction
Public releaseAgda specifications, generated checker, EVI-DiST adapter, scenarios, replay tools, SBOM, under BSD-3-Clause

Standards it is built against

  • NIST SSDF 1.1 for secure software development
  • NIST SP 800-82r3 for operational-technology threat boundaries
  • NIST AI RMF 1.0 for documenting AI risk
  • Selected NASA-STD-7009B practices for modelling credibility
  • A qualification map to ANSI/ACP 101-1-2021, IEC 61400-2 and applicable UL requirements

These guide development and evaluation. Product certification is a later, separate step, and the plan names its route rather than assuming it.



Who it is built with

A real turbine. A public tool. An open result.

The work is anchored to hardware a U.S. manufacturer ships and to data anyone can download, so every result can be checked by someone other than us.

Manufacturer partner

Uprise Energy

Maker of the 12-kW Mobile Power Station, the reference system for Demonstrator A, with a signed participation letter for the proposed Phase 1.

Public tool

NLR’s EVI-DiST

Used as published, on public data, for Demonstrator B and the results above. About EVI-DiST →