Commit Graph
810 Commits
Author SHA1 Message Date
glenn schrooyenandClaude de0790e62d MAINT-25: the Home plan shows no cycle during the 7-day back-off
checks / unit (pull_request) Successful in 27m21s
infra-pin / fresh (pull_request) Successful in 1s
homeview.maintenance_runs() ignored backoff_until(); it drew a cycle every
night of the wait. Now no run and a plain line (EN, NL). test_maint25.py.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-12 09:57:56 +01:00
glenn schrooyenandClaude b80cfa969f MAINT-24: test_peak_margin pins the maintenance checks to the guard's aim
checks / unit (pull_request) Successful in 29m32s
infra-pin / fresh (pull_request) Successful in 1s
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-12 08:22:13 +01:00
glenn schrooyenandClaude 6004bfad9a MAINT-24: read the last row without a bare index (test_named_absence)
checks / unit (pull_request) Successful in 26m37s
infra-pin / fresh (pull_request) Successful in 1s
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-12 08:15:01 +01:00
glenn schrooyenandClaude b44a648cab MAINT-24: test_maint24.py points at MUTATION.md
checks / unit (pull_request) Successful in 28m32s
infra-pin / fresh (pull_request) Successful in 1s
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-12 07:51:28 +01:00
glenn schrooyenandClaude 0f5e513f1d MAINT-24: keep the refusal probe beside a maintenance charge
checks / unit (pull_request) Failing after 45m44s
infra-pin / fresh (pull_request) Successful in 2s
The mode trade still lets a SAFETY-73 probe (PROBE_W alone) go on while a pack
is in its maintenance CHARGE phase; test_opt20.py g7 pins it. ch_ch_maint
digest moved (B no longer grid-charges beside A's charge).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-12 07:33:04 +01:00
glenn schrooyenandClaude 54a738dd87 MAINT-24: a started maintenance charge gets the cheap night
checks / unit (pull_request) Failing after 41m45s
infra-pin / fresh (pull_request) Successful in 2s
While a pack is in its maintenance CHARGE phase the mode trade files no grid
charge for the other packs (why "cycle", mirror of SAFETY-78). The maintenance
shaping check and charge floor aim at peakguard.quarter_target_w, month peak
included (SAFETY-80). Tests through cycle(): test_maint24.py.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-12 07:07:44 +01:00
admin 02eac3b84e Merge pull request #245: SAFETY-135 one guard stop does not cost the night charge the whole period
infra-pin / fresh (push) Successful in 2s
2026-11-11 20:55:30 +01:00
glenn schrooyenandClaude Opus 5.5 4066624cce SAFETY-135 round 2: the first guard stop in a period may restart once; tests and docs
checks / unit (pull_request) Successful in 29m42s
infra-pin / fresh (pull_request) Successful in 1s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC
2026-11-11 19:49:18 +01:00
glenn schrooyenandClaude 66d8777b39 SAFETY-135: a young 15-minute period does not cost the night charge the whole period
checks / unit (pull_request) Successful in 41m54s
infra-pin / fresh (pull_request) Successful in 2s
With battery modes on, a grid charge the peak guard (or a measured headroom)
stops in the first 60 s of a period no longer latches off for the period: it
may start again once the period is 60 s old, if the guard is clear and the
headroom is over START_W. A stop after 60 s latches as before. In a young
period no charge starts while the batteries' give is still falling (over
START_W within 15 s), since the meter may not show that drop yet. The guard
itself is unchanged, so a real over-aim load is cut on the same cycle.

DECISIONS/SAFETY-135-young-period.md, test_safety135.py.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-10 17:43:28 +01:00
admin a8ecf171d6 Merge pull request #244: SAFETY-136 a gentler loop on a slow meter until the last move shows
infra-pin / fresh (push) Successful in 2s
2026-11-09 22:35:21 +01:00
goodwe-agent 0f9c119bcf SAFETY-136 round 2: tests for override and direction, true wording
checks / unit (pull_request) Successful in 26m2s
infra-pin / fresh (pull_request) Successful in 2s
F1 the on-change case is tested as slow, F2 override and direction checks,
F3 the 3.75 s rule in the texts, F4 the quarter figures and the live note.
No behaviour change.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 20:51:06 +01:00
goodwe-agent c50e2279dd SAFETY-136: a gentler loop on a slow meter until the last move shows
checks / unit (pull_request) Successful in 26m18s
infra-pin / fresh (pull_request) Successful in 2s
On a meter whose readings come 4 s or more apart, the loop runs at half its
gain after a move of 150 W or more, until the meter has fallen by half of the
move or 2 cycles have passed. With readings 10 s late on a 5 s meter the export
falls 44 % over oven, kettle and hob, owner shape, steps; 1-2 s meters are
untouched.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 14:49:26 +01:00
admin 8508ac33f0 Merge pull request 'MAINT-21: split app/main.py Controller into ctl_*.py mixins' (#243) from MAINT-21 into release/1.0
infra-pin / fresh (push) Successful in 2s
2026-11-09 08:06:31 +01:00
glenn schrooyenandClaude Opus 5.5 8f0b8477e6 MAINT-21 review: two source scans read the split files too
checks / unit (pull_request) Successful in 31m44s
infra-pin / fresh (pull_request) Successful in 1s
test_safety118's "size rule is gone" and test_validate's "no numeric
maintenance_* fallback" read app/main.py only; the code they guard can now
sit in app/ctl_*.py, where a regression passed unseen. Both read
main_files.source() for main.py now. Tests only; no app change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 07:15:14 +01:00
glenn schrooyenandClaude 58b6fa35f5 MAINT-21 round 2: keep the move pure - revert the added DECISIONS text, restore cut comments
checks / unit (pull_request) Successful in 26m32s
infra-pin / fresh (pull_request) Successful in 1s
Router T241: the comments commit had put new rationale into
MAIN-orchestration.md and cut comment lines that the note at 56fc41f did not
hold.

- DECISIONS/MAIN-orchestration.md is the 56fc41f text plus the one sentence
  that the Controller is split into app/main.py and app/ctl_*.py.
- Comments whose content is not in a DECISIONS note at 56fc41f are back in the
  code verbatim: MAINT-05 one config, the SAFETY-02, SAFETY-42/34,
  SAFETY-30 site half, SAFETY-31 and SAFETY-18 latch blocks in __init__, the
  _grade_store_migration docstring and comment, the trade_power_w docstring,
  the rows.py docstrings.
- Kept: cuts of text already in the note, the SMA-10 / SAFETY-137 / SMA-2
  pointers, the SAFETY-32 line fix.

No code change: maint21_same_ast OK, maint20_same_code -OO same.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 05:48:00 +01:00
glenn schrooyenandClaude 902da3f723 MAINT-21: comments only - trim restated notes, add DECISIONS pointers
checks / unit (pull_request) Successful in 25m17s
infra-pin / fresh (pull_request) Successful in 1s
No code change: tools/maint21_same_ast.py and tools/maint20_same_code.py HEAD~
both print OK, and the -OO code objects are the same.

- Trims 56 comment and docstring lines (2088 -> 2032) in app/main.py and the
  new files that only restated their MAIN-orchestration.md bullet, each cut to
  its first sentence and a pointer. What the cut comments said and the bullet
  did not is now in the bullet: why a SAFETY-02 latch is restored, why the
  SAFETY-30 site check is not armed at one inverter, the SAFETY-18 re-derive,
  the MAINT-05 one-config rule, the OPT-09 sizing rules, the "no plan" row,
  the 5 400 s age bound, and the guard being the only latch repair.
- Adds the missing DECISIONS pointers on the SMA-10, SAFETY-137 and SMA-2
  comments (FALLBACK_BUDGET_S, write_setpoint, _await_inflight,
  _release_last, the retry wait, the failed-release branch, release_zero_sent,
  the in-flight write, the stop_event hand-back, the SMA-2 read and driver).
- DECISIONS/SAFETY-32: the stale `main.py:932-936` now names
  Controller.pack_floor_soc.
- main.py's docstring and import block say where the Controller's parts are.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:41:34 +01:00
glenn schrooyenandClaude 27a867f34b MAINT-21: app/ctl_tasks.py - Controller methods that run as tasks
Moves the methods named in the card and the constants only they read out of app/main.py unchanged. TasksMixin: run_control, run_tariff_refresh, fresh_tariff_plan and the store-migration grade. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:30:04 +01:00
glenn schrooyenandClaude 66952beb53 MAINT-21: app/ctl_status.py - Controller methods that build the status and MQTT output
Moves the methods named in the card and the constants only they read out of app/main.py unchanged. StatusMixin: checks, status_payload, forecast_payload, publish, mqtt_command, handle_action, why_words. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:30:00 +01:00
glenn schrooyenandClaude d3504fbbe7 MAINT-21: app/ctl_alarms.py - Controller methods that raise and clear alarms
Moves the methods named in the card and the constants only they read out of app/main.py unchanged. AlarmsMixin: the check_* alarms and the loop-alarm helpers. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:29:56 +01:00
glenn schrooyenandClaude 3939211176 MAINT-21: app/ctl_cycle.py - Controller.cycle, whole
Moves the methods named in the card and the constants only they read out of app/main.py unchanged. CycleMixin: cycle() and _shadow_settle(). cycle() is not cut up. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:29:52 +01:00
glenn schrooyenandClaude f7c2d45957 MAINT-21: app/ctl_trade.py - Controller methods for trading
Moves the methods named in the card and the constants only they read out of app/main.py unchanged. TradeMixin: trade sizing, the mode runs, the day plan, the peak floors, drain and charge limits, pack actions. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:29:48 +01:00
glenn schrooyenandClaude 058ecb7caa MAINT-21: app/ctl_writes.py - Controller methods that write, refuse and hand back
Moves the methods named in the card and the constants only they read out of app/main.py unchanged. WritesMixin: write_setpoint, write_refusal, _write_unit, _hand_back, the refusal evidence, heartbeats and the site release/zero commands. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:29:44 +01:00
glenn schrooyenandClaude fb0730fe6f MAINT-21: app/ctl_inputs.py - Controller methods that read the inputs
Moves the methods named in the card and the constants only they read out of app/main.py unchanged. InputsMixin: read_inputs, _read_unit, live_units and the other readers of the meter, packs, PV and forecast. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:29:40 +01:00
glenn schrooyenandClaude 1b6bb05fb4 MAINT-21: app/rows.py - the status-row and Why-line module functions
Moves why_raised, why_key, tariff_plan_row and arbitrage_row out of app/main.py unchanged. main.py imports them, so app.main still exports them. tools/maint21_same_ast.py: OK.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:29:37 +01:00
glenn schrooyenandClaude 0d49027daa MAINT-21: tests read and patch the Controller through tools/main_files.py
Prepares the split of app/main.py's Controller into files by job, with no app
change. tools/main_files.py gives a test the text and the AST of main.py plus
the files split from it, and `live`, which sets a global in every file whose
functions read it (and raises when none does). Tests that read main.py's
source, and tests and replay tools that patch a main global (datetime,
compute, resolve, _mono, WRITE_BUDGET_S, ...), go through it, so they pass on
this layout and on the split one. test_split_patches.py fails when a test or
tool patches an app.main attribute that main.py no longer reads, or that
another file also reads. tools/maint21_same_ast.py proves every function,
method and module-level assignment of main.py at the base is found unchanged
in its new file.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 00:27:07 +01:00
admin 56fc41fffa Merge pull request 'MAINT-20 part 2: comments and docstrings in main.py' (#224) from MAINT-20-2 into release/1.0
infra-pin / fresh (push) Successful in 1s
2026-11-08 22:16:27 +01:00
glenn schrooyenandClaude Opus 5.5 bbbc89b235 MAINT-20 part 2 review: comment-only fixes in main.py and the MAIN notes
checks / unit (pull_request) Successful in 30m13s
infra-pin / fresh (pull_request) Successful in 1s
- check_peak_floor_limited: restore the SAFETY-25 line (the reserve sentence is
  in messages.peak_reserve() on every branch, unreadable SoC included).
- Three status-page comments that no longer said anything (SAFETY-20 row,
  AC 5 delivery row, banner-vs-text) now say their rule in one line.
- tariff_refresh_wanted docstring: no orphan "TARIFF-24)" line.
- MAIN-orchestration.md: blank line before the first heading.
- MAIN-orchestration-archive.md: refilled intro; says how to find a section
  from a main.py pointer.

No code change: maint20_same_code.py 16029d7 -> SAME CODE, -OO same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:25:37 +01:00
glenn schrooyenandClaude f8df7cd860 MAINT-20 part 2 r2: DECISIONS MAIN-orchestration-archive intro
checks / unit (pull_request) Successful in 25m14s
infra-pin / fresh (pull_request) Successful in 1s
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:01 +01:00
glenn schrooyenandClaude f5714248f6 MAINT-20 part 2 r2: app/main.py comments, lines 6001-6185 (amain .. main)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:01 +01:00
glenn schrooyenandClaude 40ef27c367 MAINT-20 part 2 r2: app/main.py comments, lines 5501-6000 (status_payload .. maint_site_tz)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:01 +01:00
glenn schrooyenandClaude b05ad2b273 MAINT-20 part 2 r2: app/main.py comments, lines 5001-5500 (shutdown .. checks)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:01 +01:00
glenn schrooyenandClaude 31d13ee8bb MAINT-20 part 2 r2: app/main.py comments, lines 4501-5000 (check_peak_saturated .. publish)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude 47e99a37bc MAINT-20 part 2 r2: app/main.py comments, lines 4001-4500 (_shadow_settle .. check_output_clamp)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude d298f8aa4f MAINT-20 part 2 r2: app/main.py comments, lines 3501-4000 (module level)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude 391c4b4411 MAINT-20 part 2 r2: app/main.py comments, lines 3001-3500 (shadow .. cycle)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude 6f94944e44 MAINT-20 part 2 r2: app/main.py comments, lines 2501-3000 (_peak_over_drain .. _read_unit)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude 56d5532b83 MAINT-20 part 2 r2: app/main.py comments, lines 2001-2500 (_reseed_drain_end .. _fill_peak_gaps)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude 9ec0a84129 MAINT-20 part 2 r2: app/main.py comments, lines 1501-2000 (pack_floor_soc .. _reseed_charge_end)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude 6492d179d6 MAINT-20 part 2 r2: app/main.py comments, lines 1001-1500 (_refusal_from_stale .. site_circulating_w)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude f114a19dcc MAINT-20 part 2 r2: app/main.py comments, lines 501-1000 (_refusal_probe .. _refusal_update)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude a5fec377ad MAINT-20 part 2 r2: app/main.py comments, lines 1-500 (tariff_refresh_wanted .. __init__)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 18:06:00 +01:00
glenn schrooyenandClaude 8fc5f15b03 MAINT-20 part 2 r2: cut the comments that came in with SMA-2, SMA-10, SAFETY-128 and SAFETY-137
Word for word in MAIN-orchestration-archive.md, keyed by the line at 16029d7.
No code change.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 17:29:27 +01:00
glenn schrooyenandClaude c2b4302dcf Merge release/1.0 (16029d7) into MAINT-20-2
Nine conflicts in app/main.py, all in comments around new code: every code
line is release/1.0's, every comment follows the part 2 rule.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 17:28:03 +01:00
admin 16029d7cb8 Merge pull request 'Release 0.21.0' (#241) from release-0.21.0 into release/1.0
infra-pin / fresh (push) Successful in 2s
checks / unit (pull_request) Successful in 23m41s
infra-pin / fresh (pull_request) Successful in 2s
2026-11-08 10:46:27 +01:00
Claude review 8e26574b03 Release 0.21.0: CHANGELOG wording (SAFETY-136, SAFETY-138 known issues)
checks / unit (pull_request) Successful in 24m11s
infra-pin / fresh (pull_request) Successful in 2s
SAFETY-136: the line said 10 to 15 s late is not caught, then that 15 s late
is caught after about 4 minutes. It now says 10 s is not caught and 15 s only
after about 4 minutes, as the card says.
SAFETY-138: the 30 s timer that zeroes a late write is the ESPHome board's
watchdog (README), not the inverter's own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 10:20:46 +01:00
Claude 0f208a0500 Release 0.21.0: version bump and CHANGELOG
checks / unit (pull_request) Successful in 33m53s
infra-pin / fresh (pull_request) Successful in 2s
Minor bump, no option changes. Folds "Not in a release yet" into a new
0.21.0 section, adds the contents table for the nine merges on release/1.0
since master 0.20.1, updates the known issues, and rewrites the 0.20.1
SAFETY-128 known issue to say it ships in 0.21.0.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 09:08:59 +01:00
admin b3cfcf2df4 Merge pull request 'SAFETY-137: the shutdown 0 W must be the last write every unit hears' (#240) from SAFETY-137 into release/1.0
infra-pin / fresh (push) Successful in 2s
2026-11-08 04:20:04 +01:00
Claude 8953be0362 SAFETY-137: the shutdown and Stop 0 W is the last write every unit hears
checks / unit (pull_request) Successful in 22m59s
infra-pin / fresh (pull_request) Successful in 1s
The 0 W of shutdown and of the Stop button now waits (bounded, 2 s) for a
write already on its way to the same unit, for every driver, GoodWe included.
Once shutdown has begun, cycle, heartbeat and safety-stop writes are dropped
right before the write is created. One shared wait (_await_inflight) serves
the 0 W and SMA-10's _release_last.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 02:39:38 +01:00
admin dbdc37b959 Merge pull request 'SMA-10: two idle states, hold 0 W or hand the inverter back' (#239) from SMA-10 into release/1.0
infra-pin / fresh (push) Successful in 1s
2026-11-07 23:43:14 +01:00
glenn schrooyenandClaude 6cae5a2f8f SMA-10 round 4: pin the Dutch default "de eigen sturing"
checks / unit (pull_request) Successful in 30m41s
infra-pin / fresh (pull_request) Successful in 2s
The NL default for a hand-back driver without words (handback._BACK_NL) was
changed to "de eigen sturing" in round 2 at the PR #239 review's request
(comment 2495: the article as in the generic clause). The brief does not name
it, so DECISIONS now says where it came from and a test checks the exact Dutch
sentence. No app code change.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-07 22:45:08 +01:00