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
5 changes: 5 additions & 0 deletions VISION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
111 changes: 111 additions & 0 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down