Skip to content

feat(api): one-file help report for "why is it doing that?" - #740

Merged
frahlg merged 2 commits into
masterfrom
feat/support-help-report
Jul 31, 2026
Merged

feat(api): one-file help report for "why is it doing that?"#740
frahlg merged 2 commits into
masterfrom
feat/support-help-report

Conversation

@frahlg

@frahlg frahlg commented Jul 31, 2026

Copy link
Copy Markdown
Member

Why

Answering a user's "why is it discharging when the plan says charge?" costs a screenshot round-trip per question. A recent support thread needed nine of them, over six hours, to establish one fact: the load forecast said 383 W while the house was drawing 7.9 kW. Everything downstream — the plan, the setpoint, the export — followed correctly from that wrong number.

That fact should have been in the first file the user sent.

What

GET /api/support/report returns one Markdown file describing what FTW is doing and why. It is reachable from a "Something looks wrong?" button under the plan chart, and from every driver's Diagnose modal.

The file opens with Findings — the checks a person would run first:

  • the plan is stale
  • the fallback solver produced this plan
  • a device is offline or reporting a fault
  • safety limits are clamping a target
  • a log message is repeating every control cycle
  • the load model is still learning
  • forecast against reality, for both load and solar

On the thread above, the first finding would have read:

PROBLEM — The load forecast is far from reality. The model predicts 383 W for right now; the house is drawing 7.90 kW. The planner sized this slot against the forecast, so its charge and discharge decisions are built on the wrong house.

Under Findings come the live site state, the plan slot covering this moment — stated before anything about the next one, since confusing those two is what sent the thread sideways — the surrounding slots with the solver's reasoning, forecast accuracy, driver health, component versions, and the recent warning and error log.

Design notes

One file, not a bundle. People paste it into a chat and ask for help there. A tarball of twelve JSON files does not survive that journey, and neither does a model reading it.

Small enough to read in full. The plan window is trimmed to ±3 h; the log tail collapses repeats and caps at 40 distinct messages. A live report from the dev stack is 3.8 kB.

No secrets. Config is not included.

/api/support/dump is unchanged and remains the deep bundle for cases this report cannot close.

What the first live run caught

The initial version was generated against a running stack and came back with 49 of its 120 log lines carrying one warning, repeated every control tick. A single unique ERROR would have been pushed clean out of the window. Second commit fixes that and two related problems it exposed:

  • log entries group on (level, driver, message) with a count, so a chatty loop cannot crowd out a one-off failure
  • a message repeating 10+ times becomes a finding in its own right, reported by count rather than by matching text so it does not rot when a log line is reworded
  • the dispatch table says what its clamp column covers — per-device limits only. The site-meter clamp caps the fleet total upstream and cannot appear there, so "no" on every row was reading as "nothing was limited" while the log showed the total clamped from 9.0 to 6.4 kW

Verification

  • Live against the dev stack, twice. Button click → GET /api/support/report → 200, file downloads, no console errors. After the fixes the log section went from 49 lines to 3 grouped entries and the clamp leads Findings.
  • 12 Go tests, 4 web tests, make verify clean.
  • The report renders correctly with every optional service nil — the state a confused user is most likely to be in.

Related

The 383 W number is a real bug in the load model, filed as #739. This PR only makes it visible.

🤖 Generated with Claude Code

@frahlg
frahlg requested a review from erikarenhill as a code owner July 31, 2026 11:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 74793be91c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


// The load-forecast check. This is the one that would have closed the
// 383 W thread in a single message.
if forecastMiss(snap.PredictedLd, snap.LoadW) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate forecast checks on available live inputs

When the site meter is stale, liveNow leaves LoadW at zero, and when the optional load model is absent it likewise leaves PredictedLd at zero; this unconditional comparison then treats either sentinel as a real measurement. Reports generated during a meter outage can therefore add a false “house is drawing 0 W” forecast problem, while installations without a load model can claim that a nonexistent model predicts 0 W and recommend resetting it. Only run each comparison when both the live meter and load model are available; the active-slot comparison also needs HaveGrid.

AGENTS.md reference: AGENTS.md:L35-L35

Useful? React with 👍 / 👎.

Comment on lines +127 to +128
socSum += *r.SoC
socWeight++

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Weight fleet SoC by battery capacity

For sites with multiple batteries of unequal capacity, this arithmetic averages each device equally rather than averaging stored energy. For example, a full 1 kWh battery plus an empty 10 kWh battery is reported as 50% instead of about 9%, which also suppresses the report's near-empty finding. The existing status aggregation uses TelemetryCapacities specifically for capacity-weighted SoC, so the report should use the same weighting.

Useful? React with 👍 / 👎.

@frahlg
frahlg force-pushed the feat/support-help-report branch from 74793be to 0df45a8 Compare July 31, 2026 12:46
frahlg and others added 2 commits July 31, 2026 14:47
GET /api/support/report returns a single Markdown file describing what FTW
is doing and why, reachable from a "Something looks wrong?" button under
the plan chart and from any driver's Diagnose modal.

It exists because answering a user's "why is it discharging when the plan
says charge?" currently costs a screenshot round-trip per question. One
thread needed nine of them to establish that the load forecast said 383 W
while the house was drawing 7.9 kW — a fact the first file should have
stated outright.

The report opens with Findings: checks in the order a person would run
them — stale plan, fallback solver, offline or faulted devices, active
safety limits, an untrained load model, and forecast against reality for
both load and solar. Then the live state, the plan slot covering *this
moment* stated before anything about the next one, the surrounding slots
with the solver's reasoning, forecast accuracy, driver health, versions,
and the recent warning and error log.

One file, not a bundle: people paste it into a chat and ask for help
there. The plan window is trimmed to a few hours either side of now and
logs to warnings and errors, which keeps a live report near 3 kB.

/api/support/dump is unchanged and stays the deep bundle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first report generated against a live stack came back with 49 of its
120 log lines carrying one warning, repeated every control tick. A single
unique ERROR would have been pushed clean out of the window by that noise,
and Findings said nothing about the repetition at all.

Three fixes, all from that one report:

- Group warnings and errors on (level, driver, message), ignoring the
  per-tick attribute tail, and show a count. The cap is now 40 distinct
  messages rather than 120 lines, so a chatty loop cannot crowd out a
  one-off failure.
- A message repeating 10+ times becomes a finding in its own right,
  reported generically by count so it does not rot when someone rewords a
  log line. ERROR-level repetition is a problem, WARN a warning.
- Say what the dispatch table's clamp column covers. It reports per-device
  limits only; the site-meter clamp caps the fleet total upstream and
  cannot appear there, so "no" on every row was reading as "nothing was
  limited" while the log showed the total clamped from 9.0 to 6.4 kW.

Verified against the dev stack: the log section went from 49 lines to 3
grouped entries, and the clamp now leads Findings instead of being
something to scroll past.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@frahlg
frahlg force-pushed the feat/support-help-report branch from 0df45a8 to aa50bff Compare July 31, 2026 12:48
@frahlg

frahlg commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

Merging without the /web/ owner's review, on Fredrik's explicit call — flagging it here rather than letting it pass silently.

@erikarenhill the web-side change is small and additive: a Something looks wrong? Download a help report button under the plan chart (index.html), its click handler in plan.js, a .plan-help-request block in app.css, and one extra button in the driver Diagnose modal. Nothing existing was restyled or moved. Happy to change the placement, the wording or the styling in a follow-up if any of it sits wrong with you.

Also worth knowing: an earlier push of this branch carried a stray commit from #727 (docs: make the driver page a host reference) because I branched from the wrong ref. It has been rebased out — #740 is now its own two commits, and #727 is untouched and still open on its own.

@frahlg
frahlg merged commit 4212dbb into master Jul 31, 2026
13 checks passed
@frahlg
frahlg deleted the feat/support-help-report branch July 31, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant