Repository navigation
Description
domain:ui#1 · os-sales · session_01L6bhgXU26UBEjd1KKHgNEx
Filing gate: ① a user-visible product defect, found beside #27460 (PR #27560) by the dev's read of the chart renderer at head 13e084eb. reach: NOT MEASURED by render (a bare jsdom render probe was non-deterministic for pie and drew no marks for funnel/treemap); the code read is below.
Business reason: a dashboard pie, donut, funnel or treemap widget with two dimensions and one measure looks complete but shows only the first group of the second dimension; every other group is dropped and nothing on the chart says so. This is the same class #27460 fixed for sankey.
Reader who acts: the triage seat (first grading), then the implementer for the chart renderer (ui/packages/plugin-charts/src/AdvancedChartImpl.tsx).
Dedupe words: pie two dimensions, pivot series[0], funnel second dimension, treemap pivot dropped.
Symptom
With dimensions: [a, b] and one measure, buildChartSeries pivots b into one series per value. The pie/donut, funnel and treemap arms read series[0]?.dataKey only, so only the first b value is drawn.
Mechanism
ui/packages/plugin-charts/src/AdvancedChartImpl.tsx: the pie/donut, funnel and treemap arms bindseries[0]and read no other series.ui/packages/plugin-dashboard/src/DatasetWidget.tsx(SINGLE_SERIESfamily comment, objectui#11417) covers dropped MEASURES on these families, not a pivoted second dimension.- PR fix(plugin-charts): a two-dimension sankey draws every flow, not only the first group's #27560 (dashboards: a sankey widget with two dimensions silently draws only the first category's flows #27460) gives sankey a two-level draw for the same input; it is the nearest precedent for a fix shape, not a ruling for these families (a pie may need a refusal or a note instead of a second ring).
Noted, not filed: buildChartSeries pivots only dimensions[1]; a third dimension collapses into the (d0, d1) cell (last row wins) on every family.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 经营报表 | none | P②
Triage: p2 ·
domain:ui·area:reports· 2026-10-29T14:05Z⛔ Not a claim.
bug,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Blocked-by: #27560 · 2026-10-29T19:31Z
plugin-charts/src/AdvancedChartImpl.tsx, the two-dimension grouping it rewrites for sankey (dashboards: a sankey widget with two dimensions silently draws only the first category's flows #27460). A claim now would race it on the same file.pm:queue→pm:blocked. Not claimed; no work done.pm:queueand claims from the newmain. On the maintainer's word (2026-10-29T19:27Z), seat 2 does not take fix(plugin-charts): a two-dimension sankey draws every flow, not only the first group's #27560 over. Seat 2 stays seated (the wind-down was withdrawn) and resumes this card when fix(plugin-charts): a two-dimension sankey draws every flow, not only the first group's #27560 lands.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Unblocked · 2026-10-29T20:54Z: the blocker landed. PR #27560 (#27460) merged at 2026-10-29T20:03Z. Labels move from
pm:blockedtopm:queue. Seat 2 dispatches this card next, and itsClaim:follows.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Claim: PM loop round 1 · 2026-10-29T20:56Z
Session:
session_01Utp6CY2n1JmZZKrHgtp9jC(seat; implementation by a card thread,mode:thread)Account:
os-billBranch:
claude/project-thread-osge5f(the card thread's harness push branch, self-reported — the measured platform exception toclaude/issue-N-slug)Worktree:
objectstack-issue-27563Domain:
domain:uiSeat:
domain:ui#2File surface:
ui/packages/plugin-charts/src/AdvancedChartImpl.tsx(pie/donut, funnel, treemap arms) and its tests;ui/packages/plugin-dashboard/src/DatasetWidget.tsxonly if a refusal note lives there; i18n keys if a refusal adds text; a changeset; ⛔packages/spec/**(a publish-time refusal is a spec door: stop withneeds_decision), every server file,examples/**Container & model:
M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no (expected; the dev measures from the diff)
Metadata-protocol: none (expected; the dev measures from the diff)
Responsibility: the chart renderer's pie/donut, funnel and treemap arms binding
series[0]only |buildChartSeriespivotingdimensions[1]into series is a fixed input | every dashboard author whose pie/donut/funnel/treemap widget has two dimensions and one measure, todayThread-read: 6508108377
Premise: holds as filed (code read at
13e084eb); step 1 of the order re-confirms onorigin/mainafter #27560 with a unit test per familySerial constraints cleared: #27560 (#27460, same
AdvancedChartImpl.tsx/DatasetWidget.tsx) merged 2026-10-29T20:03Z; sibling card #27491 (seat 2) may touchDatasetWidget.tsx, so whichever PR lands second rebasesDispatch order:
/mnt/project-files/ui-seat2/dispatch-27563.mdin the Claude Code project (not on GitHub); its ruling section quotes the triage text above verbatim.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
os-dev-report
{ "issue": 27563, "status": "done", "branch": "claude/project-thread-osge5f", "pr": "https://github.com/objectstack-ai/objectstack/pull/27736", "head": "d12c72c818c69ea25169f241868f87998e3ad941", "session": "session_01Utp6CanXq6PY9nH1pZ5E5m (card thread; seat session_01Utp6CY2n1JmZZKrHgtp9jC)", "premise_still_valid": true, "summary": "Measured the premise: on origin/main 525ea3632 the pie/donut, funnel and treemap arms of AdvancedChartImpl draw series[0] only for a buildChartSeries pivot (stage x owner, sum amount): the treemap drew 3 one-level leaves, pie/donut/funnel each rendered one Pie/Funnel bound to the first owner. Fix per family: treemap draws every group as two levels (buildTreemapGroups: parent per first-dimension value, leaf per carried second-dimension cell, named 'stage / owner', unsized cells left out with the existing unsized-rows note per group, no-positive-magnitude refusal naming every group, leaf click drills to the cell); pie, donut and funnel refuse on the tile (OneSeriesFamilyRefusal in the ChartRefusal shell, data-chart-error one-series-family) naming every group, because a second series has no place on one ring or one funnel and a two-level ring is a new visual this card does not decide. groupSeries (sankeyFlowSeries renamed and shared) ignores comparison overlays. DatasetWidget hands every SINGLE_SERIES_CHART_FAMILIES family only the measure it renders (the 27460 sankey filter widened), so stored multi-measure widgets still draw their first measure. No spec, server or locale change; refusal copy is English like its siblings.", "tests": "New AdvancedChartImpl.twoDimensionSingleSeries-27563.test.tsx (20) and DatasetWidget.twoDimensionSingleSeries-27563.test.tsx (12): 32/32 pass. Premise/ablation legs (git restore --source=525ea3632, trap restore, hash-object == HEAD blob and git diff HEAD empty): base renderer+widget 15 failed/17 passed (all subjects red, all controls green); base DatasetWidget only 8 failed (4 new two-measure controls + 4 singleSeriesMeasures-11417 TIE rows). plugin-charts+plugin-dashboard full vitest under the lock at 5d26a453: 297/298 files, the one red the ChartRenderer.yAxisUndrawn-10691 pie control (authored yAxis list on a pie now refuses; control updated, see open_questions). Then 38 files (the 10691 file, the 27563 renderer file, console/app-shell/chatbot/list chart tests, all plugin-report tests): 38 passed, 390 tests. At 4fb5e46c (after merging main): 6 files (27563 x2, 10691, 11417, 27460 sankey x2) 81 passed. plugin-charts and plugin-dashboard type-check exit 0. eslint touched files 0 errors.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 35 at 4fb5e46c (same list as before the merge); run at 4fb5e46c, changeset-reading gates re-run at d12c72c8 (later commits touch only the changeset); --ran: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. node scripts/check-adr-0087-registration.mjs --self-test :: exit 0; node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0; node scripts/check-empty-changeset.mjs --self-test :: exit 0; node scripts/check-sdui-manifest.mjs :: exit 0; node scripts/check-sdui-manifest.mjs --self-test :: exit 0; node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0; node scripts/release-pending-publish.mjs --self-test :: exit 0; pnpm --dir ui exec vitest run scripts/ :: exit 0; pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0; pnpm check:changeset-gate-self-tests :: exit 0; pnpm check:closed-ceremony-text :: exit 0; pnpm check:cross-package-test-inputs :: exit 0; pnpm check:dispatcher-error-vocabulary :: exit 0; pnpm check:driver-memory-census :: exit 0; pnpm check:engine-double-contract :: exit 0; pnpm check:error-status-conformance :: exit 0; pnpm check:gitlink-declared :: exit 0; pnpm check:nul-bytes :: exit 0; pnpm check:published-files :: exit 0; pnpm check:query-options-erasure :: exit 0; pnpm check:refd-timer-probe :: exit 0; pnpm check:skill-identifier-liveness :: exit 0; pnpm check:test-source-alias :: exit 0; pnpm check:tier-file-adoption :: exit 0; pnpm check:type-check-coverage :: exit 0; pnpm check:type-check-debt :: exit 0; pnpm check:undeclared-dep-imports :: exit 0; pnpm check:watch-hint-literal :: exit 0; pnpm check:where-matcher :: exit 0; node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0; node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0; node scripts/check-empty-changeset.mjs --base origin/main :: exit 0; node scripts/check-closing-keyword-parity.mjs :: exit 0; pnpm check:pm-changeset-deadline-census :: exit 0; node scripts/check-comment-mask-corpus.mjs :: exit 0. CI check-runs on PR #27736: in_progress at report time.", "dogfood_battery": "n/a - no ! in the PR title and no narrowing arm", "line_budget": "594 changed lines (+571/-23) vs origin/main: AdvancedChartImpl.tsx +180/-7, renderer test +233, DatasetWidget.tsx +18/-15, widget test +118, 10691 test +6/-1, changeset +16; under the 3000 human-merge threshold", "files_changed": [ ".changeset/27563-two-dimension-single-series.md", "ui/packages/plugin-charts/src/AdvancedChartImpl.tsx", "ui/packages/plugin-charts/src/AdvancedChartImpl.twoDimensionSingleSeries-27563.test.tsx", "ui/packages/plugin-charts/src/ChartRenderer.yAxisUndrawn-10691.test.tsx", "ui/packages/plugin-dashboard/src/DatasetWidget.tsx", "ui/packages/plugin-dashboard/src/__tests__/DatasetWidget.twoDimensionSingleSeries-27563.test.tsx" ], "deviations": [ "DatasetWidget.tsx is touched for the measure filter and two comments, not for a refusal note (the Claim lists it conditionally).", "ChartRenderer.yAxisUndrawn-10691.test.tsx (an existing plugin-charts test) edited: its draw helper settles on the plot or the refusal and the pie control asserts the refusal; its subject (no y-axis note on a pie) is unchanged.", "Refusal copy is an English literal like every sibling refusal; no locale keys.", "The harness's post-PR assign/review step was skipped, per the maintainer's routing rule." ], "mcp_calls": "0 - no GitHub MCP call; card, comments and PR read through gh api GET.", "api_writes": "2 - relay pr_create (draft, no assignee, no reviewer, no labels) via run 40960895059, body read back identical (14107 bytes); this os-dev-report comment. Plus git pushes of the branch (not REST).", "open_questions": [ { "question": "Keep the renderer-wide reading (two or more non-comparison series on pie/donut/funnel/treemap = groups), which also changes charts outside the dashboard that carry several MEASURES, or restrict it to pivots?", "evidence": "AdvancedChartImpl cannot tell a pivoted group from a measure. A chart block authoring a yAxis list on a pie (ChartRenderer.yAxisUndrawn-10691 control) and a page chart with one dimension and two measures (checkDashboardWidgetChartMeasureArity is attached to the dashboard widget schema only) used to draw their first measure silently; now pie/donut/funnel refuse naming every measure and a treemap nests the measures. #27560 made the sankey read series the same way.", "options": [ "A - keep (this PR): one rule for all five single-series families, no partial chart anywhere; multi-measure treemaps nest measures of possibly different units.", "B - mark pivot series in buildChartSeries (@object-ui/core published type, Clause-2 yes (widening)) and refuse/nest only on that marker; multi-measure charts keep drawing their first measure silently." ], "recommendation": "A, because the silent first-measure draw is the same partial-chart class triage ruled out and the sankey already reads series this way; B if the seat wants this card scoped to the dashboard pivot only." } ], "out_of_scope_findings": [ "observation, not filed · reach: the dashboard publish door accepts dimensions [d0, d1] with one measure on pie/donut/funnel (the spec's single-series arm judges the measure count only) · triage's 'refuse at publish' half would be a spec door (packages/spec), outside this card; the tile refusal covers render now · dedupe words: publish refuse second dimension pie, single-series two dimensions · carrier: seat" ] }objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
ACCEPT → PR #27736 comment 6509565003 (head
d12c72c8). Contract review not owed (Clause-②: no,Metadata-protocol: none). Landing through the merge queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Landed · 2026-10-29T22:31Z
d7625ea4500aa244c792d55b5d7668c80dbc10fecompletedby the PR'sFixeslineState:
pm:dispatchedremoved; the assignee stays as the record of who carried it.Generated by Claude Code