Skip to content

Usage hover: window + spend graphs; one fleet spend number; devbox fix - #349

Merged
henrypinkard merged 2 commits into
romp-on:mainfrom
henrypinkard:usagegraphs
Aug 14, 2026
Merged

Usage hover: window + spend graphs; one fleet spend number; devbox fix#349
henrypinkard merged 2 commits into
romp-on:mainfrom
henrypinkard:usagegraphs

Conversation

@henrypinkard

Copy link
Copy Markdown
Collaborator

The hover gains time-series graphs — utilization sparklines under each window's bars (0-100 pinned, null-gapped) from a new 8-day usage-history.json ledger appended by both existing usage writers, and a 7-day $/hour area graph with peak in a new ONE-fleet-level API-spend section that sums every host (one shared key, one number, "· N machines"). The devbox's missing spend was a missing-usage.json bail before the no-login arm — fixed with a fall-through — plus the answered-empty staleness clear on the remote poll. Version-skew safe: hosts without series still join sums; the graphs add contributors only. Tests: tests/test_usage_series.py (8) + updated pins; suites green (Python 4478, node 1883).

🤖 Generated with Claude Code

Three asks in one build (the user 2026-08-13):

Graphs. usage-history.json is the window bars' recorded past — both
usage writers append hourly max-pct per window under their lock
(roll-aware: a new resets_at takes the fresh reading), bounded to 8
days. The payload ships it as dense null-gapped series (winSeries)
beside a $/hour series from spend.json's own hour buckets
(spendSeries, keyed split beside bars, total on a no-login host). The
hover draws a sparkline under each window's bars — y pinned 0-100 so
every window shares one honest scale, gaps where no reading exists —
via one new inline-SVG helper (the panel is pointer-events:none, so
the graph speaks alone).

One number. The per-host API-spend hover rows are replaced by ONE
fleet-level section: every host's windows summed ("API spend · N
machines") — one shared key is one number, and each host records only
its own turns, so the sum IS the number — plus a 7-day area graph of
the summed $/hour (hosts' series aligned on their base hour) with its
peak. Old-kernel hosts still join the sums; the graph adds only
contributors.

The devbox. A pure API-key host NEVER writes usage.json (both snapshot
writers skip keyed sessions), and _usage() bailed on the missing file
two lines before the no-login spend arm written for exactly that
machine — it answered {} and its spend vanished from the fleet sum. An
empty snapshot falls through now. And a host that ANSWERS /usage with
nothing clears its row instead of freezing its last reading (only an
unanswered poll keeps the last good one).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@henrypinkard
henrypinkard enabled auto-merge August 13, 2026 22:59
CI ran the suite across 23:00 UTC and all five test_usage_series failures
were the same race: the module pinned "the current hour" at import while
the code stamped hour buckets at call time, so one straddled boundary
shifted every index. Local runs never crossed an hour, which is why the
suite was green at push time.

Fix per the evidence-time rule (never wall-clock `now`):
- _spend_series / _usage_history_series take now= to anchor h0
- SdkBackend._record_usage_history takes now= to stamp the hour bucket
- the tests freeze a synthetic instant (FIXED) and derive every key and
  index from it; the one path still on the real clock (_usage) is
  asserted via the payload's own h0, never an assumed position
- the foreign-account skip is now actually asserted, with the login
  pinned (CI has no login, which made the skip inert and untested)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@henrypinkard
henrypinkard merged commit 58ca882 into romp-on:main Aug 14, 2026
6 checks passed
@henrypinkard
henrypinkard deleted the usagegraphs branch August 14, 2026 00:19
henrypinkard added a commit that referenced this pull request Aug 14, 2026
…ine script

PR #349's spendDet edit ate the function's closing brace, so the whole
_LANDING_USAGE_JS blob died on one SyntaxError — the bottom bar rendered
nothing at all, with nothing to click (the user 2026-08-13, right after
the deploy). The kernel's payload was healthy the entire time; the script
that draws it never ran. Both suites and CI were green around it because
nothing anywhere read the inline blobs as JavaScript.

- restore spendDet's closing brace
- tests/test_inline_js_parses.py: load the kernel module (hermetic state)
  and node --check every _*_JS attribute — the runtime value, exactly as
  browsers receive it, all 17 blobs — so a non-parsing inline script can
  never ship green again; skips only where node is absent

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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