fix(#111): cap chart X categories, not raw rows; honest transform note#274
Merged
Conversation
buildChartData() previously sliced the raw rows to chartRowCap(type) BEFORE grouping, so a row past the cap was dropped from its category's sum and a category could vanish only because its first row arrived late. Now it is two-pass: pass 1 discovers unique raw X keys across ALL fetched rows in first-seen order and retains the first `cap`; pass 2 aggregates every fetched row whose X is a retained category. Categories are never value-ranked, sorted, or folded into an Other bucket. The result carries typed ChartDataMeta (totalRows/totalCategories/ shownCategories/categoriesTruncated/duplicateCellsSummed/groupKey) and a new pure chartDataNote(meta) renders "first N of M categories" and/or "duplicate X[/series] rows summed in the browser" — describing only the browser-side transform, never whether the SQL pre-aggregated. Duplicate detection keys on X (or (X, series)), so a normal multi-series result is not reported as summing, and a duplicate confined to an omitted category never flags the visible chart. renderChart aggregates once (chartJsConfig accepts the precomputed result) and renders the note on every surface: inline in the config bar on the workbench, and as a standalone block above the canvas on Dashboard / read-only / detached tiles (controls:false), which previously capped categories silently. Tests: buildChartData category-cap + metadata cases, chartDataNote formatter, renderChart note text/placement across control states + the single-aggregation contract, and a Dashboard-surface panels regression. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XP1KN94N969SVMNFPdVtGg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Fixes #111 (follow-up to #109).
buildChartData()applied the chart-typerow cap to the raw rows before grouping, so the chart could disagree with
the result already in memory: a category was short-totaled when another row for
the same cell appeared after the cap, and a category could vanish only because
its first row appeared after the cap. The old note also said
first N of M rowswhile the chart displays categories, and — because the note lived inside the
controls block — Dashboard and read-only/detached tiles (
controls:false)capped categories silently.
Fix
buildChartData(): pass 1discovers unique raw X keys across all fetched rows in first-seen order and
retains the first
chartRowCap(type); pass 2 aggregates every fetched rowwhose X is a retained category. No value-ranking, sorting, or
Otherbucket.ChartDataResult.meta: ChartDataMeta(
totalRows/totalCategories/shownCategories/categoriesTruncated/duplicateCellsSummed/groupKey).chartDataNote(meta)→first N of M categoriesand/orduplicate X[/series] rows summed in the browser. It describes only the browser-side transform, never whether the SQLpre-aggregated. Duplicate detection keys on X (or
(X, series)), so a normalmulti-series result with repeated X values is not reported as summing, and
a duplicate confined to an omitted category never flags the visible chart.
workbench, and as a standalone block above the canvas on
controls:falsesurfaces (Dashboard / read-only / detached).
chartJsConfigaccepts the precomputedChartDataResultvia a newdataoption.No
panels.tschange was needed (the note now renders regardless of controls);no new runtime dependency and no new network request.
Tests
chart-data.test.ts: late-row contribution, first-seen order, post-capomission, all metadata states (truncation-only, duplicate-only, both,
unique multi-series, duplicate
(X, series), duplicate in an omittedcategory, series only in omitted categories),
chartDataNoteformatter, andchartJsConfighonoring precomputeddata.chart-render.test.ts: category-cap note text, type-switch recompute,duplicate-X / duplicate-X-series / combined text, standalone note on
controls:false, no-note when neither condition holds, and singleaggregation per render.
panels.test.ts: a Dashboard chart panel discloses the cap despite hiddencontrols.
npm test(2891 tests, per-file 100/100/100/100 gate) andnpm run buildpass.Closes #111.
Checklist
npm testpasses (the per-file coverage gate is non-negotiable)npm run buildsucceeds (single-filedist/sql.html)src/core/, network insrc/net/(injected fetch), DOM insrc/ui/CHANGELOG.md([Unreleased]) updated if behavior or the deployed surface changed🤖 Generated with Claude Code
https://claude.ai/code/session_01XP1KN94N969SVMNFPdVtGg