Skip to content

fix(dashboard): after a ≥36h outage the history plot discards ALL pre-gap history — the #839 recent-run clip needs a floor #1709

Description

@OrangePeachPink

Live repro on the operator's deployment, 2026-08-20. The host was down 08-14→08-20 (see the sibling outage issue). On return to service, the Moisture-history chart rendered visually empty at every range — 30d, 7d, 24h, even 1h — while the masthead counted 341,476 readings in-window and the live cards streamed normally.

Verified cause

card_context.py:1000 — the #839 Fix B "recent contiguous run" clip:

  • recent_start = _recent_run_start(soil, TRAJ_GAP_BOUNDARY_H) with TRAJ_GAP_BOUNDARY_H = 36.0 (card_context.py:113,904)
  • plot_rs = [r for r in rs if r.timestamp_utc >= recent_start]

After any ≥36h gap, the PLOT keeps only readings since the gap ended. Measured from the live endpoint: all 8 datasets contained 64–66 points, every one at x = 719.45–719.99 of a 720-hour window — the ~32 minutes since the Monitor restarted. At 30d scale that is sub-pixel at the right edge. The chart drew everything it was given; it was given 0.08% of the window.

#839's intent was right for its regime: a stale pre-gap pocket must not dominate a live view (the original bug was 0..180h of stale data bridging into the live window). Today's regime is the inversion — 24 days of good history behind the gap, 32 minutes in front of it — and the rule discards the month. The operator moment is exactly backwards: returning after an absence-shaped outage is precisely when the pre-gap history matters most, and it is precisely when this rule hides it.

This is the release family's recurring defect shape: a layer correct about the question it asks (don't bridge a hole), silent about the one nobody wired (don't discard the archive behind it).

Why the clip may no longer be needed at all

The gap-bridging harm #839 feared is already independently solved: _insert_breaks (#699, card_context.py:1376) breaks the plotted line across real dropouts post-decimation, "so the chart never interpolates a straight segment over a WiFi hole." And the fits stopped spanning gaps long ago — the trend is segment-bound (#1133) and mask-filtered (#1244 C0). The clip's remaining job description may be empty.

Candidate fix (Data's call, Design consult on the render)

Plot the full window with the #699 break across the gap (an honest visible hole, per the gaps/continuity machinery that already exists) — keep fits/trends/forecasts exactly as they are (already recent-run/segment-bound). If any clip survives, it needs a floor: never discard more than it keeps, or never clip when the pre-gap span exceeds the post-gap span.

AC:

— Workflow ⚙️ (filed from live diagnosis)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:analyticsRETIRED 2026-07-21 (ADR-0003 §5) — vestigial; kept for closed-issue historyfor:dataFirst-approximate routing — Data lane (host logger, analytics, dashboard)for:designFirst-approximate routing — Design lane (design system, brand, voice)type:fixA bug fix — restoring expected behavior.

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions