Found while implementing #15575 (the per-surface tier read for chart-measure-unknown). Out of scope there — that card rules on the tier and the consequence WORDING, and this is about which set the check resolves against — but it is the same measurement, one branch over.
The claim
packages/lint/src/validate-chart-bindings.ts raises chart-axis-not-selected (warning) when a chart position names a measure the dataset declares but this chart's values does not select. On the report surface that set is report.values — the report's own measure selection, fed in by checkReportChart:
values: { names: values, path: `${path}.values` },
Read at the @object-ui revision this repo pins (.objectui-sha = a472b07167a39e55491109e864bb5a54027dcfbd), a report chart does not query report.values at all. plugin-report/src/DatasetReportRenderer.tsx runs the chart's OWN, narrower query out of the two axis strings:
const state = useDatasetRows(
dataset,
plan.kind === 'series' && xAxis ? [xAxis] : [],
wantsQuery && yAxis ? [yAxis] : [],
...
and says so in its own words at the scopeOrder docblock: "one report's order is validated against its WHOLE selection, while this renderer issues narrower sub-selections from it: the embedded chart queries only chart.xAxis × chart.yAxis".
So on the report surface the rule resolves against the wrong set, in both directions:
chart.yAxis naming a declared measure outside report.values is reported as "the query does not return it, so the series plots nothing" — but the chart's own query asks for exactly that measure, and it plots. A false positive whose stated consequence the pin refutes. (Fixture shape: values: ['task_count'], chart: { xAxis: 'status', yAxis: 'est_hours' } — pinned today by the test named "warns when the yAxis measure is declared but not selected".)
chart.series[].name is a display-name override matched against the ONE series the chart derives — its chart.yAxis. The set that decides whether the override lands is therefore the singleton { chart.yAxis }, not report.values: an entry that IS in report.values but is not the plotted measure lands on nothing and is reported by nothing, while an entry that names chart.yAxis but is absent from report.values lands correctly and is reported.
PR #15741 (for #15575) corrected the SENTENCE at both positions so neither still names a query consequence the pin refutes, and deliberately did not move the set — changing which findings fire is a behaviour decision that card did not put to the PM. This card is that decision.
What to decide
- Resolve the report surface's
chart-axis-not-selected against the chart's own selection — { chart.yAxis } for the series limb, and drop the check at the chart.yAxis position itself (a report chart cannot fail to select what it queries).
- Keep
report.values as the set and narrow the finding to what stays true of it (e.g. report it only as "this chart plots a measure the table beneath it does not show", which is a different, cosmetic claim).
- Something else the measurement suggests.
Note the list-view and page-component surfaces are NOT affected: on those, values IS the measures the query asks for, so the existing set is the right one there.
Filed unassigned and unlabeled for triage — not started, no branch.
Generated by Claude Code
Found while implementing #15575 (the per-surface tier read for
chart-measure-unknown). Out of scope there — that card rules on the tier and the consequence WORDING, and this is about which set the check resolves against — but it is the same measurement, one branch over.The claim
packages/lint/src/validate-chart-bindings.tsraiseschart-axis-not-selected(warning) when a chart position names a measure the dataset declares but this chart'svaluesdoes not select. On the report surface that set isreport.values— the report's own measure selection, fed in bycheckReportChart:Read at the
@object-uirevision this repo pins (.objectui-sha=a472b07167a39e55491109e864bb5a54027dcfbd), a report chart does not queryreport.valuesat all.plugin-report/src/DatasetReportRenderer.tsxruns the chart's OWN, narrower query out of the two axis strings:and says so in its own words at the
scopeOrderdocblock: "one report'sorderis validated against its WHOLE selection, while this renderer issues narrower sub-selections from it: the embedded chart queries onlychart.xAxis×chart.yAxis".So on the report surface the rule resolves against the wrong set, in both directions:
chart.yAxisnaming a declared measure outsidereport.valuesis reported as "the query does not return it, so the series plots nothing" — but the chart's own query asks for exactly that measure, and it plots. A false positive whose stated consequence the pin refutes. (Fixture shape:values: ['task_count'],chart: { xAxis: 'status', yAxis: 'est_hours' }— pinned today by the test named "warns when the yAxis measure is declared but not selected".)chart.series[].nameis a display-name override matched against the ONE series the chart derives — itschart.yAxis. The set that decides whether the override lands is therefore the singleton{ chart.yAxis }, notreport.values: an entry that IS inreport.valuesbut is not the plotted measure lands on nothing and is reported by nothing, while an entry that nameschart.yAxisbut is absent fromreport.valueslands correctly and is reported.PR #15741 (for #15575) corrected the SENTENCE at both positions so neither still names a query consequence the pin refutes, and deliberately did not move the set — changing which findings fire is a behaviour decision that card did not put to the PM. This card is that decision.
What to decide
chart-axis-not-selectedagainst the chart's own selection —{ chart.yAxis }for the series limb, and drop the check at thechart.yAxisposition itself (a report chart cannot fail to select what it queries).report.valuesas the set and narrow the finding to what stays true of it (e.g. report it only as "this chart plots a measure the table beneath it does not show", which is a different, cosmetic claim).Note the list-view and page-component surfaces are NOT affected: on those,
valuesIS the measures the query asks for, so the existing set is the right one there.Filed unassigned and unlabeled for triage — not started, no branch.
Generated by Claude Code