fix(lint): chart-axis-not-selected resolves a report chart against its own chart.yAxis, not report.values (#15734) - #15789
Conversation
…s own chart.yAxis
The report surface fed `report.values` in as the set `chart-axis-not-selected`
resolves against. At the pinned `@object-ui` revision the embedded report chart
never queries that set: `DatasetReportRenderer.tsx` runs its own axis-pair query
(`useDatasetRows(dataset, [xAxis], [yAxis], …)`) and derives ONE series from it.
So the warning at `chart.yAxis` named a query consequence its own pin refutes,
and a `series[].name` override was measured against the wrong set in both
directions.
`checkReportChart` now carries `ownSelection` — the chart's own `{ chart.yAxis }`
— which the not-selected limb reads; the check at the `chart.yAxis` position is
removed on that surface. `chart-measure-unknown` is untouched everywhere, as are
the list-view and page-component surfaces, where `values` IS the query's measure
set.
Ruled by the maintainer on #15734 (option 1, batch #47).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…port-chart-axis-own-selection
📓 Docs Drift Check3 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 5 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 94476cdf9c735369e49a01f1e1775d246db75671 && git checkout 94476cdf9c735369e49a01f1e1775d246db75671
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin c99449ab5fd5e87292f4efccd15270cecf4d5242 658c596a1b5d977d5663f112cf8105c628af9d39 && git checkout -B drift-repro c99449ab5fd5e87292f4efccd15270cecf4d5242 && git merge --no-ff 658c596a1b5d977d5663f112cf8105c628af9d39
node scripts/docs-audit/affected-docs.mjs --json c99449ab5fd5e87292f4efccd15270cecf4d5242 |
|
ACCEPT — PR #15789 (head Ruling 1 ( Measured by this seat: Flip + arm when both required jobs report success on Generated by Claude Code |
|
Flipped ready + auto-merge enabled (08:26Z, Generated by Claude Code |
Fixes #15734
The ruling
Maintainer ruling recorded at
5550127165(batch #47, verbatim reply 「同意」) — option 1, quoted:The renderer at the pin, quoted
Read at the
@object-uirevision this repo pins —.objectui-sha=a472b07167a39e55491109e864bb5a54027dcfbd, verified present in the sibling checkout and read withgit cat-file -p a472b07…:packages/plugin-report/src/DatasetReportRenderer.tsx.The chart's query (lines 859–867 at that sha) asks for the axis pair and nothing else:
The file says so in its own words at the
scopeOrderdocblock (line 326): "the embedded chart queries onlychart.xAxis×chart.yAxis".And the series the override is matched against is derived from that same pair (line 1008), exactly one of them — line 1002 above it: "The selection is exactly one dimension × one measure, so this takes the helper's single-dimension branch and returns ONE series":
So
report.valuesis the selection of the TABLE beneath the chart, and the warning that fired for achart.yAxisoutside it named a query consequence its own pin refutes.What changed
ChartBindinggainsownSelection— the measures a chart's OWN query selects, when that is narrower than thevalueslimb.checkReportChartsets it to{ chart.yAxis }; the other two surfaces leave it undefined and keep resolving againstvalues, which on them IS the query's measure set.ownSelection ?? values, so a reportseries[].nameis measured against the singleton.chart.yAxiscall site no longer passes a selection at all — that position IS the query.chart-measure-unknownis untouched at every position, on every surface: an UNDECLARED measure is still no column, stillerrorat a query position.report.valuesis still walked forchart-measure-unknown, unchanged.recordsOf.Pins flipped and added
warns when the yAxis measure is declared but not selectedsays nothing when the yAxis measure is declared but outside report.values — a report chart cannot fail to select what it queries,expect(findings).toEqual([])chart-axis-not-selected at the report yAxis position keeps its wordingchart-axis-not-selected does not fire at the report yAxis position at all,toEqual([])(the branch it pinned is gone; the wording it guarded is not re-touched)series[].namenamingchart.yAxisis silent even whenreport.valuesdoes not select itseries[].namenaming a declared measure OTHER thanchart.yAxisfires — even onereport.valuesdoes select; asserts the message names the singleton,selected values (est_hours)views[0].list.chart.values[1]stillerrorchart-measure-unknownchart-axis-not-selectedand both messages nameselected values (task_count), i.e.values— never a borrowed singletonVerification
Exit codes captured before any pipe; verdict lines quoted as the tools printed them. Heavy runs through
scripts/pm/os-verify-lock.shwithOS_VERIFY_LOCK_SLOT=issue-15734.pnpm --filter @objectstack/lint exec vitest run src/validate-chart-bindings.test.tsTests 35 passed (35)·VERDICT command-exit 0pnpm --filter @objectstack/lint test(after mergingorigin/main)Test Files 97 passed (97)·Tests 3331 passed (3331)·VERDICT command-exit 0pnpm --filter @objectstack/lint typecheck(after the merge)check:test-typecheck: OK — @objectstack/lint's test layer compiles·VERDICT command-exit 0pnpm check:pm-dispatch-gatesdispatch-gates self-test: 1478 cases pass.·EXIT=0pnpm check:nul-bytescheck-nul-bytes: OK (scanned 7613 text file(s) … no raw ASCII control bytes).·EXIT=0node scripts/pm/check-governed-merges.mjs --test THE_3_CHANGED_PATHSNOT governed — ordinary queue landing applies·EXIT=0node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstackEXIT=0, 53 commands; all 53 run (see below)Ablation — the set change, trap-guarded, blob-hash restore
The implementation was committed first, so the restore leg points at
HEAD.trap 'RESTORE_FN' EXIT INT TERM; every path absolute fromgit rev-parse --show-toplevel. No dist leg: the test imports its subject relatively (./validate-chart-bindings.js, a sibling in the samesrc/), so it can never reachdist/— nothing to rebuild between legs.derivedreverted toreport.values, andselectedhanded back to thechart.yAxiscallgrep -c ABLATION= 2 (expect 2);grep -c 'binding.ownSelection ? new Set'= 0 (expect 0);git hash-object=dc31fa66…, differs from HEAD blob718a2cd5…Tests 4 failed | 31 passed (35)·VERDICT command-exit 1git checkout HEAD -- ABSOLUTE_PATHgit hash-object=718a2cd58249552fa0b9d46bac3871170ca97edb= HEAD blob;git diff HEAD: EMPTY (restored)Tests 35 passed (35)·VERDICT command-exit 0The four that fail under ablation are exactly the flipped pin, the replaced pin and the two new singleton pins:
The two new firing controls stay green under the ablation, which is the point of them: they measure the two surfaces this change does not move.
Lint — a declared narrowing, with the three readings
pnpm lint(eslint . --no-inline-config) is the repo-level sweep CI owns. Ran targeted instead, at final head658c596a1:isPathIgnoredovergit ls-files, not a guess): 5979 lintable tracked JS/TS files, 0 of them ignored.--format json: 2 —validate-chart-bindings.ts,validate-chart-bindings.test.ts;errors 0,warnings 0,EXIT=0.eslint.config.mjs, which "never enables type-aware linting (noparserOptions.project, no typed@typescript-eslintrules) for ANY file" (its own header, line 326). With no cross-file program, a diff confined to two files cannot move the verdict on any file it does not contain.NOT MEASURED, by name
pnpm check:dual-build-cjs-loads— exit 3,PREREQUISITE NOT MET — this gate reads built output, and some package has no dist/. Needs the whole workspace built; CI's.pnpm check:type-check-debt— exit 3,PREREQUISITE NOT MET, "Build the closure first, exactly as lint.yml does before this step". Its siblingpnpm check:type-check-coverageran and isEXIT=0.pnpm check:docs-transcript-drift— exit 3 on the first pass (packages/lint/dist/index.jsabsent), then re-run afterpnpm --filter '@objectstack/lint...' buildand it isEXIT=0: "4 declared transcript value(s) across 405 page(s) under content/docs/ equal what the registry derives today". Measured, not left open.check-cross-package-test-inputs --union-into "$RUNNER_TEMP/…", the threecheck-shard-attestation --emitjobs, the twocheck-test-completenessjobs,check-half-states --provenance="$PROVENANCE".dispatch-gatesprints them as⊘ NOT MEASUREDitself; no value exists outside a CI run.@objectstack/cliunit tier — attempted (vitest run --project unit) and not measured: 113 of 176 files fail before any assertion withFailed to resolve entry for package/Cannot find package(unbuilt dependency closure in this worktree), whileAssertionErrorcount is 0 and individual failed tests (×) is 0; 813 of the tests that did resolve passed. Left to CI, which builds first.@objectstack/cliis affected only through the dependency edge — this diff moves no exported symbol or signature.dispatch-gatesprints: silence there is a fact about a list, not a clearance. CI runs them.Gate family
All 53 derived commands were run: 50
EXIT=0, 3 exit-3 prerequisite cases named above (one of which was then measured green). The derived command list is byte-identical across three derivations — before the merge, after it, and after a furthergit fetch— soorigin/mainmoving under the branch did not move this card's family.Scope
Only the SET the report surface resolves
chart-axis-not-selectedagainst.origin/mainwas merged in (merge commit658c596a1) after PR #15751 landed at 07:16Z, and the lint suite re-run once on the merged tree; #15751's one-copy gate (collection-coercion-single-copy.test.ts) is green here.Changeset:
@objectstack/lintpatch, stating the behaviour change.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code