The optional openfdd-engine package (openfdd_engine)
Open-FDD has one real rules implementation: YAML files evaluated on pandas via RuleRunner in the open_fdd.engine package. Everything else is either that same code in a different wrapper, or documentation about how to deploy it.
This page explains how the in-repo package packages/openfdd-engine/ (PyPI name openfdd-engine, import openfdd_engine) fits next to open_fdd.engine and the Docker fdd-loop service.
Re-exports only — no duplicated types
openfdd_engine does not define its own rule engine, Pydantic models, or resolver types. The shim __init__.py imports from open_fdd.engine (e.g. RuleRunner, resolve_from_ttl, BrickTtlColumnMapResolver, ColumnMapResolver) and lists them in __all__. Any new public API should be added once under open_fdd.engine; the shim only gains new names via import + re-export.
- Why: One source of truth for PyPI
open-fddand optionalopenfdd-engine; no drift between packages. - Versioning:
open-fddon PyPI is authoritative;openfdd-enginepinsopen-fdd>=…in itspyproject.tomlwhen published.
The same policy applies to the repo-root openfdd_engine/ namespace used in some dev installs.
Mental model (three layers)
| Layer | What it is | Typical import / entrypoint |
|---|---|---|
| Core engine | Loads YAML rules, runs checks on a DataFrame, produces fault columns | from open_fdd.engine.runner import RuleRunner |
| Optional shim | Same classes, different package name (depends on open-fdd) | from openfdd_engine import RuleRunner |
| Platform loop | Pulls Timescale data + TTL, builds frames per site, calls RuleRunner, writes fault_results | Docker: python -m openfdd_stack.platform.drivers.run_rule_loop --loop → openfdd_stack.platform.loop.run_fdd_loop |
There is no second rule engine inside openfdd_engine: its modules re-export symbols from open_fdd.engine (see packages/openfdd-engine/src/openfdd_engine/runner.py).
When to use pip install open-fdd vs openfdd-engine
Default for everyone (PyPI, notebooks, CI, integrators):
pip install open-fdd
from open_fdd.engine.runner import RuleRunner, load_rule, load_rules_from_dir
# brick resolution in-platform / with extras:
from open_fdd.engine.brick_resolver import ...
Optional openfdd-engine distribution — use only if you intentionally want:
- A separate PyPI project name (
openfdd-engine) for procurement or a minimal dependency line that still pullsopen-fddunderneath, or - An editable install of only the shim while developing the monorepo:
cd packages/openfdd-engine
pip install -e .
# optional TTL helpers:
pip install -e ".[brick]"
from openfdd_engine import (
RuleRunner,
load_rule,
bounds_map_from_rule,
resolve_from_ttl,
BrickTtlColumnMapResolver,
ColumnMapResolver,
)
Public story: pip install open-fdd is the supported install; openfdd-engine may or may not be published to PyPI as a second project (maintainer setup). See PyPI releases (open-fdd).
How the full stack uses the engine (so IoT-only users know what they are skipping)
In Docker, fdd-loop runs:
python -m openfdd_stack.platform.drivers.run_rule_loop --loop
That driver:
- Optionally refreshes Open-Meteo for the lookback window.
- Calls
run_fdd_loop()inopenfdd_stack.platform.loop, which loads YAML fromrules_dir, loads timeseries from Postgres, buildscolumn_mapviaBrickTtlColumnMapResolver(Brick TTL — same as historical behavior) fromconfig/data_model.ttl, and constructsRuleRunnerfromopen_fdd.engine.runner. Advanced use: passcolumn_map_resolver=...intorun_fdd_loopto swap mapping logic; the default stack does not. Library helpers inopen_fdd.engine.column_map_resolver:ManifestColumnMapResolver,FirstWinsCompositeResolver,load_column_map_manifest(also re-exported fromopenfdd_engine). - Writes results to
fault_results(and run log for Grafana).
So: same YAML and same RuleRunner semantics as a standalone script; the platform adds DB, schedule, TTL, and weather.
Operational triggers (touch file, one-shot exec): Operations — FDD loop.
Library-only / external data (no Docker engine mode)
If your data is already in a warehouse or a CSV pipeline, you do not need openfdd_engine — use open_fdd.engine on a DataFrame and the same rule files as the platform. Step-by-step and column_map: Engine-only deployment and external IoT pipelines.
Worked example under the repo: examples/engine_iot_playground/.
Summary
| Goal | Install | Import / run |
|---|---|---|
| Normal development & PyPI users | pip install open-fdd | open_fdd.engine.* |
| Optional second package name | pip install -e packages/openfdd-engine (or published openfdd-engine) | openfdd_engine.* |
| Scheduled FDD against platform DB | Docker --mode engine / full stack | fdd-loop → run_rule_loop → run_fdd_loop → RuleRunner |
See also
- Engine-only deployment and external IoT pipelines —
--mode enginevs pandasRuleRunner - PyPI releases (
open-fdd) — tags, publishing,openfdd-enginescope - Modular architecture — which services run in engine mode
- Expression rule cookbook — YAML rule types and patterns
- Package README:
packages/openfdd-engine/README.md