Patrick Mockridge

Specification

Azoth

Chemical-engineering calculations in Python and Rust, where every number carries its provenance.

What
A chemical-engineering calculation library in Python and Rust, written twice by hand from one declaration, where every result carries its provenance.
Why
In process safety, the dangerous number is rarely obviously wrong. It is reasonable, it is in the right units, and it has no history — so it gets used. A library that returns a bare float is optimised for that failure. Azoth makes a number unable to be anonymous: it carries its source and verification state, and a calculation that cannot be supported refuses instead of returning a plausible default. The library is built so the unsourced number cannot exist.
The combination
One declaration → two hand-written kernels (Rust and Python) compared in CI → per-result provenance → typed refusal as a first-class outcome; a disagreement is a finding, not a fallback.

The difference

Table 1. A number, with and without a record.What changes when the result carries its own history.
Table 1. A number, with and without a record.
MeasureA plain calculationAn Azoth result
ValueA float.A float plus its identity, source, verification state, skipped checks, and kernel hashes.
ImplementationOne code path.Two hand-written kernels (Rust and Python) from one declaration, compared in CI.
DisagreementA fallback, or unnoticed.Recorded as a finding.
Unsupported inputA plausible default, or an exception with no field.A typed refusal naming the field.

Design intent, not current coverage: v0.1.1, not on PyPI, not for design work yet; everything ported ships as unverified.

Design

  • A disagreement is a finding, not a fallback. Two hand-written kernels from one declaration are compared in CI; a difference is recorded rather than resolved by choosing one. This catches implementation drift, not a shared specification error.
  • No result is anonymous. Each result carries its identity, source, verification state, skipped checks, and kernel hashes.
  • Unsupported answers are refused. Typed errors name the offending field rather than returning a plausible default.
  • Agent-exposed results keep their provenance. Data access is sealed at load, not at use, and results exposed over MCP carry the same record.

Provenance

Port of NeqSim (Apache-2.0), with documented divergences. Original to this work: the specification, dual generation, provenance layer, typed refusal, sealed data access, and the Lean-checked foundations. Azoth is AGPL-3.0-or-later.

Evidence

Azoth upstream evidence
MeasureValueSource
Upstream issues filed97 (80 closed, 17 open)NeqSim issue search
Provenance tests259Azoth repository

As of October 2026. These are upstream issues filed against NeqSim, not an Equinor engagement.

Figure 1. Azoth pipeline, abridged.

Limits

  • v0.1.1; not on PyPI; incomplete port coverage; everything ported ships as unverified; the standalone simulator is an aim, not a status.
  • Not for design work yet: shipped Crane K-factor coefficients are estimated dummy values; a pressure drop can be wrong by a factor of two while looking reasonable.
  • Lean covers foundations only — dimensional calculus, unit vocabulary, two derivative formulas, keycard non-amplification. Physics kernels are measured, not proved.
  • One upstream issue did not reproduce in situ. This is a self-audit, not a third-party audit.
  • AGPL-3.0-or-later has commercial implications for proprietary integration.