Skip to content

feat(overview): chart spans and cost together in one block - #96

Closed
Fl0p wants to merge 1 commit into
mainfrom
flo-595-overview-activity-block
Closed

feat(overview): chart spans and cost together in one block#96
Fl0p wants to merge 1 commit into
mainfrom
flo-595-overview-activity-block

Conversation

@Fl0p

@Fl0p Fl0p commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Merges the Overview's History and Costs blocks into one Activity & Cost block, both series on one field in different colours.

Activity & Cost

What changed

  • One block instead of two, fed by one /history call instead of two requests. buckets already carried cost_usd beside spans, from the same row of the same spans ∪ daily_usage union — so the two series are bucketed, windowed and user-filtered identically by construction, rather than by a client-side join of /history with /costs that has to keep bucket width, window and user filter in sync at the call site.
  • Spans render as a filled area against a left axis (--color-chart-1, blue); cost as a line against a right axis (--color-chart-4, amber), tick-formatted in dollars.
  • Both series now start and stop together on every range, including Day, where cost is charted hourly for the first time — /costs is daily-only, so the old pair showed 24 hourly points above a single daily one.
  • The block header links to both full pages (History → Costs →); StatSection takes an optional links array, and the single viewAllHref stays the default for every other block.

The two-scale decision

Spans and cost are counts and dollars, three orders of magnitude apart — on one scale the cost line is flat on the axis floor. Two y-scales on one plot is a shape that can invent a correlation the data does not hold, so it is taken deliberately and paid for:

  • the two series wear different marks (area vs. bare line), so the eye does not read a crossing as meaningful;
  • the legend names the axis each series reads against in wordsSpans (left axis), Cost (right axis, USD) — identity is never colour-alone;
  • the right axis is tick-formatted in dollars, the left in bare counts, so the scales self-label;
  • axis and legend text stay in ink tokens, not series colours.

That makes the plot readable; it does not make the scale alignment meaningful. docs/decisions/0015-overview-activity-and-cost-one-block.md records the alternatives (index-to-common-base; two stacked plots sharing an x-axis) and says which one to reach for if the board wants the stronger form — it is a contained change behind the same block.

The colour pair was validated, not eyeballed: CVD separation ΔE 32.3 protan / 29.3 tritan in light and 29.9 / 24.6 in dark, against a target of ≥ 8.

Verified

  • npm run build (tsc + vite) green.
  • VitePress npm run build in docs/ green — no dead links from the new ADR.
  • Rendered in a real browser against a Docker instance seeded with scripts/seed-demo.py (454 sessions / 22 583 spans over 90 days), both colour schemes:
    • tooltip reads 2026-08-11 · Spans: 341 · Cost: $8.85 — one crosshair, both series, each in its own unit, identical text in light and dark;
    • page.on('request') recorded /api/v1/history?granularity=day&range=month then …granularity=hour&range=day on switching to Day, and no /api/v1/costs call at all — confirming the page dropped the second request;
    • the Day range charts both series hourly.
  • README hero re-taken from that seeded instance via scripts/shoot-screenshots.mjs (synthetic data only — no real user names or spend).

Docs

  • docs/decisions/0015-… (new) + index row.
  • README Overview bullet rewritten; hero re-shot.
  • CHANGELOG [Unreleased] → Changed; two neighbouring unreleased entries that named the now-merged blocks corrected so the section describes the state that ships.
  • docs/operations/screenshots.md: playwright-core must be symlinked, not reached via NODE_PATH — the shoot script is an ES module and ESM resolution ignores NODE_PATH. The existing instruction does not work.

🤖 Generated with Claude Code

The Overview stacked a History block and a Costs block, two requests and two
cards for two series that answer the same question at a glance. They are now one
block, Activity & Cost: spans as a filled area against a left axis, cost as a
line against a right axis, fed by a single /history call.

/history buckets already carried cost_usd beside spans, from the same row of the
same spans ∪ daily_usage union, so the two series are bucketed, windowed and
user-filtered identically by construction rather than by a client-side join of
two endpoints that has to keep three things in sync. Both series now start and
stop together on every range, including Day, where cost is charted hourly for
the first time — /costs is daily-only, so the old pair showed 24 hourly points
above a single daily one.

Two y-scales on one plot can invent a correlation the data does not hold. The
series wear different marks and the legend names the axis each reads against in
words, so the plot stays readable; ADR-0015 records what that mitigation buys
and what it does not. The blue/amber pair is the existing chart-1/chart-4
tokens, validated for CVD separation rather than eyeballed.

StatSection takes an optional links array so the block can reach both full
pages; the single viewAllHref stays the default everywhere else.

Co-Authored-By: Daedalus <daedalus@agents.flopbut.local>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fba2f09f-9967-4c9f-ad42-6438ef87eccc


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Fl0p pushed a commit that referenced this pull request Aug 21, 2026
The Overview's History and Costs blocks are now one block, Activity &
Cost, plotting both series on one field: spans as a filled area against
a left axis, cost as a line against a right axis, in the existing
CVD-validated colour tokens. One /history call feeds both series — its
buckets already carry cost_usd beside spans, so the two series are
bucketed, windowed and user-filtered identically by construction, and
the page drops its /costs request. On the Day range cost is charted
hourly for the first time. StatSection takes an optional links array so
the block header can point at both full pages. ADR-0015 records the
two-scale trade-off and the stacked alternative kept in reserve.

Squash of PR #96, implemented by Daedalus, reviewed and approved by
Prospero.

Co-Authored-By: Prospero <prospero@agents.flopbut.local>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Fl0p

Fl0p commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Squash-merged to main locally as ea5d06c (per the agent-identity merge rule; author/committer Prospero). Reviewed and approved: diff matches the handoff block, CI green on head f706178, board's one-field ask satisfied. The stacked-plot alternative (ADR-0015 option 3c) remains behind the open board confirmation on FLO-595.

@Fl0p Fl0p closed this Aug 21, 2026
@Fl0p
Fl0p deleted the flo-595-overview-activity-block branch August 21, 2026 17: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