Skip to content

Model inflexible devices as assets; drop the unreleased flex-context group field - #2374

Merged
Flix6x merged 8 commits into
mainfrom
feat/inflexible-device-assets
Jul 31, 2026
Merged

Model inflexible devices as assets; drop the unreleased flex-context group field#2374
Flix6x merged 8 commits into
mainfrom
feat/inflexible-device-assets

Conversation

@Flix6x

@Flix6x Flix6x commented Jul 31, 2026

Copy link
Copy Markdown
Member

Description

Changes how inflexible (unschedulable) devices are modelled, and removes an unreleased sub-feature of #2358.

An inflexible device can now be declared in a flex-model entry (as its own asset) by giving it a single inflexible-consumption or inflexible-production sensor reference (the field name sets the sign; source filters are supported). Such an entry carries no schedulable-device fields; it simply declares a fixed device whose power is accounted for. It joins a group through the ordinary flex-model group field, exactly like a flexible member — so:

  • inflexible devices are no longer an exception: group membership is defined the same way for every element (the element points at its group);
  • the field is a single reference, not a list;
  • inflexible devices are gathered upward with the rest of the flex-model / asset tree, so we never need to gather flex-context downward into a subtree (keeping the invariant "a flex-context only ever inherits downward").

The flat inflexible-consumption / inflexible-production lists in the flex-context remain, for plain site base load (no group).

Removed (unreleased, from #2358)

  • The group field on flex-context inflexible entries, the SensorReference.group carrier, and the device-inventory plumbing behind it (_collect_inflexible_referenced_group_keys, FlexDevice.group_reference, the inflexible branch of group_key). group_to_devices still folds inflexible members in, and by_index stays — both are reused by the new model.

Notable

  • InflexibleDeviceSchema moves to schemas/sensors.py so both the flex-context and the flex-model can use it without an import cycle.
  • Validation on a flex-model inflexible entry: rejects declaring both signs, a sensor whose explicit consumption_is_positive contradicts the field, and co-existing schedulable-device fields.
  • Canonical solver order: flexible devices → flex-model inflexible devices → flat flex-context inflexible devices.

How to test

  • pytest flexmeasures/data/models/planning/tests/test_device_inventory.py (classification + ordering + group membership)
  • pytest flexmeasures/data/models/planning/tests/test_group_constraints.py -k inflexible (an inflexible load in a group caps the battery end-to-end)
  • pytest flexmeasures/data/schemas/tests/test_scheduling.py -k "inflexible or storage_flex_model" (schema validation)

Note: test_battery_storage_with_time_series_in_flex_model fails on this branch and on clean main in this environment (a price-fixture/shared-DB artifact, UnknownPricesException); unrelated to this change.

Related

🤖 Generated with Claude Code

Flix6x and others added 2 commits July 31, 2026 17:53
…t group field

An inflexible (unschedulable) device can now be declared in a flex-model entry
via a single inflexible-consumption/inflexible-production sensor reference (its
own asset). Such a device joins a group through the ordinary flex-model 'group'
field, exactly like a flexible member, so its fixed load counts towards the
group's intermediate power constraint -- and it is gathered upward with the rest
of the flex-model/asset tree, so no downward flex-context traversal is needed.

This replaces the unreleased approach from #2358, which let a flex-context
inflexible entry carry a 'group' field (removed here, together with the
SensorReference.group carrier and the inventory plumbing behind it). The flat
flex-context inflexible-consumption/production lists remain for site base load.

InflexibleDeviceSchema moves to schemas/sensors.py so both the flex-context and
the flex-model can use it without an import cycle. group_to_devices already folds
inflexible members in, and FlexDevice.group_key reverts to reading the flex-model
'group' -- so a flex-model inflexible device's membership uses the normal path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The OpenAPI schema/examples for the new flex-model inflexible fields currently document an array example for fields that accept a single object, which can mislead API/UI users.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR updates FlexMeasures’ scheduling model to treat inflexible (unschedulable) devices as assets declared in the flex-model (via a single inflexible-consumption or inflexible-production sensor reference), and removes the previously introduced but unreleased flex-context inflexible group sub-feature. This unifies group membership semantics (everything joins groups via the normal flex-model group field) and simplifies device-inventory classification and solver ordering.

Changes:

  • Add flex-model support for inflexible devices (inflexible-consumption / inflexible-production) with schema-level validation to prevent ambiguous/invalid entries.
  • Update device inventory classification/enumeration so flex-model inflexible entries are indexed after flexible devices and before flat flex-context inflexibles, and so only flex-model entries can participate in groups.
  • Update docs/tests/OpenAPI to reflect the new modeling approach and the removal of the flex-context inflexible group carrier.
File summaries
File Description
flexmeasures/ui/static/openapi-specs.json Updates generated OpenAPI schema for removed flex-context group support and added flex-model inflexible fields (but currently contains misleading examples for these new fields).
flexmeasures/data/schemas/tests/test_scheduling.py Replaces flex-context-group validation test with flex-model inflexible-field validation tests.
flexmeasures/data/schemas/sensors.py Moves InflexibleDeviceSchema into a shared location and removes SensorReference.group.
flexmeasures/data/schemas/scheduling/storage.py Adds flex-model fields for inflexible devices plus schema validation to enforce correct/unambiguous declarations.
flexmeasures/data/schemas/scheduling/metadata.py Updates descriptions of inflexible fields to reflect “list in flex-context vs single ref in flex-model entry”.
flexmeasures/data/schemas/scheduling/init.py Removes old scheduling-local InflexibleDeviceSchema (with group) and updates UI schema metadata for inflexible fields.
flexmeasures/data/models/planning/tests/test_group_constraints.py Updates group-constraint test to model an inflexible load as its own flex-model entry/asset and join group via normal group.
flexmeasures/data/models/planning/tests/test_device_inventory.py Updates inventory tests to cover new inflexible classification, ordering, and group membership semantics.
flexmeasures/data/models/planning/devices.py Implements flex-model inflexible-entry classification and updates group membership resolution (flex-model only).
documentation/features/scheduling.rst Documents flex-model inflexible fields and explains new approach for inflexible devices participating in groups.
documentation/changelog.rst Adds changelog entry for modeling inflexible devices as assets and removes mention of unreleased flex-context group-on-inflexible feature.
Review details

Suppressed comments (3)

flexmeasures/data/schemas/scheduling/storage.py:381

  • The inflexible-production field on a flex-model entry is a single nested reference, but it reuses metadata.INFLEXIBLE_PRODUCTION whose example is a list; this makes the generated OpenAPI/Docs misleading (array vs. object).
    inflexible_production = fields.Nested(
        InflexibleDeviceSchema,
        data_key="inflexible-production",
        required=False,
        metadata=metadata.INFLEXIBLE_PRODUCTION.to_dict(),

flexmeasures/data/schemas/scheduling/storage.py:664

  • Same issue as above for DB-stored flex-model entries: inflexible-production is a single nested object, but the reused metadata example is a list, which misdocuments the expected input shape.
    inflexible_production = fields.Nested(
        InflexibleDeviceSchema,
        data_key="inflexible-production",
        required=False,
        metadata=metadata.INFLEXIBLE_PRODUCTION.to_dict(),

flexmeasures/ui/static/openapi-specs.json:6870

  • In the generated OpenAPI schema for StorageFlexModelSchemaOpenAPI, inflexible-production is a single object ($ref to InflexibleDevice), but the example is an array. This is inconsistent with the actual schema and may mislead API/UI users.
            "example": [
              {
                "sensor": 3
              },
              {
  • Files reviewed: 11/11 changed files
  • Comments generated: 3
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment on lines +371 to +376
inflexible_consumption = fields.Nested(
InflexibleDeviceSchema,
data_key="inflexible-consumption",
required=False,
metadata=metadata.INFLEXIBLE_CONSUMPTION.to_dict(),
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4de6dd: the flex-model inflexible-consumption/inflexible-production fields now override the shared metadata's list example with a single object ({"sensor": 3}), so the generated OpenAPI documents an object ($ref InflexibleDevice), not an array. The flex-context list fields keep their array example.

Comment on lines +654 to +659
inflexible_consumption = fields.Nested(
InflexibleDeviceSchema,
data_key="inflexible-consumption",
required=False,
metadata=metadata.INFLEXIBLE_CONSUMPTION.to_dict(),
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4de6dd: the flex-model inflexible-consumption/inflexible-production fields now override the shared metadata's list example with a single object ({"sensor": 3}), so the generated OpenAPI documents an object ($ref InflexibleDevice), not an array. The flex-context list fields keep their array example.

Comment thread flexmeasures/ui/static/openapi-specs.json Outdated
The flex-model inflexible-consumption/inflexible-production fields are a single
sensor reference, but reused the shared metadata whose example is a list (that
form fits the flex-context list fields). Override the example to a single object
on the flex-model declarations so the generated OpenAPI no longer shows an array
for an object-valued field. Addresses Copilot's review on #2374.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The new validation intended to forbid schedulable-device fields on inflexible flex-model entries currently misses at least soc-unit, allowing contradictory inputs to pass.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (1)

flexmeasures/data/schemas/scheduling/storage.py:57

  • validate_inflexible_flex_model_entry is meant to reject any schedulable-device fields on an inflexible flex-model entry, but _SCHEDULABLE_DEVICE_DATA_KEYS currently omits soc-unit. This allows inputs like { "inflexible-consumption": {…}, "soc-unit": "kWh" } to pass validation even though the entry is still treated as inflexible, which contradicts the stated validation rules and can lead to silently ignored fields.
    "soc-maxima",
    "soc-targets",
    "soc-gain",
    "soc-usage",
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

…ation

The schedulable-field check used a hand-maintained blacklist that missed at
least soc-unit (Copilot review on #2374), so a contradictory entry like
{inflexible-consumption, soc-unit} slipped through. Replace it with a whitelist
of the keys allowed alongside an inflexible declaration (identity/group/commodity
and the defaulted activation preferences), rejecting every other declared field.
This stays complete as new device fields are added. Adds a soc-unit test guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>
@Flix6x

Flix6x commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

Addressed Copilot's second-round finding in fd78a771a: the schedulable-field check on an inflexible flex-model entry used a hand-maintained blacklist that missed soc-unit. Replaced it with a whitelist of the keys allowed alongside an inflexible declaration (identity/group/commodity + the defaulted activation preferences), so every other declared field — including soc-unit and any future device field — is rejected. Added a soc-unit test guard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

A small docstring-formatting fix is needed and the new “source-filtered inflexible device in flex-model” path lacks a dedicated regression test.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (2)

flexmeasures/data/schemas/sensors.py:1060

  • The new InflexibleDeviceSchema docstring introduces line breaks mid-sentence (e.g. breaking after “in a”), which conflicts with the repository docstring/comment convention to break lines only after punctuation for readability and easier searching.
    """One inflexible device: a sensor reference with optional source filters.

    Used both in the flex-context (as a list, for site-level inflexible load) and in a
    flex-model entry (as a single reference, when an inflexible device is modelled as
    its own asset). Deserializes to a plain :class:`Sensor` when no source filters are
    given (a backward-compatible shape downstream) and to a :class:`SensorReference`
    otherwise.
    """

flexmeasures/data/models/planning/devices.py:343

  • Support for source-filtered inflexible devices in the flex-model is implemented by accepting SensorReference-like objects (entry_ref.sensor) here, but there is no test covering that path. Adding a regression test would ensure source filters are preserved on FlexDevice.sensor_reference for flex-model-declared inflexible entries (not just the flat flex-context list).
        # Tolerate SensorReference-like objects (with a `.sensor`) and plain Sensors.
        reference_sensor = getattr(entry_ref, "sensor", None)
        if reference_sensor is not None:
            sensor, sensor_reference = reference_sensor, entry_ref
        else:
            sensor, sensor_reference = entry_ref, None
        return FlexDevice(
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

…ltered flex-model inflexible

Addresses Copilot's third-round review on #2374:
- Reflow the new docstrings (InflexibleDeviceSchema and the inflexible-device
  helpers/validator) to break only after punctuation, matching the repo docstring
  convention and the surrounding code.
- Add a device-inventory regression test that a flex-model inflexible entry given
  as a source-filtered SensorReference keeps the reference on
  FlexDevice.sensor_reference (so source filters reach the solver's power lookup).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>
@Flix6x

Flix6x commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

Addressed round 3 in the latest commit: reflowed the new docstrings to break only after punctuation (matching the repo convention / surrounding code), and added a device-inventory regression test that a flex-model inflexible entry given as a source-filtered SensorReference preserves the reference on FlexDevice.sensor_reference (so source filters reach the solver's power lookup).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

A single-sensor flex-model dict containing inflexible-consumption/inflexible-production can be accepted by schema deserialization but will not be classified as an inflexible entry in DeviceInventory, risking silent misconfiguration.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (1)

flexmeasures/data/models/planning/devices.py:448

  • In single-sensor mode (flex_model is a dict), flex-model-declared inflexible devices are not classified (_register_flex_model_inflexible is a no-op), but the schema layer can still deserialize a dict that only contains inflexible-consumption/inflexible-production. That would currently be treated as a schedulable DEVICE entry (using the target sensor) rather than being rejected, which can silently accept an invalid configuration.
        # Collect the group keys referenced by flex-model entries' "group" fields; the
        # entries whose own sensor/asset matches a referenced key are classified as group
        # entries below. Flex-model-sourced inflexible devices carry their "group" the
        # same way, so this one scan covers them too.
        inventory.referenced_group_keys = _collect_referenced_group_keys(
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Addresses Copilot's fourth-round review on #2374: a single-sensor flex-model
dict containing inflexible-consumption/inflexible-production was a no-op in
classification, so it would be silently scheduled as a normal device. Now raise
'only supported in multi-device flex-models' (mirroring the group field), and add
a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>
@Flix6x

Flix6x commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

Addressed round 4: a single-sensor flex-model declaring inflexible-consumption/inflexible-production now raises "only supported in multi-device flex-models" (mirroring the group field) instead of silently being scheduled as a normal device. Added a regression test.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Human review recommended

It changes core scheduling/device-inventory classification and grouping semantics, so a final human review should confirm no subtle regressions beyond the updated tests and docs.

Review details
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.


* New ``inflexible-consumption`` and ``inflexible-production`` flex-context fields make explicit how the sign of each inflexible device's power data should be read (positive values denote consumption resp. production), accepting sensor references with optional source filters; they replace the now-deprecated ``inflexible-device-sensors`` field (bare sensor IDs, sign read from each sensor's ``consumption_is_positive`` attribute), which remains supported. Each inflexible device may also carry a ``group`` field, so that inflexible (measured) load counts towards the intermediate power constraint of the group it belongs to [see `PR #2358 <https://www.github.com/FlexMeasures/flexmeasures/pull/2358>`_]
* New ``inflexible-consumption`` and ``inflexible-production`` flex-context fields make explicit how the sign of each inflexible device's power data should be read (positive values denote consumption resp. production), accepting sensor references with optional source filters; they replace the now-deprecated ``inflexible-device-sensors`` field (bare sensor IDs, sign read from each sensor's ``consumption_is_positive`` attribute), which remains supported [see `PR #2358 <https://www.github.com/FlexMeasures/flexmeasures/pull/2358>`_]
* An inflexible (unschedulable) device can be modelled as its own asset by giving its flex-model entry a single ``inflexible-consumption`` or ``inflexible-production`` sensor reference; such a device joins a ``group`` like any other member, so its fixed (measured) load counts towards the group's intermediate power constraint [see `PR #2374 <https://www.github.com/FlexMeasures/flexmeasures/pull/2374>`_]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* An inflexible (unschedulable) device can be modelled as its own asset by giving its flex-model entry a single ``inflexible-consumption`` or ``inflexible-production`` sensor reference; such a device joins a ``group`` like any other member, so its fixed (measured) load counts towards the group's intermediate power constraint [see `PR #2374 <https://www.github.com/FlexMeasures/flexmeasures/pull/2374>`_]
* An inflexible (unschedulable) device can be modelled as its own asset by giving its flex-model entry a single ``inflexible-consumption`` or ``inflexible-production`` sensor reference; such a device can be assigned to a ``group`` like any other member, so its fixed (measured) load counts towards the group's intermediate power constraint [see `PR #2374 <https://www.github.com/FlexMeasures/flexmeasures/pull/2374>`_]

Comment thread documentation/features/scheduling.rst Outdated
Comment thread documentation/features/scheduling.rst Outdated
Flix6x and others added 2 commits July 31, 2026 20:06
…e, and it may set a commodity

Addresses review questions on #2374: without a group, a flex-model inflexible
device is simply accounted for under the grid connection (like the flex-context
list, only declared on the asset); with a group it additionally counts towards
that group's constraint. It may also set a commodity like any device entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>
…vice

The flex-model inflexible tests all used the default (electricity) commodity;
only the flat flex-context lists had per-commodity coverage. Add a test that a
flex-model inflexible entry with commodity=gas is classified with that commodity
and joins the gas device group (not electricity).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>
@Flix6x
Flix6x merged commit 42a79c6 into main Jul 31, 2026
13 checks passed
@Flix6x
Flix6x deleted the feat/inflexible-device-assets branch July 31, 2026 19:04
Flix6x added a commit that referenced this pull request Jul 31, 2026
…mmitments

Brings in #2374 (inflexible devices as flex-model assets); clean auto-merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaMepbxRYzJxQKFtu6Hq4p
Signed-off-by: F.N. Claessen <felix@seita.nl>
Flix6x added a commit that referenced this pull request Aug 2, 2026
Only documentation/changelog.rst conflicted: main reworded the #2358 entry and
split the group-membership part out into #2374, so this takes main's wording for
both and keeps this branch's #2306 entry alongside them.

Signed-off-by: F.N. Claessen <felix@seita.nl>
Flix6x added a commit that referenced this pull request Aug 2, 2026
Brings in #2295 (sensor/group-scoped commitments), #2358 (inflexible-consumption
/ inflexible-production replacing inflexible-device-sensors), #2374 (inflexible
devices as assets), #2278 (operation-mode power bands) and #2306 (rate limiting).

Conflict resolutions of note:

* schemas/scheduling/storage.py -- main moved GroupReferenceSchema into the new
  schemas/scheduling/groups.py and storage.py now imports it, so the branch's
  local copy is dropped rather than merged. Kept _validate_coupling_name (still
  used by both flex-model schemas) alongside main's new
  validate_inflexible_flex_model_entry.
* linear_optimization.py -- coupling groups (this branch) and operation-mode
  power bands (main) are independent features; both kept.
* devices.py -- FlexDevice gains main's inflexible-device fields next to this
  branch's coupling fields.
* storage.py -- the device_scheduler call passes both coupling_groups and
  device_power_bands.

flexmeasures/data/models/planning + flexmeasures/data/schemas: 579 passed,
3 xfailed. black and flake8 clean.

Note: #2306 imports `limits`, which is resolved via uv.lock but not declared in
pyproject.toml, so existing venvs need `uv sync --all-groups`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEvWAj45zXaod5WjniF81D
Signed-off-by: F.N. Claessen <felix@seita.nl>
Flix6x added a commit that referenced this pull request Aug 2, 2026
Picks up feat/chp's merge of origin/main (#2295 sensor/group-scoped commitments,
#2358 inflexible-consumption/-production, #2374 inflexible devices as assets,
#2278 operation-mode power bands, #2306 rate limiting).

Two conflicts, both additive: this branch's internal-node balance groups and
feat/chp's operation-mode power bands are independent features. The
device_scheduler call now passes all three feature arguments side by side:
coupling_groups (converters), balance_groups (internal commodity nodes) and
device_power_bands (operation modes).

flexmeasures/data/models/planning + flexmeasures/data/schemas: 586 passed,
3 xfailed. black and flake8 clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEvWAj45zXaod5WjniF81D
Signed-off-by: F.N. Claessen <felix@seita.nl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants