FLUXFLUX
  • Introduction
  • Quickstart
  • Two Specs, One Substrate
  • The Six Families
  • The FLUID Seam
  • Deterministic & Governed
  • Runtime & Evidence
  • Anatomy
  • The Nineteen Kinds
  • Versions
  • Changelog
  • JSON Schema 0.5.1
  • UI Hints 0.5.1
  • Enforcement Contract 0.5.0
  • Bundle Manifest 0.5.0
  • Overview
  • Tutorial
  • How-to guides
  • Reference
  • Explanation
  • Command line
  • Error codes
  • Accuracy program
  • The vNext Plan
  • The Nine RFCs
  • RFC-10 (proposed)
  • Conformance Profiles
Examples
What's New
FLUID
GitHub
  • Introduction
  • Quickstart
  • Two Specs, One Substrate
  • The Six Families
  • The FLUID Seam
  • Deterministic & Governed
  • Runtime & Evidence
  • Anatomy
  • The Nineteen Kinds
  • Versions
  • Changelog
  • JSON Schema 0.5.1
  • UI Hints 0.5.1
  • Enforcement Contract 0.5.0
  • Bundle Manifest 0.5.0
  • Overview
  • Tutorial
  • How-to guides
  • Reference
  • Explanation
  • Command line
  • Error codes
  • Accuracy program
  • The vNext Plan
  • The Nine RFCs
  • RFC-10 (proposed)
  • Conformance Profiles
Examples
What's New
FLUID
GitHub
  • FLUX Simulation Engine
  • Tutorial
    • First evidence pack in five minutes
  • How-to guides
    • Model your customers
    • Add a journey
    • Use the FLUID seam
    • Calibrate from aggregates: declare a scorecard
    • Ship with evidence
  • Reference
    • Command line
      • fluxsim init
      • fluxsim validate
      • fluxsim plan
      • fluxsim apply
      • fluxsim run
      • fluxsim verify
      • fluxsim ship
      • fluxsim replay
      • fluxsim calibrate
      • fluxsim accuracy
      • fluxsim gate
      • fluxsim expr
      • fluxsim describe
      • fluxsim plugins
      • fluxsim explain
    • Error codes
    • Python API
    • Schemas
  • Explanation
    • The six-step loop
    • Determinism and the seed tree
    • The FLUID seam
    • The evidence pack, and what it does not claim
  • Accuracy program

    • The accuracy program: design
    • Accuracy report

flux_engine.api — the governed extension contract

This package is the surface a third-party implementation targets and an in-process consumer imports against. Everything outside flux_engine.api and flux_engine.engine (the facade described under "The engine facade" below) is internal and may move without notice; everything inside this package is governed by __api_version__, which is "0.1" today and moves on its own schedule — removing or renaming anything listed below is a breaking change to that number regardless of what the engine's own version does.

The package holds Protocols and frozen records only. There is no logic here to disagree with the kernel about, no runtime import into the kernel, and no number that is not a Decimal or an int.

Rules the surface keeps

  • VerifyVerdict keeps two answers apart: whether a run reproduces, and whether the scenario describes the world. It has no __bool__, so if verdict: is always true, and no passed or summary accessor. Read the two fields.
  • Scorecard records where a dial's setting came from. A grade that was never computed is reported as absent, never as a default number.
  • AccuracyGate fixes an order: register a prediction before its horizon, score it against the readout afterwards, record the verdict either way, misses included.
  • Every record is frozen, every plural field is a tuple, and no field holds a float.

Why the two verdict fields stay apart is in the evidence pack.

Four ports are reserved: AccuracyGate, ExpressionEvaluator, FidelityProver and SkillRunner. This build publishes their shape, ships no implementation of it, and has no parameter through which a consumer could inject one. They are shapes to design against, not extension points to ship against, and the tables below mark them.

The names

Digests

NameWhat it is
DigestRefA digest together with the domain it was taken in and what it was taken over. The unit every port speaks in, so two digests of different kinds are never silently compared.
DIGEST_DOMAINSThe three domains a digest can belong to: file bytes, a canonical document, an emitted stream.

Expressions

NameWhat it is
ExpressionEvaluatorReserved. The shape of a checker for a segment or guard expression: it compiles against the attribute model and returns a predicate, and every way an expression can be wrong is reported at compile time, not when it runs. The engine's own compiler is a pair of module-level functions of a different shape.
ExpressionScopeThe three scopes an expression can be written against: a subject, an event, an observed readout.

Emitting rows

NameWhat it is
EmitHeaderThe declared shape of one emitted stream: the expose, its columns in declared order, their types, and the contract they were declared under.
EmitSinkSomewhere rows are written — opened once, written to, closed once, including when the run fails. The stream's digest is taken above the sink, so which sink is in use cannot change what the run is answerable for.

Calibration

NameWhat it is
CalibratorTurns aggregate statistics into dial settings and reports how much those settings are worth. Aggregates only: individual records never reach it.
ScorecardWhere a setting came from, how it was graded, over what period, and how much weight that supports. Reports absence as absence.
ProvenanceDeclared, fitted, or scored.
CredibilityThe band the evidence supports: not established, declared, backtested, or validated against a live comparison.

Outcome accuracy

NameWhat it is
AccuracyGateReserved. Register a prediction, score it against what was observed, record the verdict. The fluxsim accuracy commands do this work; they do not go through this shape.
PredictionRecordA statement about the future, fixed before the future arrives.
ObservedReadoutWhat actually happened, read after the horizon, with the sample it rests on.
AccuracyVerdictThe comparison of one prediction with one readout, carrying what it rests on so it still says so when quoted alone.
AccuracyOutcomeWithin the declared interval, outside it, or not scored.

Claims

NameWhat it is
ClaimOne sentence the engine will stand behind, with the basis it rests on and the digests a reader can re-take.
ClaimTypeThe four questions a claim can answer: conformance, reproducibility, fidelity, validity.
ClaimBasisWhat a claim rests on: a live randomised comparison, a historical period held out of the inputs, or nothing. The third is a stated position, not a missing field.

The fidelity check

NameWhat it is
FidelityStatementWhat is being checked and against which committed summary of the source.
FidelityProverReserved. The shape of something that runs where the source data lives and produces a backing artefact if its backend has one. In v0.1 no backend does, so nothing implements it.
FidelityVerifierRuns anywhere; re-evaluates the statement from what crossed the boundary and returns the claim it supports.
ProofSystemNames the backend a record was produced under. In v0.1 there is one, called none, and the record states it rather than omitting it.

The agentic tier

NameWhat it is
ModelPortThe one place a language model can be reached. It may only return content; it has no path to the scheduler, the trace, or an emitted row.
SkillRunnerReserved. Runs a skill through a model port under a token budget, reusing an earlier answer when the call is identical.
SkillInvocationOne call, addressed by everything that makes it repeatable: the seed path, the request, and the governing policy.
SkillProposalContent offered to the engine, which decides what to do with it — including whether the content was reused rather than asked for again.

Lineage

NameWhat it is
LineageEmitterSends lineage reports somewhere. A receiver that is down loses the report, never the work; whether reports arrived is a question a caller can ask.
LineageEventOne report about a run at one point in its life. Carries digests and declarations, never rows.
LineageEventTypeStart, complete, fail, abort.
DatasetRefOne end of a lineage edge.

The verify readout

NameWhat it is
VerifyVerdictTwo disjoint answers and their claims. headline() renders both in one line — reproducible: yes | validity: not asserted — because the second half's absence reads, to every reader, as the stronger claim.
ReproducibilityReproducible, not reproducible, or not checked. The third is not a negative answer.
ValidityNot asserted, supported, or not supported. Not asserted is the default, and the honest answer for a run that measured nothing against the world.

Stage results

NameWhat it is
StageResultWhat one stage returned: its exit code, its captured output, and a read-only view of its structured artefacts.
StageNameThe seven stages, in order: validate, plan, apply, run, verify, ship, replay.
EngineErrorBase failure. Catch it to handle any stage.
ValidateFailed, PlanFailed, ApplyFailed, RunFailed, VerifyFailed, ShipFailed, ReplayFailedOne per stage, so a caller that cares about exactly one — a withheld bundle, say — does not have to match on text.

StageResult.success answers one question about one stage. It is not a verdict about a run; that is VerifyVerdict, and it deliberately does not reduce to a single boolean.

The stage functions in flux_engine.engine do not raise these errors. A stage that fails returns a StageResult whose success is false and whose error_code names the failure. Call result.raise_for_status() to get the stage's typed exception.

The engine facade

flux_engine.api is the vocabulary; flux_engine.engine is the way in. It is the library entry point a host process imports — one async def per stage, dispatching to the synchronous stage functions via asyncio.to_thread, so an in-process consumer never blocks its event loop on a run that takes real wall-clock time. It mirrors forge-cli's fluid_build.engine (the Pulumi Automation API pattern).

import asyncio

from flux_engine.engine import run

result = asyncio.run(run("./bundle", state_dir="./.flux", verify=True))
assert result.success
result.raise_for_status()  # does nothing here; on a failed stage it raises RunFailed

Seven callables, one per stage, each returning the StageResult named below: validate, plan, apply, run, verify, ship, replay.

Two contracts hold on them:

Frozen kwarg names, from that module's first release forward. Adding an optional keyword argument is not a breaking change; renaming or removing one is. Every callable takes its bundle directory positionally and everything else by keyword.

A soft timeout. Every callable accepts timeout: float | None. When it fires the awaiter gets TimeoutError, but the stage thread keeps running in the background — Python threads cannot be cancelled — so this is a bound on how long the caller waits, not a kill. Same contract forge-cli's engine documents.

Stability here is governed by the frozen-kwarg promise in that module's own docstring, not by __api_version__: __api_version__ covers the names exported from flux_engine.api, and the facade exports none of them — it returns them. Nothing in flux_engine.engine is on a digest path (the import-linter contract in pyproject.toml forbids the kernel packages from importing it), so it is orchestration over flux_engine.stages and nothing else.

Using it

from flux_engine.api import VerifyVerdict, Reproducibility, Validity

verdict = VerifyVerdict(
    reproducibility=Reproducibility.REPRODUCIBLE,
    validity=Validity.NOT_ASSERTED,
)
assert verdict.headline() == "reproducible: yes | validity: not asserted"

Implementing a port is a matter of matching its shape — nothing needs to be registered or subclassed, and every port can be checked at a boundary with isinstance:

from flux_engine.api import EmitSink

assert not isinstance(object(), EmitSink)  # an object with a sink's methods would pass

Stability

The export list is pinned by a snapshot test that fails on an addition as well as on a removal. A new name on this surface is therefore a decision, taken together with the __api_version__ bump and a row on this page, and never something noticed later. The same test pins the rules listed at the top: frozen records, no float fields, ports that can be checked with isinstance, and a VerifyVerdict with no way to collapse its two answers into one.

Last Updated: 11/12/26, 10:41 PM
Prev
Error codes
Next
Schemas