diff --git a/VISION.md b/VISION.md index f736b473c..d7c4fe66e 100644 --- a/VISION.md +++ b/VISION.md @@ -68,6 +68,11 @@ Installed kWp is an optional starting estimate. Approximate user input must not permanently constrain a model when measurements support a better fit. Panel drawings, orientations and engineering knowledge are not prerequisites. +STRÅNG, roof geometry and panel drawing are outside the selected Core scope. +They may serve a future optional extension if a concrete need warrants it; +the module boundary and delivery are not decided. Normal setup must work +without choosing an irradiance source, azimuth or panel layout. + Initial load and solar models must already support useful first-day planning. On-site learning improves them as evidence arrives. Elapsed days alone do not prove model quality; state uncertainty honestly and handle cold start. diff --git a/docs/roadmap.md b/docs/roadmap.md index a8c0a5b9c..44c2791f7 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -9,6 +9,117 @@ and site evidence before claiming a gap or completion. Preserve established behaviour while simplifying the product. Bug fixes, security, recovery and necessary maintenance continue alongside product work. +## Implementation review, 12 September 2026 + +### Selected scope after the PR review + +The owner selected the delivery order below. Start with the confirmed Core +control and Lua-host gaps, then finish the daily charging flow. Keep necessary +maintenance in small changes alongside that work. + +The STRÅNG, roof-geometry, panel-drawing and related settings stack +([#734](https://github.com/srcfl/ftw/pull/734), +[#735](https://github.com/srcfl/ftw/pull/735), +[#826](https://github.com/srcfl/ftw/pull/826), +[#1052](https://github.com/srcfl/ftw/pull/1052)) leaves the Core queue. +Preserve the work as reference for a possible optional extension. Its form +is undecided; do not add a module framework now. Default setup must work +without irradiance-source selection, azimuth or panel geometry. + +Close the retired Python-optimizer work in +[#963](https://github.com/srcfl/ftw/pull/963) and +[#1036](https://github.com/srcfl/ftw/pull/1036). Core removed that runtime in +[#1083](https://github.com/srcfl/ftw/pull/1083); new solver work belongs in +Energyplan. Retain the useful requirements: report unmet household goals, +compare plans with one physical and economic model, and evaluate whether +cost-neutral peak reduction improves the current planner. These requirements +do not authorize restoring the Python runtime or copying private solver source +into Core. + +[#971](https://github.com/srcfl/ftw/pull/971) already reached Core through the +Energyplan integration; its exact head is in master's history. Close the +remaining PR against its old feature base. Preserve independent benchmarks +and Python development tools where they verify today's product; they are not +the retired optimizer runtime. + +### Reviewed baseline + +This baseline checks Core `f1a3b765`, webapp `ff7af033`, native app +`79fdd0e8`, drivers `7e594655`, and website `d26e14f7`, after the shared +vision changes merged. It combines source review, repository tests and a local +webapp simulator rendered in a browser. It is not an audit of every installed +box, hardware combination or measured saving. + +Much of the required foundation exists. The next work should close gaps in +that foundation and complete daily flows, rather than replace the planner or +add another control service. + +### Close confirmed control gaps first + +Core already has a [site freshness gate](../go/cmd/ftw/site_dispatch_safety.go), +[device-fault exclusion and retries](../go/cmd/ftw/driver_failure_default.go), +and [planner filtering of available batteries](../go/internal/mpc/service.go). +These need to work through every path. Current legacy paths still differ: + +- [LuaDriver.Command](../go/internal/drivers/lua.go) returns success when + `driver_command` is absent. +- [siteLoadW](../go/internal/control/dispatch.go) sums cached battery and PV + watts without excluding offline drivers. In the existing regression cases, + a 500 W house becomes 4,500 W or 5,500 W. +- The same dispatch file substitutes 10% for missing battery SoC. One + regression case produces a -1,200 W battery target without a SoC reading. +- `liveCurtailLimitW` accepts an old or offline meter in isolated tests. + The outer site gate already blocks stale-site dispatch; the inner helper + still needs its own correct freshness contract. + +Nine existing regression cases from +[#1170](https://github.com/srcfl/ftw/pull/1170) and +[#1199](https://github.com/srcfl/ftw/pull/1199) were run against this baseline +through a temporary Go test overlay: seven failed and two passed. No runtime +source was changed. These are gaps in the existing test coverage and code, +not regressions from the documentation merge. + +Continue those PRs before adding wider actuation. Recheck their current diffs +and reviews: missing-SoC protection must survive slew and final clamps; +read-only metadata must agree with actual command enforcement; PV curtailment +needs the default-mode gate too. Verify the bundled driver pin through startup +with any stricter host rule. An earlier approval or a merged driver-source +change does not prove the currently pinned recovery bundle passes. + +### Existing behaviour and remaining product work + +| Area | What the baseline contains | What remains | +|---|---|---| +| Mixed equipment | Separate SolarEdge legacy and Pixii drivers exist. Their [published evidence](https://github.com/srcfl/device-drivers/blob/7e5946555245dee2150d46d1b7278aaec5ebe242/drivers/lua/solaredge_legacy.lua) and [Pixii metadata](https://github.com/srcfl/device-drivers/blob/7e5946555245dee2150d46d1b7278aaec5ebe242/drivers/lua/pixii.lua) still say experimental; the legacy header and declared curtail capability also need to agree. | Reconcile known field runs with the catalog, then verify the named inverter + battery + charger combination. Distinguish measured telemetry, verified commands and unverified control. Metadata is not evidence that no user has ever run the hardware. | +| Setup and usable power | Discovery, fingerprinting and per-device settings exist. [Planner battery limits](../go/cmd/ftw/main.go) use configured limits or a 0.5C estimate, then an aggregate fuse cap. | A guided commissioning result and measured usable-power learning are still missing from the reviewed setup path. Read verified limits first; learn response within them. A capacity-derived estimate is not a learned power limit. | +| Forecasts and defaults | [PV learning](../optimizer/native/README.md) needs no panel geometry or rating. [Cold-load selection](../go/cmd/ftw/forecast_tracking.go) keeps the site prior until learning, and [load/net-risk tests](../go/cmd/ftw/forecast_load_risk_test.go) cover uncertainty. Charge and discharge efficiency are included. The [minimum arbitrage spread](../go/internal/config/config.go) defaults to zero. | Verify first-day and learned performance on held-out site periods. Keep the separate opt-in wear-cost requirement open; a minimum arbitrage spread is not a general wear model. Align all persisted defaults and worker support before exposing such a setting. Do not rebuild cold-start support already delivered in #1204. | +| Daily charging | [The webapp panel](https://github.com/srcfl/ftw-webapp/blob/ff7af033fa3fcdeb38882e3ff365e8d6d7aba75a/src/views/EvPanel.svelte) already saves SoC on slider release, changes schedules without a Save button and supports Charge now. | [Now](https://github.com/srcfl/ftw-webapp/blob/ff7af033fa3fcdeb38882e3ff365e8d6d7aba75a/src/views/Now.svelte) normally opens that panel after a charger tap or notification link. Bring the relevant SoC action directly into the post-plug-in entry experience. Complete the goal → plan → delivered-energy flow on real chargers, including offline cars and restarts. | +| Notifications | Core and the webapp implement subscription, charging connection/completion/interruption events and device alerts. See the [shared push catalogue](../contract/push-catalogue.yaml) and [rule defaults](../go/internal/notifications/service.go). | There is no dedicated predicted-missed-departure event in that catalogue. Add an actionable goal-risk notification and make activation clear during charging setup, with user consent. Verify delivery while the app is closed; an interrupted-session alert alone does not cover a future shortfall. | +| Live trust and expert access | Flow exists. [LivePanel](https://github.com/srcfl/ftw-webapp/blob/ff7af033fa3fcdeb38882e3ff365e8d6d7aba75a/src/views/LivePanel.svelte) already puts a recent one-second trace behind each energy bubble and freezes it on silence. Core stores [structured v2 command results](../go/internal/state/driver_command_results.go), plan diagnostics and issued forecasts. | Join request, accepted intent, command response and measured effect in the normal experience and a structured analysis API, including legacy drivers and different sample cadences. Current result records and live watts are useful parts, not a complete proof of causality. Measure response time on a target box. | +| External control and agents | [Protocol command IDs and authorization leases](../go/internal/appproto/command.go), scoped operations, [bounded battery holds](../go/internal/api/api_battery_manual.go), schedule APIs and encrypted sessions exist. [HASS callbacks](../go/cmd/ftw/main.go) persist modes and grid targets. The built-in [Ask why tools](../go/internal/api/api_assistant_tools.go) are read-only. | Define renewable external control separately from durable goals. Losing HASS does not currently expire its saved mode. Existing authorization leases do not supply that policy. Build structured agent reads first, then permitted schedule/plan writes and a cloud MCP endpoint using the same Core checks. | +| Savings | [The API](../go/internal/api/api_savings.go) explicitly reports `site_total` against `no_pv_no_battery_vehicle_energy_at_daily_average`. Actual import cost and export revenue are available. | Make the scope clear on each surface that says “saved”. Then add and validate the same-hardware self-consumption counterfactual, including EV behaviour and stored-energy accounting. Do not relabel the current figure as FTW's incremental benefit. | +| Heat and settings | Thermal contracts and an [explicitly opted-in solar feed](../go/cmd/ftw/solar_feed_send.go) already exist. The on-box [planner settings](../web/settings/tabs/planner.js) and webapp use different levels of technical language; the on-box minimum SoC still says “House reserve”. | Keep existing opt-ins explicit while phase one uses heat data for planning. Align basic controls around user goals and distinguish operating limits from forecast caution. Audit stored settings before removing or hiding them. Active tank/hot-water optimization remains a later bounded outcome. | + +### Selected delivery order + +These are the selected priorities, with no dates promised to users. Complete +one bounded outcome at a time. Each delivery should have a focused PR and a +clear result that the owner can review. + +| Order | Delivery | Done when | +|---|---|---| +| 1 | Close the confirmed legacy control and host gaps in #1170 and #1199. | The failing baseline cases pass through the final command path; remaining review findings are resolved; the pinned driver set starts and reaches its safe defaults. | +| 2 | Complete everyday charging. | Plug in → open app → correct SoC → see accepted plan takes no extra navigation or Save. Recurring weekday goals, Charge now, restart recovery and goal-risk notifications work together on a named charger and offline-car setup. | +| 3 | Complete first-day commissioning and simple defaults. | A new mixed site reaches safe automatic operation with confirmed fuse/meter, minimal required input and a receipt for observed control. Wrong starting ratings and failed integrations have clear handling; learned power does not replace hard equipment limits. | +| 4 | Share live evidence with people and agents. | One structured path explains intent, command result, freshness and measured outcome. Both normal Flow and an authorized analysis agent can use it. Target-box latency and differing sampling rates are measured; forecast evaluation covers cold start and learned periods. | +| 5 | Complete external authority and fair value as separate focused changes. | Temporary control expires to a defined local default; durable goals persist; schedule/plan access can be revoked; cloud MCP does not expose data to the relay. Separately, the validated self-consumption comparison reports FTW's incremental value and missing evidence honestly. | +| Later | Bounded thermal control and further expert extensions. | A named tank/hot-water use case meets comfort, hardware and failure requirements without making ordinary household setup harder. Native expansion still follows its existing Pair + Now verification gates. | + +Necessary safety, security, recovery and support fixes continue throughout. +Correct misleading value labels when their scope is known; that need not wait +for the new counterfactual model. Reading and analysis access for agents can +also support the evidence work before agents receive control authority. + ## Current focus: a complete and trustworthy default experience Make discovery, planning, control and feedback fit together for mixed hardware