Agent Context — Alpiq BESS (Mando)
Purpose
Dense reference for AI agents to quickly gather project context. Load this file first when working on any Mando crate.
Identity
- Project: Battery Energy Storage System optimization platform
- Org: Alpiq, Sales & Origination / Flexible Assets
- Repo:
sales-and-origination/flexible-assets/bess/poc/mando(GitLab) - Source path:
/Volumes/bandi/coding/poc/mando(workspace root:/Volumes/bandi/coding/poc/) - Language: Rust toolchain 1.89.0 (
rust-toolchain.toml), MSRVrust-version = 1.88.0, edition 2021 + Python 3.12 via PyO3 - Version: 1.16.0 (
origin/develop@92bfe1c8, 2026-07-09) - Main branch:
develop— localdevelopfast-forwarded 2026-07-13 and now tracksorigin/develop; still fetch + diff againstorigin/developbefore trusting local state
Master conventions guide
An untracked
AGENTS.mdat the mando repo root is the canonical conventions document (non-negotiables, style, error system, recipes, landmines). Fully rebuilt 2026-07-13 against thedeveloptip92bfe1c8— it no longer lags the tip. See Mando AGENTS.md Master Guide for its map, the round-1 corrections, and the round-2 verified facts. When it disagrees with code ondevelop, code wins.
Workspace Crates
Workspace members on origin/develop @ 92bfe1c8, 2026-07-09 (dependency direction: mando-core → mando-lib → binaries; never invert):
| Crate | Type | Purpose |
|---|---|---|
mando-core | lib | No internal deps: error! macro, DataPointId, model primitives, DataFrame validation. Compiled into the Python extension — keep lightweight |
mando-lib | lib | Data layer: repos (PG/DuckDB/SQLite/passthrough), MandoService, adapters (Alpiq/Volue/Fingrid), workflow engine, validation |
mando-codegen | build-dep | Build-time generator: YAML + Askama templates → Rust (not a proc macro); output under mando-bess/build/generated/ is tracked in git |
mando-flow-step | lib | FlowStepService trait — a construction trait (NOT execute-style): type Params: ParamMeta; type Response; + async from_config(config: &str, providers: &StepProviders); StepProviders (src/providers.rs) carries flow_repository, data_point_registry, 6 auth providers, simulation_enabled. Zero tests |
mando-flow-step-derive | proc-macro | ParamEnum + ParamMeta derives for flow-step params (not ErrorCode — no such derive exists on develop); param structs derive #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ParamMeta)]. Zero tests |
mando-bess-lib | lib | Shared mando-bess library (split out in the Jul-08 restructure). Zero tests |
mando-bess | bin | REST API (Axum 0.8.7, port 8080): routes, flow execution, scheduling, auth (JWT/Entra ID) |
py-mando | cdylib | PyO3 extension (abi3-py38): algo params, DataFrame ops, algo runner HTTP server, adapters for Python. SimulationRunner REMOVED (moved to py-mando-simulation, commit 3559042d — breaking) |
py-mando-simulation | cdylib | PyO3 bindings for the simulator — py_mando.SimulationRunner lives HERE now; requires Python ≥3.11, ships ddtrace, no polars/pandas. Rust side zero tests, 1 Python integration test |
mando-simulator | bin | Flow-simulation server (uses position-manager) |
position-manager | lib | Market position bookkeeping |
Adjacent (not workspace members):
| Crate | Type | Purpose |
|---|---|---|
mando-scrt | bin | Rust-based Python runtime: virtual module injection, Arrow FFI streaming, memory-safe algo hosting (PyO3 auto-initialize) |
mando-cli | bin | Workspace CLI: typed commands (init/pull/build/up/down/override/config/mock/migrate/volume/release), git handler with SSH/HTTPS fallback, Docker lifecycle via bollard, config resolution (standalone repo at /Volumes/bandi/coding/poc/mando-cli/) |
mando-bess-am | bin | BESS AM (BE-2262, in flight) — headless Kinesis stream processor for WAGO battery telemetry; consumes bess-am-events, 1-min aggregates, forwards to bess-os-events. See BESS AM (BE-2262) - mando-bess-am. NOT yet merged to develop. |
mando-lib-macrodoes not exist ondevelopThe
#[derive(ErrorCode)]crate previously listed here lives only in.worktrees/experiments (poc-error-extractor, BE-2023, BE-1595/BE-3482).error.kind/error.codeare extracted at runtime bymando_core::error!. See Mando AGENTS.md Master Guide.
Key Abstractions
MandoService (async trait)
├── retrieve / retrieve_at / retrieve_history — read data points
├── insert — write data points
├── retrieve_catalog — list available data points
└── send — push data externally
Repository (trait) → DataPointRepository, CacheRepository
├── RepositoryPostgres (production)
├── RepositoryDuckDb (analytics/OLAP)
├── RepositorySqlite (local dev)
└── RepositoryPassthrough (caching layer)
DataPointId = hierarchical path: "Asset/FI/Battery/SoC" → ["Asset","FI","Battery","SoC"]
DataPointType = TimeSeriesDouble | TimeSeriesDoubleMatrix | StaticData
DataPointFilterQueryMode = ORIGINAL | OVERRIDE | MERGED
Feature Flags (mando-lib)
| Flag | Enables |
|---|---|
app | Axum + OpenTelemetry (used by mando-bess) |
codegen | Code generation with CSV |
python | PyO3 classes/functions |
workflow | Flow execution engine |
Flow Engine
Versioned workflows for BESS trading strategies. On origin/develop @ 2026-07-08 (mando-bess/config/flows/fi/ + manifest.yaml):
- Manual Schedule (v3) — operator schedules; the canonical exemplar flow
- Auction (v4) — auction bidding
- AS Auction Update (v2) — ancillary-services auction updates
- Intraday (v2) — intraday ops
- Data Update (v2) — data pipelines
Released flow versions are immutable
Never change a released vN’s YAML or generated code — breaking behavior goes to v(N+1). Definition YAMLs generate Rust via
build.rs(tracked in git: commit YAML + regenerated output together). Src-side wiring moved from per-typesrc/flow/{type}/v{n}/dirs toflow_registry.rsin the Jul-08 restructure (with new cratesmando-flow-step+mando-flow-step-derive); steps register via 36type_entry!entries inmando-bess/build.rs.
config/flows/manifest.yaml is the deployment catalog: setup: {version}: flows: {name}: {path, schedule_env, semaphore_group} — scheduling env vars and concurrency groups are configured in the manifest, not in code; semaphores have capacity 1 per group.
BESS AM (BE-2262) — real-time telemetry workstream
Separate from the flow engine
BESS AM = BESS Asset Management is a newer workstream, NOT one of the flows above. It introduces a new
Event-typed data-point class (real-time telemetry) alongside the existingTimeSeriesDouble/TimeSeriesDoubleMatrix/StaticData. Full reference: BESS AM (BE-2262) - mando-bess-am.
- Headless Kinesis stream processor (
mando-bess-amcrate) for per-second WAGO battery telemetry (real-time SoC/SoH) on the FI/Valkeakoski/Beskar asset. - Pipeline:
WAGO Box → AWS IoT Core → Kinesis (bess-am-events) → mando-bess-am → Kinesis (bess-os-events) → mando-bess. - Persists raw events, computes 1-min aggregates (Mean/Max/Min/Last/StdDev/Count/Sum) via windowing + grace-period closure, forwards to
bess-os-events. - Postgres schema
bess_am; env prefixBESS_AM_*; Kinesis adapter atmando-lib/src/adapter/kinesis/; Event model atmando-core/src/model/{event,wago}.rs; Event datapoints inmando-bess/config/parts/battery_online.yaml. - Status (2026-06-24): core MR !512 OPEN, blocked on review (
requested_changes); nothing merged todevelop. Builds on BE-2132 (interval/Event groundwork), depends on BE-2341 (generic Kinesis producer, folded into !512).
External Integrations
| System | Adapter | Purpose |
|---|---|---|
| Azure Entra ID | EntraIdClient | Authentication |
| Alpiq EBS | adapter/alpiq/ | Energy Balance System |
| Alpiq MDR | adapter/alpiq/ | Market Data Repository |
| Alpiq OPL | adapter/alpiq/ | Operations Planning |
| Volue EMS | adapter/volue/ | Energy Management System |
| Volue ATP | adapter/volue/ | Token provider |
| Fingrid | adapter/fingrid/ | Finnish market data |
Tech Stack Summary
| Layer | Technology |
|---|---|
| Web | Axum 0.8.7, Tower middleware |
| Data | Polars 0.49.1, Arrow 56.2.0 |
| DB | PostgreSQL (deadpool), DuckDB 1.4.2, SQLite (rusqlite) |
| Auth | JWT (RS256), Entra ID, Volue EMS/ATP |
| Python | PyO3 0.25.1, pyo3-polars 0.22.0, Maturin 1.9.2 |
| Observability | OpenTelemetry 0.30.0 (OTLP/gRPC), tracing |
| API docs | utoipa + Scalar UI |
| GraphQL | cynic 3.12.0 + graphql-ws-client |
| Serialization | serde, serde_json, serde_yaml, Apache Avro |
| Error handling | thiserror enums + mando_core::error! macro (runtime error.kind/error.code extraction; tracing::error! is clippy-banned; no ErrorCode derive on develop). Redesign landed in stages: ae6d1098 (error.message = root cause, error.stack = source chain, fingerprint) then MR !569 (fingerprint = {code}|{step_path}|{activity}) and MR !571 = BE-3541 Single Error Emission (logged_at_site/logged() REMOVED: construct ErrorWithStepStatus with new/message only, never log at the detection site; one boundary emission carries HttpContext). error.trace + .step_context() NOT landed. MR !578 = BE-3656 APM Span Enrichment MERGED 2026-07-22 (merge 4a0d297f = develop tip: error.*/http.* on trace spans). In flight: BE-3657 error_stack Adoption (full-path codes via error_stack 0.8, rebased onto 4a0d297f, 14 commits @ ab8cfd11 incl. the DD_SERVICE env read fix, MR pending on Andras’s yes) |
mando-bess Routes
| Endpoint | Method | Purpose |
|---|---|---|
/query_data | — | Read data points |
/save_data | — | Write data points |
/flow/{id} | — | Manage flows |
/flow_executions | — | List executions |
/flow_executions/{asset_id} | — | Asset executions |
/audit_logs | — | Audit trail |
/settings | — | Configuration CRUD |
/versions | — | Component versions |
Build Commands
cargo build # Build workspace
cargo test --all-features --release -- --test-threads=1 # CI test command; single-threaded MANDATORY (shared in-memory DB pools)
cargo clippy --release --all-features # the lint gate (CI has NO fmt gate)
cargo run -p mando_bess # Run service (port 8080)
cd py-mando && maturin develop # Build Python extensionNever run
cargo fmtin ANY formBare
cargo fmtreformats ~64 legacy files, andcargo fmt -- path/to/file.rsdoes NOT scope either (field-verified 2026-07-13: it touchedapi_docs.rs, which was never named; see BE-3482 Datadog Logs and APM Conformance). Format single files withrustfmt --edition 2021 path/to/file.rs. The import-grouping/comment options inrustfmt.tomlare nightly-only and silently ignored on the stable 1.89 toolchain; import grouping is maintained by hand, and the tip tree is NOT fmt-clean.format!on tip is ~3:1 positional over inline; inline args are the review rule for new code.
RTK machines: the shell hook falsifies the test gate
The RTK hook rewrites
cargo test --all-features --release -- --test-threads=1so the threads flag becomes a test-name filter: every test is filtered out, exit 0 in 0.00s (signature:0 passed, N filtered out); two gate runs were false-green this way before detection (2026-07-13). Run it asrtk proxy cargo test --all-features --release -- --test-threads=1and confirm the summed passed totals are nonzero; exit 0 alone proves nothing. Piped forms report the LAST command’s exit (cargo test | grep | tail; echo $?is tail’s status). See BE-3482 Datadog Logs and APM Conformance.
CI/CD
- Platform: GitLab CI
- Stages: Security (Snyk) → Container → Setup → Build/Test → Publish → Release → Pages
- Branching:
feature/*,bugfix/*,develop→ Dev ECR;release/*→ Prod ECR - Runtime image:
debian:13.1-slimwith ca-certificates, libc6, libssl3, bundled libduckdb.so (samba libs removed by the remotefs-smb to smb migration; build image still installs them) - Gates: clippy (
--release --all-features) + tests (--test-threads=1); no fmt gate - New jobs (Jul 2026): “PyMando Simulation Linux Dev” (pytest, without
--nbval) + a simulator docker publish child pipeline - Repo hygiene: no MR/issue templates, no CODEOWNERS
File Layout
mando/
├── mando-core/src/ # error.rs (error! macro), model/, util/, validation/, python/
├── mando-lib/src/ # adapter/, audit/, bess/, model/, util/, workflow/, repo_*.rs, ...
├── mando-bess/src/ # flow/ (flow_registry.rs on tip), route/, database/, model/
├── mando-bess/build/generated/ # GENERATED Rust (domain.rs + flows) — tracked in git, never hand-edit
├── py-mando/src/ # 12 modules: algo, polars, adapter, data_point, ...
├── assets/ # Test data
├── lib/libduckdb/ # Bundled DuckDB 1.4.2 (git LFS)
├── scripts/ # Benchmarks, load tests, seed data
└── test/ # Manual E2E scripts