Enhance the handling of the Copilot CLI to ensure better user-focused output and prevent issues with empty responses. Adjustments include using a pipe for input and adding checks for output validity.
Impact: Users receive more accurate and user-friendly release notes without technical jargon.
Included Anthropic Claude and OpenAI ChatGPT extensions to support AI-assisted coding features.
User-Impact: Developers can leverage AI tools for improved productivity and code suggestions.
Add a step to trigger the release notes workflow after creating a version tag. This ensures that the release notes are generated even when the tag push does not automatically trigger the workflow due to GitHub's recursion guard.
Impact: Users will receive timely release notes corresponding to new version tags.
_calculate_metadata()'s inline calc_stats() computed the median as a
naive sorted(data)[len(data) // 2], which returns the upper-middle
value for even-length datasets instead of averaging the two middle
values. A full day is always an even interval count (96 quarter-hours
or 24 hours), so this silently overstated "median" and
"median_position" in nearly every price_stats block of the
get_chartdata response. The rest of the codebase already has a
correct calculate_median() in utils/average.py; this was an isolated
inline duplicate with the bug.
Impact: get_chartdata's price_stats.combined/dayN.median and
median_position now report the statistically correct median for
chart annotations and metadata-driven dashboards.
check_min_distance_from_avg() computed the distance threshold as
range_avg * (1 ± ratio). Tibber prices can go negative during grid
oversupply, and multiplying a negative range_avg directly flips the
intended direction: e.g. avg * 1.05 makes a negative average MORE
negative (i.e. cheaper), which is the wrong direction for a
"most expensive" threshold check, and analogously wrong for
"cheapest" checks.
Compute the threshold as range_avg ± abs(range_avg) * ratio instead,
matching the sign-safe normalization pattern already used for
min_distance_from_avg in the period system
(coordinator/period_handlers/level_filtering.py). Behavior for
positive averages (the common case) is unchanged.
Used by find_cheapest_block, find_cheapest_hours, and plan_charging.
Impact: min_distance_from_avg now correctly filters cheapest/most
expensive windows during negative-price periods instead of silently
accepting windows in the wrong direction relative to the search range
average.
find_cheapest_block, find_cheapest_hours, and find_cheapest_schedule
accept an optional power_profile (fixed per-interval watt array
matching the requested duration/task length). When allow_relaxation
was enabled and no full-duration window could be found, the
duration-reduction relaxation phase silently reduced the interval
count without shrinking power_profile accordingly. Downstream code
(find_cheapest_contiguous_window, calculate_window_statistics,
_find_cheapest_window_in_pool) then truncated the profile from the
front to match, dropping trailing appliance-cycle phases and using
the wrong per-interval weights for both window selection and the
reported cost estimate.
Disable duration-reduction relaxation whenever a power_profile is
supplied (find_cheapest_schedule guards per-task via
any_task_has_power_profile); distance and level-filter relaxation
phases remain available since they don't affect interval count.
Impact: Services with a power_profile no longer silently pick a
shorter window with mismatched power weighting during relaxation;
they now correctly report no window found if the full duration isn't
available, preserving the accuracy of appliance-cycle cost estimates.
Add a real (non-mocked) end-to-end test exercising apply_must_finish_by
and resolve_search_range together with a range-filtering fake pool,
reproducing the exact scenario from GH #168: a naive must_finish_by
datetime combined with search_start_day_offset: 0. The underlying fix
already landed in db5d172 but had no test covering the full request
pipeline (only individual helpers were mocked in existing tests).
Release-Notes: skip
User-Impact: none
_find_cheapest_window_in_pool() scans for contiguous available blocks
when scheduling multiple tasks. When a block-in-progress hit a
temporal gap (e.g. from price-level filtering removing intervals from
the middle of the search range, or missing API data), the scanner
jumped to i = j + 1 instead of i = j, silently skipping the interval
right after the gap as a valid — sometimes cheaper — window start.
Distinguish 'unavailable slot' (correctly skipped via j + 1) from
'temporal gap' (must retry at j, since that slot was never actually
tested as a window start).
Impact: find_cheapest_schedule can now find the true cheapest window
for a task when the search range contains time gaps, instead of
occasionally picking a more expensive window right after such a gap.
apply_segment_constraints could add far more grid energy than requested when
max_cycles_per_day or min_charge_duration_minutes forced bridging across
expensive gaps between cheap intervals. With max_cycles_per_day=1, isolated
cheap intervals were merged into one continuous segment by filling every gap
in between, without ever trimming the surplus back down, resulting in
achieved_soc_percent far above 100%.
Add a post-bridging trim step that removes segment-edge intervals (highest
price first) until total grid energy matches the requested target again,
while still respecting max_cycles_per_day/min_charge_duration_minutes and
never dropping below the target itself (fixed-power mode's expected
last-interval rounding overshoot is preserved).
A related edge case is also fixed: trimming could previously remove an
interval required to satisfy a must_reach_by deadline, silently flipping
deadline_met to False even though the overall energy target was still
reached. Deadline-critical intervals are now passed through as
protected_starts and are never removed during trimming.
Fixes#167
Impact: plan_charging no longer overcharges the battery/EV past the
requested target SoC when max_cycles_per_day or min_charge_duration_minutes
is set, and must_reach_by deadlines are honored even when those constraints
require bridging across expensive price gaps.
Updated the description for Norway and Sweden's fee structures to specify that the energy price unit depends on the display mode, enhancing clarity for users implementing templates.
Impact: Users will have a clearer understanding of how to handle energy price units in their configurations.
Revise the Germany section to focus on feed-in compensation for exported PV energy and provide detailed steps for creating input number helpers and template sensors.
Impact: Users can better understand and implement feed-in compensation calculations in their Home Assistant setups.
Clarify the unit display modes for energy prices and provide guidance on template normalization for user-specific setups.
Impact: Users gain clearer instructions on adapting energy price calculations to their local currency display settings.
Add UV_PRERELEASE=allow to the format, lint-check, and lint-fix scripts to enable pre-release features in Ruff.
Impact: Users can now utilize pre-release features during code formatting and linting processes.
Updated error messages in German, English, Norwegian, Dutch, and Swedish translations to remove unnecessary quotes around placeholders. This improves clarity and consistency in error reporting.
Impact: Users will see clearer error messages without quotes around variable placeholders.
Updated the default Home Assistant version in the bootstrap script and requirements file to ensure compatibility with the latest features and fixes.
Impact: Users will benefit from improved stability and new features available in Home Assistant 2026.4.4.
Updated the step value for number fields in the plan_charging service to allow any value instead of a fixed increment. This change enhances flexibility in user input.
Impact: Users can now specify any value within the defined range for charging plans.
---
refactor(translations): update error message formatting for entity attributes
Modified the error messages in multiple translation files to remove curly braces around entity attributes. This improves consistency in message formatting across languages.
Impact: Users will see cleaner error messages when attributes are not found.