Repository navigation
feat(dash): one redesigned dashboard: Overview rewrite, plain-words tabs, Benchmarks tab removed - #564
Conversation
OsherElhadad
left a comment
There was a problem hiding this comment.
Review: REQUEST CHANGES at 1a719cd (draft). (Posted as a comment: GitHub does not let the author account request changes.)
Blocker: the Overview no longer shows our cache-reorder saving, and the test that guarded it was deleted.
/api/statsdefinestotal_saved_usdas four disjoint addends of ours (dash/overview.go):net_saved_usd,cachesplit_saved_usd,keepalive_net_usdanddecl_filter_usd. On main the Overview showed the total and a prefix-reorder tile (cachesplit_saved_usd + historical).- The new "What context-guru saved" ledger has three rows (keep-alive net, compaction
net_saved_usd, filterdecl_filter_usd). It drops the cachesplit saving and shows no total. The removed api_test assertion said exactly this: "the overview does not render cachesplit_saved_usd, the one cache saving we claim". - Nothing double counts:
net_saved_usd= baseline − cost − cg_llm and excludes keep-alive, so the three rows are disjoint and the "% of spend" bars share one denominator. - But the section understates what we saved. Either add a fourth "Cache reorder" row (
cachesplit_saved_usdplus the historical credit, as before) and restore the guard test, or record the omission as an owner decision and say so on the page.
Correct as checked:
- Keep-alive token estimate.
keepalive_saved_usd / (1.15 × input), with input recovered fromcache_saved_usd / (0.9 × cache_read), has consistent units for 5-minute writes, and it is labelled "about" / "≈". It overstates tokens when the pings avoided 1h rewrites (2× input, gap 1.9×), and the input price is blended over the provider-cache mix rather than the keep-alive mix. A one-line caveat in the tooltip would cover both. - CSP.
- No
style=or inline handlers in index.html, and widths are set through the CSSOM. - The font is same-origin (
default-src 'self'coversfont-src) and served raw as woff2. assetversion_testcovers the font reference from style.css, and the OFL licence is included.
- No
- Benchmarks removal. The DDL is simply no longer created, so existing
bench_*tables are left untouched and old databases open fine. The flag is kept as an ignored no-op, and TestBenchmarksRouteIsGone pins the route's removal. - Accessibility. The diagnostics use native
<details>/<summary>, so they are keyboard and screen-reader friendly. Headings go h1 → h2 → h3 in order. - Tests.
go vetis clean, and the fullgo test -p 1 ./dashpasses (69 s, idle host).navhash.test.mjspasses 10/10, and the new browser smoke test TestUISmokeEveryTab passes with playwright-core and Chromium.- The deleted tests are for removed features (bench ingest, bottom line, v2), apart from the cachesplit guard above.
- Publication. Screenshots use synthetic data (
*@example.test, hashed ids, 2026 demo dates), and the PR text and docs have no internal paths or hosts. All 5 commits are signed off with no AI lines.
Non-blocking:
- charts.js is not lazy. It loads with
<script defer>on every page; only the drawing waits until the diagnostics are opened. Either load it on the firsttoggle, or reword the claim. - Likely cause of the +3.9 s Keep-alive median. The Overview now fetches
api('keepalive')(loadOverviewKeepAlive), and the Keep-alive tab fetches the same heavy route again (loadKeepAlive) without reusingstate.keepAliveLedger. Landing on Overview and then opening Keep-alive therefore queues a second ledger read behind the first. Reuse the in-flight promise or the cached ledger inloadKeepAlive, or defer the Overview's read until idle. - Leftovers:
dash/keepalivestrategy.go:91still mentions/api/benchmarks, and the docs/design.md:335 diagram still listsbench_runs/tasks. The ignored--dashboard-bench-dirscould log one deprecation line when set. - Clickable
<tr class="click">rows are mouse-only (no tabindex or Enter handler). This predates the PR, but they are worth a follow-up now that Sessions gained a sort control.
OsherElhadad
left a comment
There was a problem hiding this comment.
Re-review: REQUEST CHANGES at c7d9425. The cache-reorder fold matches the agreed design, but there are three blockers. (Posted as a comment: GitHub does not let the author account request changes. This is a draft.)
Blockers
- Four backend tests were deleted by accident. This commit overwrites
dash/savings_test.gowith the new node wrapper, which removesTestSavingsTotalsAgreesWithOverview,TestSavingsTotalsScopesBySession,TestSavingsTotalsSessionInSumsAcrossSessionsInOneQueryandTestSavingsTotalsEmptyIsZeroNotError. They guardDB.SavingsTotals(still indash/savings.go, used by /stats) against Overview's figures, and nothing replaces them. Restore the file from main and putTestSavingsPartsAddUpin a new file (for examplesavings_ui_test.go). keepAliveLedger()is shared across scopes. The promise is reused for 15 s whatever the filter is, butapi('keepalive')takes its query fromstate.filterand the time range (qs()). Changing the tenant, session or range and then opening Keep-alive within 15 s shows the previous scope's ledger. Key the shared promise byqs(), or clear it when the filter changes.- CI
buildis red.mkdocs build --strictaborts becausehow-to/dashboard-guide.mdlinks../img/dashboard/config-light.pngandsettings-light.png, which don't exist (the screenshots haven't been regenerated yet).
Checked and correct
- Totals add up.
savedParts()has cache =keepalive_net_usd+cachesplit_saved_usd+cachesplit_historical.usd, compaction =net_saved_usd, filter =decl_filter_usd. That is exactly the server'stotal_saved_usd:savingsArithmetic's net + cachesplit + kaNet, plus the historical credit in api.go, plusFilterUSDin SetDeclCredit, so nothing is counted twice. The "of which" sub-line is a subset of the cache row and is labelled. The "All three together" line is held back until the full read, which carries the filter. - Tests.
node --test savings.test.mjs(2/2) andnavhash.test.mjs(10/10) pass. The browser smoke test (TestUISmokeEveryTab) passes. The fullgo test -p 1 ./dashpasses, andgo vetis clean. - Plots and asset versioning.
charts.jsis now really lazy (loadScriptOncewhen the fold opens), and the asset-versioning test lists it.savings.jsis a quotedsrc, so it is versioned. No inline styles or handlers. - Keep-alive. The tooltip states the 5-minute-write caveat, and the tab now starts the recommendation together with the ledger.
Non-blocking
savings.test.mjstests the arithmetic function only. Dropping the "of which" sub-line or the total line from the renderer fails no test, so have the smoke test assertsaved-totaland the sub-line.docs/design.md:335still listsbench_runs/tasks.--dashboard-bench-dirsis ignored with a help-text note but logs no warning when set; the message said it would.
Overview now shows the three savings (keep-alive, compaction, tools and skills filter) in dollars and tokens against spend, tool and skill removal advice with the plugin commands, a map of the other tabs, and one collapsed Detailed diagnostics area at the bottom. Every tab gets a heading and a one-line intro from one table (TAB_INFO), plain section labels and a sentence under each chart or table; jargon is replaced or defined with term(). Flat sections, a bundled serif for titles and figures, a sliding nav underline, reduced-motion safe. The Benchmarks tab, its route, its ingest code and the table DDL are removed; --dashboard-bench-dirs stays as an ignored flag so an existing unit file still starts. Adds a browser smoke test that loads every tab and checks the removed sections stay removed. Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
… on Inventory, compact Usage and Sessions, phone layout) and regenerated docs Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
…e-page home retired New diagnostics plots (charts.js): net saving line, money saved and added as two-sided bars, tokens removed, cache share, latency on separate scales, requests. Old five-page links (#home, #cache) land on Overview and Keep-alive; /dashboard/home.html redirects. The sessions list can be ordered by cost. The unused bottom-line banner code and its tests are removed. Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
… Overview Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
…uests, Sessions on a phone, Usage axis, Strategies form; Overview paints from the lean read and loads plots on demand; keep-alive drawn as an upper bound Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
…as waiting behind the ledger) Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
…um to total_saved_usd; shared keep-alive ledger; plots code loads when the fold opens; Keep-alive staggers its reads; stale benchmark mentions Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
…ctive names shown Compaction becomes 'your preset' and keep-alive becomes 'cache strategy' in every heading, label, tooltip and tab name (Cache strategy, Preset steps, Cache strategies, Strategy campaigns); the old ids and anchors still work. The Overview rows show the preset the requests ran under and, for one account, the cache strategy in force. Internal terms stay in Technical details folds. Also: the single-flight group is keyed by cache and entry, because /api/stats and /api/tools collapsed onto one computation when requested together. Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
c7d9425 to
325082c
Compare
…names; screenshots regenerated on the neutral demo Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
|
Replying to the comment that asked for user terms ("they know about preset, for instance conservative, and cache strategy, not compaction and keep-alive"). Done in this PR (head
Unchanged on purpose: MCP tools and skills, Inventory, Usage, Sessions, Requests, KV-cache. The old names appear only inside collapsed "Technical details" folds, with "(also called compaction)" / "(also called keep-alive)" so people can match them to logs. View ids and hash links ( Found while testing this: a bug in the dashboard's shared cache layer (fix in #565): |
Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
|
Full serial |
OsherElhadad
left a comment
There was a problem hiding this comment.
Re-review: REQUEST CHANGES at 708c8ec. Two of the three blockers from c7d9425 are still open.
Blocking:
- The four
DB.SavingsTotalstests are still deleted. On main,dash/savings_test.goholds TestSavingsTotalsAgreesWithOverview, TestSavingsTotalsScopesBySession, TestSavingsTotalsSessionInSumsAcrossSessionsInOneQuery and TestSavingsTotalsEmptyIsZeroNotError. At 708c8ec that file holds only TestSavingsPartsAddUp (127 lines changed, 120 removed), and the four tests exist nowhere in the tree. They guard the backend totals/statsserves. Restore the file from main and move TestSavingsPartsAddUp to its own file, for examplesavings_ui_test.go. keepAliveLedger()still ignores the scope. It reusesstate.kaLedgerPfor 15 s whatever the current filter, butapi('keepalive')builds its query from the current tenant, session and range. Nothing resetskaLedgerPon a filter change. So changing tenant or range, then opening Keep-alive (or the Overview re-rendering) within 15 s, shows the previous scope's ledger. Key the shared promise byqs(), or clear it wherever the filter changes.
Fixed:
- CI
build(mkdocs --strict) is green. CI is green overall. - The cache row includes the cache-reorder credit, and the rows sum to
total_saved_usd(TestSavingsPartsAddUp). - The singleflight key now includes the cache (
%pof the jsonCache). That is a real bug fix: /api/stats and /api/tools collapsed onto one computation. There is no test for it in this PR. #565 changes the samejsonInflight.Doline, so the second to merge will conflict ondash/api.go. Keep one copy, plus #565's test. - JSON field names are unchanged apart from the removed benchmark types. The rename is UI text only.
Non-blocking, still open: dash/ui_smoke.mjs doesn't check that the "of which cache reorder" line or the "All three together" total renders.
…red ledger by query, the Together line shows estimate and upper bound apart, settings text in preset words, plain step fallback Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
|
Pushed fe579f2 for the three blockers and the small notes: (1) dash/savings_test.go is restored byte for byte from main (the four SavingsTotals tests are back; the arithmetic wrapper is in dash/savingsparts_test.go); (2) the shared keep-alive ledger is keyed by the whole query (test added); (3) docs: |
Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
|
Design review, round 5: PASS at b2e7038. Both round-4 blockers are closed. The Overview now reads "Together: $53.26 estimated saved, up to $157.68 more from your cache strategy (an upper bound), of $1,574 spent", with the estimate and the upper bound in separate colours and no blended sum. The Settings subtitle now says "preset settings"; no old term remains outside a definition or a Technical fold. All tabs have been judged on desktop light, with dark and phone checked for duplicates and error states. Remaining POLISH before ready-for-review, none blocking:
|
…ut a description go in a fold Signed-off-by: Osher-Elhadad <Osher.Elhadad@ibm.com>
OsherElhadad
left a comment
There was a problem hiding this comment.
Re-review: APPROVE at 875d960. (Posted as a comment: GitHub does not let the author account approve.) Both remaining blockers are fixed.
- SavingsTotals tests restored.
dash/savings_test.gois byte-identical to main (empty diff), so the four SavingsTotals backend tests are back. The savings-sum test lives in its own files (savings.test.mjs, savingsparts_test.go). - Ledger keyed by scope.
keepAliveLedger()is keyed by the whole query (qs({}): tenant, window, filters), so a scope change within 15 s starts a fresh request instead of reusing the old scope's ledger. A failure clears the shared promise. The test is a source-pinning check in savingsparts_test.go, which is weaker than a behavioural test but adequate for a three-line guard. - Earlier fixes still hold: the three rows sum to
total_saved_usdwith the cache-reorder sub-line, CIbuild(mkdocs --strict) is green, andcharts.jsloads only when the fold opens. go vetis clean. The dash SavingsTotals/SavingsParts/UI/Asset/Nav tests pass, and nodenavhash.test.mjs(10/10) andsavings.test.mjs(2/2) pass. CI is green and the commits are signed off.
Non-blocking, carried over: the smoke test doesn't assert that the "of which" and "All three together" lines render. The single-flight key fix now lives in #574 — make sure this PR rebases cleanly onto it.
This approval covers 875d960.
|
Pushed 70750e7 with the polish round: KV-cache tab is 'Cache detail' (same anchor #/kvcache); Preset steps lists only steps the running build registers (from /api/options; a name in the history that the build no longer has is not shown, falls back to the described list if options are unavailable); plain step names (and one-clause jobs) for every step in Settings, the 'N of M keys set, read-only' lines shortened; date, time and file inputs styled like the other controls; account labels shortened (6 characters, full id in the tooltip) on the Cache strategy table too; the Cache strategy intro cut and its column header 'Avoided (at most)' no longer clips; Sessions and Requests share one date format. Full serial go test -p 1 -parallel 1 ./dash with the browser smoke test: ok (98 s). mkdocs --strict passes. Screenshots for the changed tabs regenerated on the neutral demo and OCR-scanned. |
70750e7 to
875d960
Compare
|
Frozen for release at 875d960 (approved, CI green): marked ready for review, no further pushes. My comment above mentioning 70750e7 describes the polish round, which is now a separate branch (feat/dashboard-ux-polish) and will be a small follow-up PR after this merges: Cache strategy paragraphs and clipped header, date/file input styling, the short account labels, one date format, Usage axis label, plain step names in Settings, and only-current steps in Preset steps. |
OsherElhadad
left a comment
There was a problem hiding this comment.
Re-review: APPROVE at 70750e7. Since 875d960, which I approved, there is one polish commit: steps limited to those the build registers (/api/options), plain step names in Settings, styled date and file inputs (CSS only; the added UI has no style= attributes, inline handlers or innerHTML), shorter labels, and refreshed screenshots. dash/savings_test.go is still identical to main. The single-flight change here is the same line as #574's, so after #574 merges it drops out or conflicts trivially. CI is green (build-test 9m36s, build/mkdocs, purego, trivy, DCO), and the commit is signed off. OK to leave draft from my side; merge order #574 → #565 → #564. This approval covers 70750e7.


Draft. Still open: design review round 4, the final load-time table, the full
./dashsuite and the code review. The screenshots below are from the previous build (synthetic demo data, no real figures, paths or upstream names; two images that showed a path and internal upstream names were removed from the branch history); a regenerated set follows.What this does
One dashboard, redesigned, at
/dashboard/./context-guru:remove-mcp-and-skillsand/context-guru:insights tools, link to Inventory), "About the other tabs" grouped like the nav, and one collapsed Detailed diagnostics with redesigned plots (net saving line, money saved and added, tokens removed, cache share, latency on two scales, requests) that load only when opened. Removed from Overview: prefix-change exposure, addressable spend, "Removed by you, not by us", "Our own LLM cost", the Diagnostics tile group, Caching insights, Cache reuse, Your sessions, the bottom-line banners.TAB_INFO), plain headings, a sentence per chart or table, jargon replaced or defined in a hover tooltip (term()). Reworked: Keep-alive (one verdict), Inventory (one ranked list with the command), Usage (one daily chart), Sessions (6 columns, order by cost, short account labels, phone layout), Requests, Components (Step, Saved, Cost, Net; reason codes in words), KV-cache (verdict first), Config, Strategies.prefers-reduced-motion./api/benchmarksroutes, ingest code and table DDL.--dashboard-bench-dirsstays as an ignored flag so an existing unit file still starts.#homelands on Overview,#cacheon Keep-alive,#savings/#tools/#sessionsalready resolve,/dashboard/home.htmlredirects. What the five-page home had that the classic lacked moved over: sessions ordered by cost, and the provider's own cache discount stated as not counted.docs/dashboard.md, a new plain guide (docs/how-to/dashboard-guide.md), reference updated;mkdocs build --strictpasses.Tests
dash/ui_smoke.mjs+TestUISmokeEveryTab: opens all 16 tabs in a real browser (fixture served as a hosted manager), fails on any JavaScript error, missing heading or intro, an error state on tabs whose data this package serves, any removed Overview section coming back, the Benchmarks tab or route returning, and the old five-page links not landing. Skips without node, playwright-core and a Chromium. Go UI tests updated only where they asserted removed tiles or old wording. Golden JSON untouched (API unchanged).Load time (paired, interleaved A B, 3 rounds, both builds on reflink copies of the same snapshot, all-time window, host load about 1.5; medians, milliseconds)
First visit to Overview on a cold process: main 55.6 s, branch 45.2 s (34 s of both is the first stats read of a 3.6 GB database). The Overview's savings rows paint from the
stats?lean=1read, about 6 s warm and 35 s on a cold process; the floor is the server's stats query, not the client (render after the last response is about 0.5 s). Details and the Keep-alive follow-up in a later comment.Screenshots (previous build)