Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cec0a6c
Add initial version of openadr-plugin
May 20, 2026
f27d1bb
chore: upgrade minimum version to FM v0.33
Flix6x Jun 10, 2026
399ba39
Use SHA hashes for github actions, use ingestion queue, add pytest sp…
Jun 22, 2026
a952a5f
Update openadr3-client to latest version
Jun 22, 2026
36b888e
rename function, move top level imports
Jun 22, 2026
5f8d3b1
Fix mypy, ruff errors
Jun 23, 2026
bdac3d2
Set credits to elaad and foss email
Jun 23, 2026
0ead655
Remove certs
Jun 23, 2026
2ff2a5d
Clean up str based time storage in favor of python native time type
Jun 25, 2026
4e393e0
Fix structure of tests. Ensure tests pass with FM 0.33.0
Jun 26, 2026
bd0635d
Fix type errors, formatting
Jun 26, 2026
ff9a614
Newline fix
Jun 26, 2026
e57f98a
newline fix gitignore
Jun 26, 2026
a0be498
Add cronscheduler to plugin
Aug 20, 2026
84416f4
Add threading for cronscheduler
Aug 20, 2026
71497d9
Add cron scheduler as a dedicated worker which allows flexmeasures to…
Aug 20, 2026
61d52ad
Make final improvements related to openadr plugin initial version
Sep 2, 2026
57a7cdb
Clean up modules
Sep 2, 2026
1162c11
Fix potential lock issue in fresh start scenario
Sep 2, 2026
c90bcb4
Process PR comments
Sep 2, 2026
86b094f
Resolve mypy and ruff errors
Sep 2, 2026
545bd4b
Final fixes for typing and formatting
Sep 2, 2026
0f78822
Update uv lock with correct CI version
Sep 2, 2026
536efee
Upgrade uv to latest version
Sep 2, 2026
f913f83
Update trigger for CI
Sep 2, 2026
8dd1826
Pin to darwin and linux platform due to testcontainer limitation
Sep 2, 2026
8cf5440
Remove extra whitespace from CI
Sep 2, 2026
a74936b
Update pre commit config yaml
Sep 3, 2026
c9465f1
Create initial WIP example which creates asset structure and configur…
Sep 4, 2026
c6239bb
Introduce semi-realistic forecasts for all assets in lf-energy-demo
Sep 4, 2026
02f62f7
Initial 'good enough' LF energy demo scenario
Sep 8, 2026
6654eab
merge main into branch
Sep 8, 2026
f956f15
Fix account_id bug in asset, clean up example
Sep 16, 2026
d03add6
Improve example
Sep 16, 2026
e8f45b3
Update live demo walkthrough script
Sep 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/instructions/README.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks like these .github instructions are copied from the flexmeasures repo. I think it would make sense to view these as being applicable to the FM server and all FM plugins (basically FlexMeasures organization-wide). I see 3 ways forward:

  1. Keep the files in flexmeasures only, and have plugins (including the flexmeasures-plugin-template repo) point to them in their AGENTS.md. Not sure if agents will respect that.
  2. Move the files to the tsc (or a new dedicated) repo under the FlexMeasures organization. Same uncertainty as 1.
  3. Have them duplicated in each plugin, and keep them in sync (perhaps through a dedicated test in the plugin, against the instructions set in the flexmeasures repo).
  4. Have them duplicated in each plugin; accept diverging.

Do you want to try 1, which would be my preference? I'm afraid you happen to be the first plugin author to face this issue.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# `.github/instructions/` — Path-Specific Custom Instructions

This directory contains [path-specific custom instructions](https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-repository-instructions#creating-path-specific-custom-instructions) for GitHub Copilot.

Each `<topic>.instructions.md` file covers a cross-cutting convention that applies to multiple areas of the codebase. Copilot automatically applies these instructions when working on files that match the `applyTo:` glob pattern in the file's frontmatter.

## Files in this directory

| File | `applyTo` | Topic |
|------|-----------|-------|
| `atomic-commits.instructions.md` | `**` | Commit discipline — one logical change per commit |
| `changelog.instructions.md` | `**` | Changelog entry format and location |
| `docstrings.instructions.md` | `**/*.py` | RST docstring format, doctests |
| `error-handling.instructions.md` | `**/*.py` | Catching specific exceptions |
| `marshmallow-schemas.instructions.md` | `flexmeasures/data/schemas/**/*.py` | `data_key`, field naming, `load_default` |
| `pre-commit-hooks.instructions.md` | `**` | Running hooks before every commit |
| `testing.instructions.md` | `flexmeasures/**/tests/**/*.py` | Full suite, `db` vs `fresh_db`, `requesting_user` |
| `timezone-awareness.instructions.md` | `**/*.py` | Always timezone-aware datetimes |
| `ui-terminology.instructions.md` | `flexmeasures/ui/**` | "organisation" not "account" in user-facing text |

## Adding new instruction files

When a convention appears in two or more agent files or is frequently missed, extract it here:

1. Create `<topic>.instructions.md` in this directory.
2. Add a YAML frontmatter block with `applyTo:` pointing to the relevant files.
3. Write concise, actionable instructions in natural language Markdown.
4. Update the table above.
5. Reference the new file from the relevant agent files in `.github/agents/`.
6. Go through the agent files to remove sections that have been made redundant by the new file.
56 changes: 56 additions & 0 deletions .github/instructions/atomic-commits.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
applyTo: "**"
---
# Atomic Commits

Each commit must represent exactly one logical change. Never mix different types of changes.

## What belongs in separate commits

- Production code changes
- Test changes
- Documentation updates
- Agent instruction updates
- Changelog entries
- Configuration / CI changes

## Forbidden in commits

Never commit temporary planning or analysis files:
- `ARCHITECTURE_ANALYSIS.md`, `TASK_SUMMARY.md`, `TEST_PLAN.md`, `DOCUMENTATION_CHANGES.md`
- Any `.md` file created for understanding or planning (use `/tmp/` if you need scratch space)

## Commit message format

```
<area>: <concise description of what changed and why>

Context:
- What triggered this change

Change:
- What was adjusted and why
```

Examples:
```
utils/time: fix duration parsing to respect timezone

Context:
- Bug #1234: PT2H parsed incorrectly in CET timezone

Change:
- Pass timezone through to isodate.parse_duration
```

```
agents/test-specialist: add full-suite requirement after governance failure

Context:
- Session 2026-02-10 revealed partial test execution as root cause

Change:
- Added explicit requirement to run complete test suite
```

Use the file path or area as the prefix (e.g. `api/v3_0`, `data/models`, `cli`, `docs`, `agents/<name>`).
68 changes: 68 additions & 0 deletions .github/instructions/changelog.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
applyTo: "**"
---
# Changelog Entries

Each PR generally requires a changelog entry.

## Changelogs

| File | Audience |
|------|----------|
| `documentation/changelog.rst` | Main changelog — API/CLI/UI users and plugin developers |
| `documentation/api/changelog.rst` | API-specific changes |
| `documentation/cli/changelog.rst` | CLI-specific changes |

## Entry format

Always follow the formatting convention already present in the target changelog file — the style may evolve over time. The canonical guide is the file itself.

Current conventions:
- **Main changelog**: one sentence, no period at the end, written for end users (abstract away technical details when possible)
- **API and CLI changelogs**: slightly more technical audience; use a period at the end

Example for the main changelog:

```rst
* Add cross-cutting Copilot instruction files to `.github/instructions/` [see `PR #XXXX <https://www.github.com/FlexMeasures/flexmeasures/pull/XXXX>`_]
```

Replace `XXXX` with the actual PR number. If the PR number is not yet known, alert the maintainer.

## Sections in `documentation/changelog.rst`

Always use this order:

- **New features** — new capabilities visible to API/CLI/UI users
- **Infrastructure / Support** — changes targeting plugin developers and hosts
- **Bugfixes** — corrections to incorrect behavior

## PR description checkbox

The PR template includes a changelog checkbox:

```markdown
- [ ] Added changelog item in `documentation/changelog.rst`
```

Tick it once the changelog entry is committed.

## What requires a changelog entry

Each PR generally requires an entry. Examples of what warrants one:

- New API endpoints or parameters
- Changed or removed API behavior
- New CLI commands or options
- UI feature additions or changes
- Performance improvements that affect users
- Breaking changes (always require a changelog entry, plus migration notes)
- Changes to plugin interfaces
- Significant changes to the repo's AI infrastructure

## What does not require a changelog entry

- Internal refactoring with no user-visible effect
- Test-only changes
- Small agent instruction updates (typo fixes, minor wording changes)
- Pure documentation typo fixes
67 changes: 67 additions & 0 deletions .github/instructions/docstrings.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
applyTo: "**/*.py"
---
# Python Docstrings

All public functions, methods, and classes must have docstrings. Use RST (reStructuredText) format for Sphinx compatibility.

## Standard function docstring

```python
def function_name(param1: str, param2: int) -> bool:
"""One-line summary ending with a period.

Longer description explaining purpose and usage when needed.
Parameter descriptions are aligned and separated from the colon
with at least one space.

:param param1: Description of param1.
:param param2: Description of param2.
:returns: Description of return value.
:raises ValueError: When param1 is empty.

Example::

>>> function_name("test", 42)
True
"""
```

## Key conventions

- One-line summary ends with a period and fits on one line.
- Leave one blank line between the summary and the extended description.
- Align `:param name:` descriptions using spaces (not tabs) for readability.
- Use `Example::` (double colon) to introduce a doctest block.
- Complement type hints — don't duplicate them in the docstring text.
- Use exactly one space after punctuation (no double spaces after periods).
- Use line breaks only after punctuation (this facilitates review commenting and text searching). This applies to in-line comments as well, not only docstrings; keep in-line comments short. So never wrap a docstring or comment in the middle of a phrase; each physical line must end at a comma, semicolon, colon, or period. (E501 is ignored and `max-line-length` is 160, so a long clause on one line is preferred over a mid-phrase break.)

## For code review (incl. automated reviewers)

The line-break-after-punctuation rule above is a deliberate, load-bearing convention (stable review comments and text search), not a stylistic nicety. When reviewing a change, always report a docstring or comment that wraps mid-phrase as a review comment; do not treat such a finding as low-confidence, and do not omit or suppress it.

## Click CLI commands

```python
@click.command()
def my_command():
"""One-line summary of what the command does.

Longer description with usage context and examples if helpful.
"""
```

## Doctests

Include doctests in docstrings for pure utility functions. Run them with:

```bash
pytest --doctest-modules
```

Doctests in `documentation/` are also executed. Keep examples accurate and test them before committing.

## Comments

Comments explain *why*, not *what*. Avoid redundant comments that just restate the code. Include issue numbers or external links in TODO comments when relevant.
81 changes: 81 additions & 0 deletions .github/instructions/error-handling.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
applyTo: "**/*.py"
---
# Error Handling

Catch specific exceptions, not bare `Exception`. Broad catches hide bugs and make debugging difficult.

## What to catch and when

```python
from sqlalchemy.exc import SQLAlchemyError

# ✅ Catch specific, expected failures
try:
obj = create_or_fetch(...)
except SQLAlchemyError as e:
db.session.rollback()
return error_response("Database error", 500)
except ValueError as e:
return error_response(str(e), 400)
# Let unexpected exceptions (AttributeError, TypeError, etc.) propagate
# — they indicate bugs that should fail loudly
```

## Never do this

```python
# ❌ Too broad: catches programming errors
try:
result = some_operation()
except Exception as e:
return error_response("Something went wrong")
```

## Exception categories

| Exception type | When to catch |
|----------------|---------------|
| `SQLAlchemyError` | Database connection, integrity, or query errors |
| `ValueError` | Invalid input that was expected and validated |
| `KeyError` | Missing required data in a known structure |
| `AttributeError` | **Never** — indicates a bug in your code |
| `TypeError` | **Never** — indicates a bug in your code |
| `NameError` | **Never** — indicates a bug in your code |

## Error messages

Good error messages state what went wrong, explain why, and suggest a fix:

```python
raise ValueError(
f"Invalid sensor ID {sensor_id}. "
f"Sensor must belong to account {account.name}. "
f"See https://flexmeasures.readthedocs.io/..."
)
```

## HTTP status codes in API endpoints

- `400 Bad Request` — invalid client input (validation failure)
- `401 Unauthorized` — authentication required
- `403 Forbidden` — authenticated but not permitted
- `404 Not Found` — resource does not exist
- `500 Internal Server Error` — unexpected server-side failure

## get-or-create idempotency

Never rely on `obj.id is None` to detect if an object is newly created (SQLAlchemy may not assign IDs until commit). Return an explicit boolean instead:

```python
def get_or_create_thing(...):
existing = db.session.query(Thing).filter_by(...).first()
if existing:
return existing, False # (object, was_created)
new_obj = Thing(...)
db.session.add(new_obj)
return new_obj, True

thing, was_created = get_or_create_thing(...)
status_code = 201 if was_created else 200
```
42 changes: 42 additions & 0 deletions .github/instructions/feature-branch-sync.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
applyTo: "**"
---
# Feature Branch Synchronization

Feature branches must be kept synchronized with `origin/main` before implementing code changes.

## Check branch status

Before starting implementation work, verify the branch is up to date:

```bash
git log --oneline origin/main...HEAD --left-right
```

If you see < markers, origin/main has commits the branch lacks — a fresh merge is needed.

```bash
# ❌ Don't just check git status (it only tells you about uncommitted changes)
git status # shows "nothing to commit" even if behind main

# ✅ Do check the commit graph
git log --left-right origin/main...HEAD
```

## Merge before implementation

```bash
git fetch origin
git merge origin/main
# Resolve any conflicts
git add .
git commit -m "Merge origin/main into feature branch"
```

This ensures your implementation starts from the latest state of the repository.

## Why this matters

- Merging later causes merge conflicts to compound
- Large late merges are harder to review
- Feature work should build on current main, not diverge
Loading
Loading