Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 54 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
# Changelog

## 0.8.0 (2026-10-22)

Goal: carry the cooling trim hold in code so the live agent cannot drop it by accident, explain the 0.7.0 ramping rise first, and get live ramping below the baseline without giving back cost, emissions, comfort or the peaks against 0.6.0 live.

Why the 0.7.0 live month ramped more than 0.6.0 live (1.0358 against 1.0174):

- **The KPI's denominator is built inside each run.** CityLearn divides the run's sum of hourly rises in district draw by the same run's draw with storage removed and cooling at the ideal load, not by the baseline run. In hour 399, during an outage in Buildings 1 and 2, the 0.7.0 agent asked for extra cooling; the grid draw was 0 anyway, but CityLearn took the extra cooling off its reference (-0.71 kWh), and the climb back at hour 400 added 0.71 kWh of rises to the denominator only. That is why the hourly series gives 1.0374 against the baseline run and the KPI 1.0358. 0.6.0 matched exactly because its cooling was at the baseline in that outage.
- **Split exactly by cause** (Shapley shares of each hour's rise, adding up to CityLearn's figure; points of ramping above 1.0, 0.6.0 live against 0.7.0 live): trims net +2.52 against +2.74 (ends +6.37 against +5.29, starts -4.84 against -3.30, depth +0.98 against +0.75); battery charging -0.60 against +1.12; battery discharging -0.10 against -0.33; hot water tank 0.00 against +0.18; extra cooling -0.07 against +0.03; the outage-hour effect 0.00 against -0.15. The scripted v5 strategy: trims +1.81, battery charging +1.36, discharging -3.51.
- **The cause is the battery, not the trims.** Battery charging accounts for 1.72 of the 1.84 point rise. 0.7.0 charged 184 kWh against 272 and discharged 156 kWh against 237. 0.6.0's daytime charging stopped, and its daytime discharges started, as the afternoon load climbed, which cancelled rises; 0.7.0 rarely charged in the day and discharged in only 35 of the 80 building hours where the strategy says to cut the daytime peak (0.6.0: 46 of 74, scripted: 51 of 51). The trims are the largest single cause in every run but look much the same in both. The scripted strategy is below the baseline mainly because of its discharging.

Changes:

- **Trim hold in the envelope** (rule `trim_hold`, `EnvelopeConfig.trim_hold`, numbers from `StrategyParamsV5`). Per building: whether a trim is on (cooling more than 0.002 below the baseline action) and how deep. Occupied and more than 0.5 C below the setpoint: at least as deep as last hour. Within 0.5 C: eases off by at most 0.02 per hour. Ends at once at or above the setpoint, when unoccupied, or with no baseline cooling, and none may start there. `null` keeps a held trim, deeper is allowed, and a miss under 0.002 is rounding (the full depth stays held). It runs after the comfort rule and only keeps cooling below the baseline within the deviation limit. The spread check, peak limiter, comfort rule, battery limits, JSON envelope, fallback and budget cap are unchanged. Not a ramp taper.
- **`end_trim` per building** in prompt version 6 replies: `null` or a reason, the only way to end a held trim early. Every hold action (start, hold, ease, release, end, early end) is recorded in the decision's `holds` with its reason; changed values are clamps with rule `trim_hold`. Early ends show in the replay viewer's reason card and the live log, and the viewer data counts them (`trim_ends_early`).
- **Prompt version 6 (default).** Version 5 plus the hold and `end_trim` in the strategy, `cooling_trim_held` per building, and `strategy_battery` with `strategy_battery_reason` (the version 5 strategy's own battery action, `battery_plan_v5`) in place of the 0.4.0 rule-based `reference_action`. `strategy_plan_v5` returns exactly what it did. Requests are 4.8 percent larger than version 5 (10,928 against 10,432 characters).
- **Versioned rules.** Manifests without the new settings rebuild without the hold, and their decisions carry no `holds` key, so every older run replays byte for byte. `EnvelopeConfig.v070()` is the 0.7.0 rule set, used for new runs on prompt versions 1 to 5. The 0.6.0 and 0.7.0 live months and the committed baseline replay 719 of 719 hours.
- **Tools.** `scripts/split_ramping.py` (the exact split), `scripts/evaluate_hold.py` (a recorded run's own replies through its own rules, which must reproduce its KPIs, and through the hold; an evaluation, never a recorded run), `RecordedReplySupervisor`, and `scripts/tune_strategy.py --version 6`. The version 4 and 5 searches now pin the 0.7.0 rules they were made with.
- `hyperbolic serve`'s first cost estimate uses the version 6 request size (5,200 input and 790 output tokens). `compare --against` labels scripted runs by prompt version. The page's How it works strip names the trim hold.
- Tests cover the hold (on, hold, ease, release, every end, early end with a reason, rounding, logging, fallback, rule order, older rules unchanged, byte-for-byte replay with hold actions, changed hold settings detected), the version 6 schema, parsing, observation, prompt and request size, the scripted version 6 reply, recorded replies, the viewer's early ends, 24 hour and full-month version 6 CityLearn runs, and the split and evaluation tools.

Estimates before any live run (tuning months first; nothing tuned on the phase 2 month):

- **Scripted v5 strategy, tuning months**, 0.7.0 against 0.8.0 rules: ramping 0.9816 against 0.9821, daily peak 0.8834 against 0.8836 and load factor 0.9517 against 0.9522 slightly worse; cost 0.9089 against 0.9086, emissions 0.9610 against 0.9607 and all-time peak 0.8532 against 0.8530 slightly better; discomfort equal at 0.0310. The rounding allowance was added here: without it discomfort rose to 0.0312 and the hold clamped 247 to 443 times a month. The strategy's own trims drift shallower by about 0.0015 an hour through rounding, and the hold stops that.
- **Scripted v5 strategy, phase 2 month**: ramping 0.9966 against 0.9957, daily peak 0.9081 against 0.9078, all-time peak 0.9597 against 0.9593 better; emissions, grid import and load factor unchanged to four decimals; cost 0.9015 against 0.9017 and discomfort 0.0424 against 0.0430 slightly worse. Clamped hours 1 against 139.
- **0.7.0 live replies through the 0.8.0 rules** (control reproduces the published 0.7.0 KPIs exactly): cost 0.9320 to 0.9169, emissions 0.9635 to 0.9477, grid import 0.9684 to 0.9527, discomfort 0.0741 to 0.0511, daily peak 0.9393 to 0.9284, all-time peak 0.9592 to 0.9548, ramping 1.0358 to 1.0249, load factor 0.9747 to 0.9787 (worse). Against 0.6.0 live that is better on cost, emissions, discomfort and the daily peak, and worse on the all-time peak and ramping, which stays above the baseline. Trim rule breaks 142 to 4. Clamped hours 66 to 323.
- **The battery change in prompt version 6 is not in any estimate and can only be measured live.**
- A Haiku month should cost about $0.66; the hard worst case is $0.99, under the $2.00 cap.

Live run (`claude-haiku-5-5`, full month, 719 hours, prompt version 6), against the baseline, the 0.4.0 rule-based controller (rerun as run 20261022T162847Z, matching its published numbers) and the earlier live months:

| CityLearn KPI (district), full month | Baseline | 0.4.0 rule-based | 0.6.0 live | 0.7.0 live | 0.8.0 live |
|---|---|---|---|---|---|
| cost_total | 1.000 | 0.9611 | 0.9219 | 0.9320 | 0.9190 |
| carbon_emissions_total | 1.000 | 0.9947 | 0.9665 | 0.9635 | 0.9610 |
| electricity_consumption_total | 1.000 | 1.0073 | 0.9740 | 0.9684 | 0.9695 |
| discomfort_proportion (too cool, too warm) | 0.1714 (0.1538, 0.0176) | 0.1714 (0.1538, 0.0176) | 0.0861 (0.0680, 0.0181) | 0.0741 (0.0560, 0.0181) | 0.0769 (0.0601, 0.0168) |
| daily_peak_average | 1.000 | 0.9978 | 0.9354 | 0.9393 | 0.9264 |
| all_time_peak_average | 1.000 | 1.0000 | 0.9483 | 0.9592 | 0.9593 |
| ramping_average | 1.000 | 1.1309 | 1.0174 | 1.0358 | 1.0076 |
| daily_one_minus_load_factor_average | 1.000 | 0.9913 | 0.9773 | 0.9747 | 0.9651 |
| power_outage_normalized_unserved_energy_total | 0.6844 | 0.6844 | 0.6844 | 0.6877 | 0.6850 |
| Clamped hours, fallback hours | | 1, 0 | 73, 0 | 66, 0 | 312, 0 |
| Model cost | | none | $0.5740 | $0.6329 | $0.5315 |

- **Against the 0.4.0 rule-based controller it wins on every KPI except unserved energy in outages**, where it trails by 0.0006 (0.6850 against 0.6844). Thermal resilience ties at 0.3698.
- **The first live run with both fewer too-cool and fewer too-warm hours than the baseline** (0.0601 against 0.1538, 0.0168 against 0.0176). 0.6.0 and 0.7.0 live added warm hours (0.0181).
- **The best live run so far on cost, emissions and the daily peak.** Not on discomfort (0.7.0 live: 0.0741), grid import (0.7.0 live: 0.9684), the all-time peak (0.6.0 live: 0.9483), or ramping and load factor (0.4.0 live, at baseline comfort: 0.9965 and 0.9559).
- **Missed the 0.8 goal on ramping**: 1.0076, down from 1.0358 and below 0.6.0 live (1.0174) and the 1.0249 estimate, but still above the baseline.
- **Gave back the all-time peak against 0.6.0 live** (0.9593 against 0.9483). Cost, emissions, discomfort and the daily peak improved on 0.6.0 live.
- **312 of 719 hours clamped**, 276 by the trim hold alone and 292 with it (243 clamps on Building_1 cooling, 100 on Building_3, 2 on Building_2); comfort in 28 hours, state of charge in 6, deviation in 2, peak in 1. The hold acted 557 times (109 starts, 243 holds, 97 eases, 21 releases, 80 ends, 7 early ends with a reason). The envelope is steering the agent. 0 fallbacks, 719 calls, $0.5315 of $2.00, replays 719 of 719 hours deterministically.
- The published viewer (`docs/data`) now shows the 0.8.0 live run in place of 0.6.0.

Next for 0.9: cut the clamp rate without losing these gains.

## 0.7.0 (2026-10-22)

Goal: bring ramping below the baseline and the load factor back toward 0.4.0 without giving back cost, emissions, comfort or the peaks, and clean up the public page.
Expand Down
Loading
Loading