Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

AC OPF solver decision

Status: accepted for feasibility work. Recorded 24 September 2026. On 29 October 2026 the release owner approved EPL-2.0 distribution of the WASI asset, and the website serves it as an experimental, base-case-only calculation. Release gates 2 to 5 below remain open.

Backend update — 4 November 2026

The native and dedicated WASI paths now pin the published, checksummed pounce-nl = pounce-rs = 0.15.0 release, with FERAL 0.22.0. The release and source-manifest guard checks all 16 POUNCE crates. The two new transitive crates, pounce-convex and pounce-sens-core, have explicit EPL-2.0 exceptions alongside the existing POUNCE crates in deny.toml.

POUNCE 0.15.0 adds complementarity support, which Tellegen does not use. Four upstream changes can move Tellegen’s solves:

  • perturb_slack_max_rows (new in 0.15.0, default 1000) caps the inertia correction’s slack-block perturbation. A model with at most 1000 inequality rows solves exactly as before; above that, solves that hit inertia correction can take a different path.
  • Restoration’s release test now uses the outer filter’s own quantities (0.14.0). A failed base solve can end with a different status, which changes which second-opinion rungs follow.
  • The second-opinion ladder gained a saddle-escape rung after an infeasibility verdict (0.14.0).
  • A stop requested from the intermediate callback is now honoured during POUNCE’s automatic re-solves (0.15.0). The ladder itself still runs its remaining rungs after UserRequestedStop, so Tellegen keeps refusing their initialization once cancelled.

The SQP handover added in 0.14.0 is off by default and stays off. Tellegen continues to construct its existing polar AC OPF model through NlProblemParts and apply its independent physical validator, with unchanged POUNCE_OPTIONS. The dependency update does not add a complementarity formulation or change the public API. The validation results below for 0.13.0 remain historical evidence for that release.

Local validation used Rust 1.96.0 on macOS arm64: all 428 enabled engine tests and the WASI adapter test passed, along with strict all-target AC OPF Clippy, the HS071 probe, release/source-manifest checks, and the EPL isolation guard. The release wasm32-wasip1 build also solved the existing three-bus planning fixture using the production WASI host under Node: objective 631.5334170921521, 12 iterations, and active/reactive balance residuals below 5e-12 MW/MVAr. This was a reactor smoke test; the browser UI was not rerun.

The engine tests solve only three- and four-bus cases, below the 1000-row threshold, so the native acopf_benchmark example compared 0.13.0 and 0.15.0 on 14 PGLib v23.07 cases (case14_ieee to case4661_sdet). Both versions solve the same 13 cases, and every objective agrees within 1e-12 relative. Nine solve identically: same status, iterations and objective. The rest:

Case0.13.00.15.0Cause
case793_gocsucceeded, 210 it, 1.8 sacceptable, 137 it, 1.3 sslack cap
case1354_pegase192 it, 3 restorations190 it, 2 restorationsrestoration test
case1888_rte605 it, 10.2 s788 it, 14.1 sslack cap
case3012wp_kbase step error, rescued by mu_strategy=adaptivebase restoration failure, same rescuerestoration test
case4661_sdetfails after 1 rung, 615 it, 123 sfails after 3 rungs, 1824 it, 244 srestoration test

Times are single serial runs. A third build, 0.15.0 with perturb_slack_max_rows 0, reproduced 0.13.0 exactly on case793_goc and case1888_rte, and matched 0.15.0’s restoration behaviour on the other three. On case4661_sdet it was slower still: 2076 iterations in 360 s. Tellegen therefore keeps the upstream default. case4661_sdet fails in both versions with a small constraint violation and a KKT error of 1.35e4. Under 0.15.0 its base solve ends in Restoration_Failed rather than Error_In_Step_Computation, so the ladder tries three rungs instead of one and failure takes about twice as long. Every attempt keeps the per-attempt max_iter 1000.

Two generator-free variants (case14_ieee and case300_ieee with every generator’s real-power limits set to zero) fail identically under both versions: InfeasibleProblemDetected after the same three rungs and 114 and 194 total iterations, in 0.1 s and 0.9 s. The saddle-escape rung did not fire.

Released backend integration — 22 October 2026

The native and dedicated WASI paths were updated to the published, checksummed pounce-nl = pounce-rs = 0.13.0 release (FERAL 0.21.0). Both exact dependency pins and every transitive POUNCE lockfile entry are checked by scripts/acopf-release.py, also invoked by the build and EPL isolation gate. The former Git-source exception has been removed.

Tellegen installs POUNCE’s multi-pass restoration factory and invokes the released second-opinion ladder on the same cancellable TNLP. Failed retries cannot overwrite the selected point. Every emitted result still passes the independent physical validator; a retry does not weaken acceptance or turn a local infeasibility report into a proof. Cancellation is checked before rescue attempts, by callbacks during them, and after the ladder regardless of the selected status. POUNCE 0.13.0 may still visit later retry rungs after UserRequestedStop; the TNLP refuses their initialization once cancelled, before they can rebuild or evaluate the model. Browser cancellation terminates the entire worker.

Responses retain the selected solve’s iteration count and residuals, and add base_solver_status, total_nlp_iterations, base_restoration_calls, restoration_calls, recovery_attempts, and recovered_by. The restoration count belongs to the selected solve; the total iteration count includes rejected attempts. The solve card uses that total and marks recovered solves. Older responses remain readable. The engine’s TypeScript contract now includes the NLP diagnostic variant, which previously existed only in the Rust and Study schemas. Each attempt uses the configured POUNCE iteration limit; the total across retries can exceed that per-attempt limit.

A canonical full-pi regression forces entry into restoration, requires restoration_calls > 0, and checks electrical feasibility and objective agreement. A genuinely unserviceable instance exercises the retry ladder and must still return an error. Small exact-expression regressions additionally prove that a failed base solve can be rescued, rejected retries retain the base point and verdict, total work includes every attempt, and cancellation during the ladder returns a cancellation error. Existing finite-difference, corrupt-result, portable-emission, cancellation and worker-lifecycle checks remain in place.

The opt-in build now places POUNCE-EPL-2.0.txt, POUNCE-NOTICE.txt and POUNCE-SOURCE.json beside the WASM asset. The manifest records its SHA-256, size, lockfile hash, Tellegen revision/dirty state, and all 14 POUNCE source archive URLs and checksums. Website builds copy these files with the solver. These materials prepare review; they do not approve public distribution. Python 3.11+ is required for the release guard (PYTHON can select an interpreter).

Local validation at commit c721344 used Rust 1.96.0 on macOS arm64 and Chromium with the release WASI artifact SHA-256 e6bf0775a90dec4fc8658c0559fadfed97545870adaae41152afb8ba8c12f5de (10,463,176 bytes). The four browser UI/import/disposal checks and the four external PGLib corpus checks all passed. Each corpus test hashes the served artifact and input, requires independently checked primal violation below 1e-6, compares the objective to the checksum-keyed oracle, and verifies that the worker terminates. These are single-run correctness checks, not a performance or peak-memory characterization.

The external corpus was PGLib-OPF revision dc6be4b2f85ca0e776952ec22cbd4c22396ea5a3. Its published TYP baseline uses PowerModels.jl 0.19.9 and Ipopt.jl 1.4.1 / Ipopt 3.14.4. The rounded baseline values below are compared with relative tolerance 1e-4; they are not full-precision solution or expression-graph oracles. The same cases passed the native benchmark:

PGLib casePublished objectiveNative objectiveNative iterationsNative restoration entriesBrowser oracle check
14_ieee2,178.12,178.0804107140passed
30_ieee8,208.58,208.5154410210passed
300_ieee565,220565,219.97465881130passed
6468_rte2,069,7002,069,730.156617667814passed

Case6468 returned Solved_To_Acceptable_Level; its independently checked maximum physical violation was below 1e-8. No case needed a second-opinion promotion. The small forced-restoration and impossible-generation regressions separately exercise the restoration and retry-driver paths.

The dated sections below retain the earlier feasibility evidence; their Git pin and old release observations describe those historical runs.

Main integration check — 5 October 2026

The feasibility branch includes main at 0d08c55, including compact multiconductor PF session responses, the generated feeder regression and the additional center-tap reference cases. The just ci aggregate retains both acopf-probe and mc-pf-regression, matching the Rust workflow. The existing multiconductor PF sessions remain independent of this opt-in NLP boundary.

The POUNCE revision and release/restoration/distribution gates are unchanged. The latest tagged release checked for this refresh is v0.12.0; the pinned revision is 35 commits ahead of that tag. Native AC OPF compilation/solve and the unpublished multiconductor IVR work remain separate layers of the stack.

Local validation for this refresh passed the HS071 probe (17.014017274, maximum source-equation violation 2.484e-8), PowerIO source check, EPL feature isolation and formatting. Workspace tests excluding the Python extension passed 374 tests (2 existing ignores), the independent mc-pf suite passed 160 (1 ignore), the conic engine suite passed 312 (2 ignores), and the conic WASM adapter passed 40. Strict Clippy passed for the shipping Rust adapters plus the opt-in probe and separately for Python with extension-module. The generated feeder-10k --check regression passed all deterministic checks; timings are not acceptance thresholds. Cross-platform, JavaScript and distribution checks remain in the GitHub workflows.

Decision

Tellegen will use POUNCE as its first nonlinear solver for canonical balanced transmission AC OPF. The choice favors an end-to-end Rust implementation and a responsive upstream over building two solver adapters in the first cycle. The public problem and solution boundary must remain backend-neutral.

The decision follows POUNCE’s WASM-frontend restoration fix and the AC OPF follow-up experiments. Those results are feasibility and implementation evidence, not general solver performance guarantees.

This decision does not relabel the existing SOCWR relaxation as AC OPF. The native opt-in feature now makes Problem::Acopf available after adding the exact PowerIO-prepared polar model, independent primal validation, truthful status mapping, and portable AcOpfSolution emission. Product distribution still requires the browser worker boundary and release approval below.

POUNCE 0.13.0 replaces the original PR #961 Git pin. The upstream WASM fix does not retrofit callers of a bare IpoptApplication; Tellegen now explicitly installs the restoration factory and calls the released recovery driver.

Feasibility boundary

The non-default tellegen/acopf feature enables pounce-nl and pounce-rs. No shipping adapter forwards it; the unpublished development WASI adapter does. The native acopf_hs071_probe example constructs HS071 with NlProblem::from_expressions, builds NlTnlp, verifies the sparse Jacobian and Lagrangian-Hessian structures, solves with exact derivatives, and checks the result independently.

Run it with:

cargo run -p tellegen --example acopf_hs071_probe --features acopf --locked

The probe pins the FERAL backend, exact Hessians, identity NLP/linear-system scaling, and 1e-9 solver/constraint tolerances. The acceptance check requires the known HS071 objective within 1e-5, source-equation violation below 1e-7, eight Jacobian nonzeros, and ten lower-triangle Hessian nonzeros.

PowerIO 0.11.3 provides the released preparation boundary used here. The model compiler consumes its AcOpfInstance, build_ac_opf_preparation, and AcOpfSolution APIs rather than reinterpreting MATPOWER data or reusing Tellegen’s modified CATS power-flow physics.

Canonical model boundary

The opt-in feature now also contains a private, POUNCE-specific polar model compiler. It consumes AcOpfInstance only through build_ac_opf_preparation, preserves PowerIO’s generator and branch columns and source maps, and emits an in-memory POUNCE expression DAG with exact sparse derivatives. Native module dispatch and capabilities are feature-gated; no shipping adapter or browser package enables them.

The recorded assembly policy is per-unit values, no zero-impedance skipping, no synthesized thermal ratings, and PowerIO’s angle-interval correction enabled. The preparation, including those choices, and the formulation version are hashed into the model fingerprint. Changing any policy is therefore a model change rather than a solver tuning option.

The variable map carries bus Va/Vm, generator-level Pg/Qg, and one epigraph column for each active convex piecewise generator cost. Constraint maps retain P/Q balance rows, zero reference angles, selected angle bounds, both terminal thermal margins, and exact piecewise segments. Balance rows use generation minus branch withdrawals, shunt consumption, and demand equal to zero. Thermal and epigraph rows use nonnegative remaining margin. No dual is published until these signs and unit conversions are independently validated.

The tests evaluate the full pi model at a non-flat point with taps, phase shifts, charging and bus shunts, compare both-end flows and nodal balances to a separate numerical calculation, and compare the sparse Jacobian and Lagrangian Hessian to finite differences. Unsupported active storage, voltage-dependent loads, and remote voltage regulation fail with the source element’s identity.

An ignored, path-driven external_model_build_ladder test makes the standard MATPOWER 14/30/300-bus construction check reproducible without vendoring a second copy of those fixtures. On 24 September 2026, a local arm64 debug build after compilation produced:

casevariables / rowsnnz Jacobian / Hessianexpression compilederivative tapemax absolute directional J / H error
1438 / 49267 / 1271.849 ms3.841 ms4.545e-9 / 1.557e-7
3072 / 184871 / 2601.016 ms12.803 ms7.186e-9 / 3.412e-8
300738 / 1,0125,433 / 2,6058.380 ms70.444 ms2.723e-7 / 3.601e-7

These are correctness/prototype measurements, not solver performance claims. Run the ladder with TELLEGEN_ACOPF_FIXTURES pointing to a directory containing case14.m, case30.m, and case300.m. Peak RSS was not available inside the sandbox used for this run, and frozen-NL parity remains a separate acceptance measurement. The regression test now reports both absolute error and error scaled by the analytic and finite-difference magnitudes with a floor of one. The latest scaled J/H errors were 3.478e-9 / 2.418e-9, 1.791e-9 / 2.239e-10, and 9.095e-7 / 2.966e-9 for cases 14, 30, and 300 respectively.

Typed native solve boundary

The opt-in native API now exposes solve_ac_opf_instance and solve_ac_opf_instance_to_solution plus cancellable counterparts. The cancellable paths poll an atomic flag before model construction and at every iteration of the base solve and recovery attempts. They run POUNCE with FERAL, exact Hessians, identity NLP and linear-system scaling, a 1e-8 solver/constraint tolerance, 1e-7 acceptable tolerance, and a 1,000-iteration ceiling. The returned AcOpfSolution is scattered through PowerIO’s source row/winding maps in MW/MVAr and degrees, retains inactive source rows as unavailable values, and round-trips through PioModule.

Only SolveSucceeded and SolvedToAcceptableLevel are candidates for emission, and both must pass a separate calculation from the prepared arrays: P/Q balance, voltage/generator boxes, references, angle and both-end thermal limits, exact piecewise epigraphs, finite outputs, and source-cost objective. The portable residuals report the independently calculated MW/MVAr balance mismatch. A local NLP infeasibility report remains a diagnostic error rather than PowerIO’s proof-strength Infeasible. No LMP or limit multiplier is emitted yet; the POUNCE dual arrays stay private pending sign and source-unit perturbation tests.

Native solve_module_json promotes a balanced network or consumes a stored AcOpfInstance when the request selects acopf, and the capability advertises only vm, va, injections, flows, and dispatch. Request edits currently fail with an instruction to amend the canonical instance, rather than being silently dropped, and every sensitivity request fails until the NLP KKT contract exists. A successful nonlinear solve is reported as feasible, not globally optimal, and its response includes the POUNCE status, iteration count, solver constraint/KKT residuals, independently checked primal residual, and model fingerprint. Failure and cancellation errors include the available iteration and residual diagnostics.

Native API example

With tellegen built with features = ["acopf"], a stored canonical instance can be solved for either the compact API response or the portable solution:

#![allow(unused)]
fn main() {
use std::sync::Arc;
use tellegen::{Problem, SolveRequest};

fn example(module_json: &str) -> Result<(), String> {
let module = tellegen::ir::deserialize_module(module_json)?;
let powerio::PioValue::AcOpfInstance(instance) = module.into_value() else {
    return Err("expected an ac_opf_instance".into());
};
let request = SolveRequest { formulation: Problem::Acopf, ..Default::default() };
let response = tellegen::solve_ac_opf_instance(&instance, &request)?;
// Compact response: powers in MW/MVAr, voltage angles in radians.
assert!(response.lmp.is_none());
let solution = tellegen::solve_ac_opf_instance_to_solution(Arc::new(instance), "my-app")?;
// Portable solution: source table order, powers in MW/MVAr, angles in degrees.
let stored = powerio::PioModule::new(powerio::PioValue::AcOpfSolution(solution));
let json = tellegen::ir::serialize_module(&stored)?;
Ok(())
}
}

These are alternative entry points; calling both performs two solves. Inactive source rows, including three-winding transformer terminals, remain unavailable (NaN in Rust, the PowerIO unavailable representation in serialized modules).

Reproducible external comparisons

The committed acopf_benchmark example accepts MATPOWER files and emits one JSONL record per case, including input and executable SHA-256, elapsed time, objective, model fingerprint, residuals, solver status, and failures. It exits nonzero if any case fails, while continuing through the remaining cases.

cargo run -p tellegen --release --example acopf_benchmark --features acopf --locked -- \
  - /path/to/case14.m /path/to/case30.m /path/to/case300.m > results.jsonl

For an independent objective comparison, replace - with a JSON file containing provenance (corpus revision, reference solver version/options, and result source) and objectives (a map from exact input SHA-256 to its reference objective). Missing checksums fail rather than comparing different case revisions. The comparison tolerance is 1e-4 * max(1, abs(reference objective)). Keep that reference file and the corpus provenance alongside the resulting JSONL. This runner does not supply or regenerate an independent oracle. The published PGLib baseline comparison above does not replace frozen expression parity or validation on the final release artifact.

Experimental browser ABI

POUNCE’s proven browser target is a separate wasm32-wasip1 module with its WASI clock/random/output shim. A direct wasm32-unknown-unknown/wasm-bindgen probe compiles and loads but traps when the solver first calls std::time::Instant::now(). Therefore tellegen-wasm does not forward acopf, and a browser AC OPF solve must use a dedicated, terminable worker with a small typed message boundary and one POUNCE memory. There must be no synchronous main-thread fallback.

The development integration now implements that boundary as the unpublished tellegen-acopf-wasi crate. Its raw ABI accepts one PowerIO module and one solve request, then returns a length-prefixed SolveResponse. The JavaScript host instantiates it with a minimal WASI Preview 1 clock/random/output shim in a fresh worker for every solve. Cancelling or superseding a solve terminates that worker; there is deliberately no synchronous or main-thread fallback.

The hosted UI defaults PUBLIC_TELLEGEN_ACOPF_WASM_URL to the bundled /experimental-acopf/tellegen_acopf_wasi.wasm asset. It probes that URL through the worker before enabling the AC OPF selector. Website builds now include the EPL-bearing asset and its notices; the Docker build compiles the reactor, while local builds and CI prepare it with npm run wasm:acopf. CI runs the three-bus browser solve against the ordinary website build. This integration prepares website enablement; it does not waive the release gates below. The current UI path is intentionally base-case only because the canonical AC OPF API rejects request edits and sensitivities rather than silently dropping them.

For a local development preview from the repository root:

npm ci
rustup target add wasm32-unknown-unknown wasm32-wasip1
npm run wasm
npm run wasm:acopf
npm run build:engine
npm run build:web
npm --workspace tellegen-frontend run preview

The app copies the asset and notices during every website build. The Vite development server also serves them after npm run wasm:acopf. These commands are for local development and do not authorize distribution.

Browser operationExperimental AC OPF support
Balanced network / MATPOWER inputPromoted to a canonical instance for the base solve
Stored AcOpfInstanceImported without replacing its objective or constraints; requires the worker to solve
Geographic sidecars / layoutSupported while retaining the instance
Demand or rating editsRejected; reset edits before selecting AC OPF
LMPs / sensitivitiesUnavailable
Save case / Export asDisabled; the one-shot path has no retained Study
Save exact AC OPF solution in the UIUnavailable; portable solution emission is currently a native API
Server fallback / WebMCP calculationsUnavailable for AC OPF

tellegen-acopf-wasi requires its own explicit acopf feature. Default workspace builds leave it inert, so selecting the workspace cannot silently enable POUNCE in the CLI or other adapters. The build script enables this feature only for the experimental reactor. Do not combine an explicitly enabled AC OPF build with a shipping-adapter build in one Cargo invocation: Cargo unifies their engine features. The EPL guard checks the default workspace graph as well as individual adapters.

A single wasm-bindgen module can be reconsidered after POUNCE has a portable clock. That reconsideration must measure artifact size, memory growth, and hard worker cancellation in real browsers.

Experimental native multiconductor IVR OPF

The separate mc-opf feature adds native unbalanced current–voltage rectangular OPF with explicit terminals and neutrals. The entry points are solve_mc_ac_opf_instance, solve_mc_ac_opf_instance_cancellable, and solve_mc_ac_opf_module_json; the JSON entry point requires an explicitly declared McAcOpfInstance. This feature is not enabled by shipping adapters or forwarded by the balanced browser worker described above.

PowerIO owns the canonical electrical semantics and solver-independent IVR preparation. Tellegen constructs the expressions and independently checks the accepted solution’s physical equations, limits and objective. Polynomial rows use POUNCE’s existing exact sparse quadratic evaluator; general load laws and smooth inverter controls use its existing sparse AD. No new differentiation package is introduced. McOpfResult includes terminal voltages and physical branch/device/winding/shunt ledgers with explicit terminal and coil identities. Canonical JSON exports retain the full report in a versioned PowerIO module extension; the MC APIs expose typed McOpfError diagnostics. Explicit canonical initial points and the mc_opf_initial_point_from_pf helper seed numerical variables without changing the declared physical problem; see initial points for supported fields and projection rules. McOpfOptions.collect_profile enables optional stage and KKT diagnostics. Native McOpfSession retains a compiled model and accepted primal for repeated solves and atomic edits. McOpfOptions.collect_duals separately enables original-scale multipliers, KKT residuals, and conditional local marginal values for supported load and limit parameters. Raw IVR KCL multipliers are not nodal prices. McOpfResult::sensitivities() and McOpfSession::sensitivities() provide conditional local forward and adjoint derivatives from a verified current dual point, reusing one sparse active-KKT factorization. Nominal load P/Q mappings include constant-current, constant-impedance, ZIP and exponential laws, including coefficients hidden by zero nominal powers. Their voltage-law coefficients and nominal voltages remain fixed. Inverter mappings cover per-coil availability, P/Q bounds, apparent-power and conductor-current ratings, including neutral returns and their effects on existing volt-var and volt-watt references. Transformer mappings cover effective port ratings and physical continuous tap bounds; outputs include winding/port flows and optimized tap ratios, including inverse regulator conventions. Shared control-profile mappings cover volt-var/volt-watt breakpoints and fractions and interior signed power factors, including all assigned coils and smoothing-width derivatives. Control modes, references and electrical coefficients remain fixed. Sparse rank qualification uses explicit fill/work budgets, with reusable KKT structure and per-query residual diagnostics exposed by sensitivity views. Version 7 reports retain these claims; version 2–6 reports are verified with their original maps and dense rank audit before upgrade.

The feature builds against published POUNCE 0.13.0 and PowerIO 0.11.8. Build and test the native feature from the repository root:

cargo build -p tellegen --no-default-features --features mc-opf --locked
cargo test -p tellegen --no-default-features --features mc-opf --locked

bash scripts/check-mc-opf.sh tests a temporary archive of committed source with all features, MC OPF alone, and strict all-target Clippy using the locked dependencies. Its optional PowerIO checkout argument is for companion development: it patches all eight PowerIO crates only in the temporary archive and does not rewrite either checkout’s lockfile. A companion checkout is not required.

See Formulations for the electrical profile and derivative strategy, Validation for acceptance and regression coverage, and Methodology for optional external studies. Ordinary frozen-reference tests need neither Julia nor the large ENWL dataset. The existing solver release and distribution gates below also apply to MC OPF.

License and release gate

POUNCE is EPL-2.0 while Tellegen is MIT. deny.toml admits EPL-2.0 only for the named POUNCE crates, and scripts/epl-guard.sh proves POUNCE is absent from the default engine and all shipping adapters while present in the opt-in probe.

That mechanical boundary is not legal approval. Before distributing a native binary or WASI asset containing POUNCE, the release owner must approve the EPL-2.0 obligations, include its license/notices, and provide a reasonable corresponding-source location. Problem::Acopf remains unavailable in the default native engine and shipping adapters; the website uses the separate worker reactor.

On 29 October 2026 Samuel Talkington, the release owner, approved EPL-2.0 distribution of POUNCE in the website’s WASI asset. The website build meets the obligations as follows:

  • POUNCE is used without modification. POUNCE-EPL-2.0.txt (the license) and POUNCE-NOTICE.txt (the notice) are served beside the asset under /experimental-acopf/.
  • POUNCE-SOURCE.json, beside the asset, gives the corresponding source: the crates.io archive URL and SHA-256 of each of the 14 POUNCE crates, the upstream tag, the Tellegen commit the deployed image was built from, and the asset’s own SHA-256 and size. The deployed asset’s manifest records "development_only": false; local builds still record true.
  • The /credits page links all three files.

Remaining release gates

The released dependency and restoration-driver gates are implemented. Gate 1 is complete. The release owner enabled the experimental calculation on the public website with gates 2 to 5 still open; they are not complete:

  1. Release-owner approval of EPL-2.0 distribution obligations. Approved on 29 October 2026; see the section above.
  2. Resolve the inherited PowerIO → ZIP advisory failures using a reviewed, patched PowerIO release; no advisory exception is added here.
  3. Repeat the independent corpus check on the final Tellegen release artifact and intended browser/platform matrix. The draft’s local validation is not a certificate for a different artifact.
  4. Complete repeated performance and peak-memory measurements, including stressed starts, beyond the correctness and lifecycle checks recorded here.
  5. Compare the 14/30/300 expressions against independently frozen benchmark values in addition to the physical validator and finite-difference checks.

The optional browser corpus regression uses the production importer and worker, checks the served WASM hash against its manifest, and requires checksum-keyed independent objectives. For example, after an opt-in build:

TELLEGEN_ACOPF_CORPUS=/path/to/pglib-opf \
TELLEGEN_ACOPF_REFERENCE=/path/to/reference.json \
TELLEGEN_ACOPF_CASES=pglib_opf_case14_ieee,pglib_opf_case30_ieee,pglib_opf_case300_ieee,pglib_opf_case6468_rte \
PLAYWRIGHT_JSON_OUTPUT_NAME=/path/to/browser-results.json \
npm --workspace tellegen-frontend exec -- playwright test ac-opf-experimental.spec.ts --workers=1 --reporter=list,json

The reference JSON has the same provenance and SHA-256-keyed objectives format as acopf_benchmark. Each test attaches the full response, input hash, artifact manifest and elapsed time. External corpus tests skip explicitly when these paths are absent; the four ordinary UI/lifecycle tests still run in CI.

A failure of expression-DAG scaling changes the private solver adapter, not the PowerIO problem or solution contract.

Input preparation safeguards

PowerIO 0.11.5 filters inactive loads and shunts during preparation; Tellegen uses that preparation directly and retains a regression covering source rows, selected constraints, objective and explicit warm-start voltages. Networks claiming to be normalized while retaining inactive injections are rejected. Selected voltage, generator, thermal and angle bounds are checked before model construction. Zero thermal ratings remain unlimited. Small full-pi directional derivative checks run in ordinary CI, with a complex-current branch-flow oracle independent of the polar coefficient transcription.

Review diagnostics and benchmark timing

Compact AC OPF primal_residual is the maximum independent P/Q balance mismatch in MW/MVAr. The optional residuals object separates voltage and generation bounds, reference/branch angles, thermal limits, epigraph gaps and objective agreement, with explicit units. Acceptance still checks every residual family; objective agreement is not presented as a power mismatch. Compact flow output includes three-winding transformer legs using the same synthetic IDs as SOCWR. Portable solutions retain the caller’s producer and append POUNCE’s exact final status, including Solved_To_Acceptable_Level.

The benchmark emits compact objective/status/iteration records, input and artifact hashes, parse_ms, solve_ms, and total_elapsed_ms. Solve timing includes model construction and independent validation but excludes parsing, file hashing and JSON serialization. Earlier elapsed_ms records measured the full input/JSON/solve path and must not be compared directly with solve_ms.

The base restoration count survives retry promotion; restoration_calls remains the selected attempt’s count. Neither field claims to total all retries. Portable producer metadata appends the base verdict, promotion label and both counts when recovery succeeds. Tests separately cover cancellation before retry initialization and cancellation from an in-flight retry’s iteration callback.

The EPL dependency-leak guard does not need Python. The separate release-pin verification remains mandatory in Rust CI and the WASI build, requires Python 3.11+, and reports that requirement explicitly on older interpreters. Set PYTHON for the WASI build when the system python3 is older.