Repository navigation
feat(plugin-charts): the dataKey arm of ChartRendererProps.series declares type (objectui#8086) - #10554
Conversation
…lares type Align the published TS union with what ChartDataSeriesSchema and the renderer accept: the dataKey arm gains `type?: string`, the name arm's own member type. No other arm changes. The docblock that said the union "stays as declared" is restated, the body comment's round-trip claim is corrected for the new member, the specSeries case drops its cast, and an arm-level compile-time pin sits beside it. The ObjectChartSchema.series docblock in @object-ui/types no longer claims to copy the arm verbatim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: ① Derived judgmentsArm change is exactly the ruling's letter. H3 verified true. Scratch probe ( H5 verified. Same probe: on base the four arm-level statements are red exactly as the PR lists them (Equal pin TS2339, arm-typed literal TS2353, read-back TS2339, Kept Two out-of-letter prose hunks. (1) Body comment: old text "round-trips every key the internal arm declares unchanged" became false once the arm declares Pending changesets. 2013 pending ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
…ies type and names chartType (objectui#10584) (objectstack-ai#10768) Fixes objectstack-ai#10584 Clause-②: no. The accept set does not move; this is a `.describe` and docblock wording fix. `yes` would be owed only if a named producer turned the card to widening, and then the dev stops and reports. ## What changed - `packages/types/src/zod/objectql.zod.ts`, the `series` member of `ObjectChartSchema`: the `.describe()` no longer calls the element "the arm ChartRendererProps declares". It now says the copy is that `{ dataKey }` arm minus the arm's per-series `type`, which this copy does not declare, and that this copy's per-series family override is `chartType` (`bar` | `line` | `area`). A short comment above the member points at the TS twin for the ground. - `packages/types/src/objectql.ts`, the `series` member docblock: "this copy has not taken up" (which read as a lag) now says the omission is deliberate. Taking `type` up widens a published accept set and waits for a named producer that writes it on an `object-chart` node. The docblock also states what a `type` written anyway meets on each face (measured below). - `.changeset/10584-object-chart-series-describe.md`: `@object-ui/types` `patch`, since the `.describe()` string is published text. Both edits stay inside the `ObjectChartSchema` block, which is the file surface the claim names. No member, type or schema node changes. ## Premise check on `origin/main` at `0896838deb` - **H1 holds.** The zod `.describe()` said "the arm ChartRendererProps declares", while both arms of `ChartRendererProps.schema.series` carry `type?: string` (objectui#8086). The TS docblock already named the omission ("every member of it except `type` ... this copy has not taken up"). It now says the omission is deliberate. - **H2 holds.** PR objectstack-ai#10734 (objectui#10608) and PR objectstack-ai#10601 (objectui#10518) are both on `main`, so this card's serial predecessors on the block have landed. The text was re-read on `main`; the card's line numbers were not used. - **H3: no pin.** `git grep` for the old describe text ("ChartRendererProps declares", "plotted series in the renderer", "has not taken up") matches only the two source files. No test, generated artifact or doc asserts the string, and no describe-verdict pin (`INTERNAL` / `AUTHORABLE` prefix) reads it. ## Stop condition: producer census for a per-series `type` on `object-chart` No producer found, so the work did not stop. Each reading has a control that hits: - **objectui (in-repo):** every `type: 'object-chart'` literal outside tests is in one of the relays: app-shell `ObjectView`, plugin-view `ObjectView`, plugin-list `ListView`, plugin-dashboard `DashboardRenderer` and `DashboardGridLayout`. Each writes `series` as `{ dataKey, label }`, and none writes `type`. app-shell forwards `viewDef.chart.series` verbatim, but the spec's `ListChartConfigSchema` is a `strictObject` with no `series` member, so no conforming stored view carries one. `chartConfigPresentation` emits no `series`. The only `{ dataKey, type }` literals are in `plugin-charts` tests of the `chart` renderer. - **objectstack showcase (at `16c5a33`):** `command-center.page.ts` writes `object-chart` nodes with no `series`. `renewals-pipeline.page.ts` writes `series={[{ name: 'total', label: 'Invoice value' }]}` on the ObjectChart react block: the `{ name }` arm, with no `type`. - **hotcrm (shallow clone at `2f7b232`):** zero `object-chart` / `ObjectChart` hits, and zero `series` in the 15 files under `src/**/dashboards` and `src/**/reports`. Control: 34 chart `type:` literals across those files (five dashboards and two reports). ## What each face does with a per-series `type` (measured, unchanged by this PR) Measured on the rebuilt `dist` at HEAD `5dc9a71e02`, with the same readings on the base build: - **zod mirror:** `ObjectChartSchema.safeParse` of `series: [{ dataKey: 'margin', type: 'line' }]` gives `success: true`, and the parsed series is `[{"dataKey":"margin"}]` (the plain `z.object` element strips `type`). `{ dataKey, chartType: 'line' }` keeps `chartType`. `{ label }` alone is still `invalid_type` at `series.0.dataKey`. The base build gives the same result for each. - **TS face:** `tsc --strict` on a literal typed `ObjectChartSchema` gives `TS2353` ("'type' does not exist in type ...") for `{ dataKey, type }` and compiles `{ dataKey, chartType }`. - **`dist` diff, base vs head:** the non-comment lines of `objectql.d.ts` are byte-identical. `zod/objectql.zod.d.ts` and `zod/index.zod.d.ts` differ only in union-member emission order on members this PR does not touch (`"json" | "csv" | "xlsx"` versus `"json" | "xlsx" | "csv"`, `position` and `operator` unions). `zod/objectql.zod.js` differs only in the comment and the describe string. ## Verification (all on HEAD `5dc9a71e02`, working tree clean) - `pnpm --filter @object-ui/types build`: `VERDICT command-exit 0`. The dependency closure `@object-ui/types^...` has no build script, so it is empty. - `pnpm --filter @object-ui/types type-check`: `VERDICT command-exit 0` (the script name is echoed as `type-check`). - `pnpm exec vitest run --maxWorkers=2 packages/types/`: `Test Files 245 passed (245)`, `Tests 5327 passed (5327)`, exit 0. - `pnpm exec vitest run --maxWorkers=2 packages/plugin-charts/`: `Test Files 82 passed (82)`, `Tests 964 passed (964)`, exit 0. Direction: the downstream consumer of `@object-ui/types` named in the dispatch, run to confirm no fixture reads the describe string. - Out-of-package tests that parse `objectql.ts` / `objectql.zod.ts` from disk (app-shell `relayRungCensus-7559`, `chartConfigForward-7891`; plugin-grid, plugin-kanban, plugin-tree and react census pins; and eight `scripts/__tests__` suites): `Test Files 15 passed (15)`, `Tests 602 passed (602)`, exit 0. - ESLint `--no-inline-config --format json` on the two touched sources: exit 0, 2 files linted, 0 errors, and 35 `no-explicit-any` warnings, none on an edited line. Type-aware linting is not enabled (`eslint.config.js` has no `parserOptions.project` / `projectService`), so this diff cannot move a verdict on any untouched file. - `node scripts/check-changeset-presence.mjs` 0 · `node scripts/check-changeset-no-major.mjs` 0 · `pnpm check:new-line-citations` 0 (`VERDICT new-cross-file-line-citations: 0 new citation(s)`) · `pnpm check:control-bytes` 0 · `pnpm check:spec-symbols` 0 · `pnpm check:test-path-roots` 0 · `pnpm check:changeset-claims` 0 (report-only). The pending objectui#8086 changeset's sentence "that copy of the internal arm does not carry `type`, and its type is unchanged" is still true. - `pnpm check:component-surface-parity` 0 · `check:designer-field-key-parity` 0 · `check:doc-types` 0 · `check:installed-pin-claims` 0 · `check:handler-key-reads` 0 · `check:action-forward-parity` 0. - `node scripts/check-governed-queue-guard.mjs --test` on the three paths: `NOT GOVERNED`. - **NOT MEASURED: `pnpm check:doc-examples`**, exit 2, prerequisite not met. It needs the dist of about 30 workspace packages, and that full build is CI's. This diff adds no `@example` block or fence (zero added lines match), so the gate's population is unchanged. - **NOT RUN: Spec Main Shape Gate.** The touched member is not spec-derived: the `series` element is a local copy of `ChartRendererProps`' arm and binds no `@objectstack/spec` symbol. The emitted `objectql.d.ts` is non-comment byte-identical, so compiling against any spec cannot move. ## Acceptance notes - **Kept verbatim: the `INTERNAL (relay-composed)` prefix.** It is objectui#7946's ruled verdict. The census above measured a channel it does not name: the ObjectChart react block. The spec's `react-blocks` entry has `schemaType: 'object-chart'` and `schema: ChartConfigSchema`, and it lists `series` in `dataProps`. `ChartSeriesSchema` is the `{ name }` arm and carries the per-series `type`. The showcase's `renewals-pipeline` page writes `series={[{ name, label }]}` through that block onto an `object-chart` node, and the published zod face refuses that node (`invalid_value` at `chartType`, `invalid_type` at `series.0.dataKey`). That belongs to the same family as objectui#10518 / objectui#10608 (the `object-chart` copy against the spec's ChartConfig contract), and it is reported to the seat rather than acted on here. It does not change this card's answer. On this node the spec's per-series `type` rides the `{ name }` arm, and the spec refuses `dataKey` by name, so a `{ dataKey, type }` entry is not spec-authorable on `object-chart` either. - The describe names `chartType` because it is this copy's declared per-series override. It is not a new authoring recommendation: the member stays `INTERNAL`. - No pin was added. The dispatch owed one only if the wording was already pinned, and it was not. Refs: objectui#8086 · objectui#7946 · PR objectstack-ai#10554 --- _Generated by [Claude Code](https://claude.ai/code/session_014fWVhLzhxR8qrFsJ5o8TYW)_ Co-authored-by: Claude <noreply@anthropic.com>
Fixes #8086
Clause-②: yes
A published TS union widens to what
ChartDataSeriesSchemaand the renderer already accept. This executes ruling5809905710(align) on objectui#8086, dispatched by thedomain:uiseat 2 (claim comment5828875764).What changed
packages/plugin-charts/src/ChartRenderer.tsx: thedataKeyarm ofChartRendererProps.schema.seriesgainstype?: string, the same member type thenamearm declares. No other member of either arm changes. The docblock that PR fix(plugin-charts): honour series[].type override on a dataKey-shaped series too #8080 added ("This TS union stays as declared …") is replaced by the aligned statement. The component-body comment saidnormalizeSeriesround-trips "every key the internal arm declares" unchanged. That comment is updated for the new member, becausetypeis translated tochartTypeand not passed through.ChartRenderer.specSeries.test.tsx: theas anyon the{ dataKey, type }case is removed. The one otheras any, on thecategoriescase, stays, and a comment now gives the reason: it coverscategories, whichChartRendererProps.schemadoes not declare. Leg B below measures this.ChartRenderer.seriesTypeArm-8086.test.ts(new, in the same folder): compile-time pins against each arm.packages/types/src/objectql.ts: a prose-only change. TheObjectChartSchema.seriesdocblock said its element type is the internal arm "VERBATIM". After this change that arm carriestypeand the copy does not, so the sentence is rewritten. The type itself is unchanged. See Deviations..changeset/8086-chart-series-type-arm.md:'@object-ui/plugin-charts': minor.Premise measurement: the old
as anywas not neededseriesis a union with no literal discriminant. TypeScript's excess-property check on an object literal therefore only asks whether each key is known to at least one arm. On the base declaration, the specSeries literal with{ dataKey: 'margin', type: 'line' }compiles without the cast, becausetypeis known to thenamearm. Leg A shows this: with the cast already removed,ChartRenderer.specSeries.test.tsxreports zero errors. For the same reason, a{ name, chartType }literal compiles against the whole union on both base and head, becausechartTypeis known to thedataKeyarm.The gap the card names is real, but it is in the arm, not the union. On base, a value typed as the
dataKeyarm cannot carrytype(TS2353), and an entry narrowed with'dataKey' in entrycannot read it (TS2339). So each new pin is written against a single arm, theExtractof the union on its binding key. Pins written against the whole union would pass on both sides of the change.Evidence (HEAD
ff726c28c)Red on base (leg A). This leg removes only the new member from
ChartRenderer.tsx, which restores the base declaration, and keeps every test at HEAD. The edit went throughnode ../objectstack/scripts/ablation-replace.mjs: the anchor went from 1 hit to 0, the blob changed frome0dac80c6e03toad7bb3165aac, and after restore the blob matched HEAD andgit diff HEADwas empty. It then rantsc -p tsconfig.test.json --listFilesinpackages/plugin-charts. The file list includesChartRenderer.tsx,ChartRenderer.seriesTypeArm-8086.test.tsandChartRenderer.specSeries.test.tsx. Line and column numbers are removed from the output below:Leg A also reports no error in
ChartRenderer.specSeries.test.tsx, which is the premise measurement above. The control@ts-expect-errorraised no TS2578, so a{ name, chartType }value typed as thenamearm is refused on base, as it is on head.Green on head.
pnpm run type-checkinpackages/plugin-charts(tsc --noEmit && tsc -p tsconfig.test.json) printedVERDICT command-exit 0.Kept cast (leg B). With the
as anyremoved from thecategoriescase at HEAD, tsc reportsChartRenderer.specSeries.test.tsx TS2353: Object literal may only specify known properties, and 'categories' does not exist in type '{ type: string; ... }'andTSC_EXIT=2. After restore, the blob matched HEAD.Tests (repo-root form, through the shared verify lock):
pnpm exec vitest run --maxWorkers=2 packages/plugin-charts/:Test Files 73 passed (73),Tests 831 passed (831).pnpm exec vitest run --reporter=verboseon the two touched test files: 2 files, 9 tests passed, 3 of them in the new pin file.pnpm run type-checkinpackages/types: exit 0.pnpm exec vitest run --maxWorkers=2 packages/types/:Test Files 233 passed (233),Tests 5184 passed (5184).Gates (verdict lines as printed):
node scripts/check-changeset-presence.mjs:✅ 4 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s).check-changeset-no-major✅,check-changeset-overwrite✅,check-changeset-fixed✅,check-changeset-claims: both sections PASS.pnpm check:new-line-citations:VERDICT new-cross-file-line-citations: 0 new citation(s).pnpm check:control-bytes:✅ check-control-bytes: OK.check:pending-changeset-literals,check:test-path-roots,check-vi-mock-specifiers/-inherit/-override-shape,check-type-check-coverage(43/43),check:published-tsconfig-excludeandcheck:unreferenced-sources: all OK.node scripts/check-governed-queue-guard.mjs --teston the five paths:NOT GOVERNED.eslint --print-configfinds the rooteslint.config.jsfor each file (117 to 118 rules), so none is ignored. Second,--format jsonshows 4 files and 0 errors; the only warnings are the existingno-explicit-anyones, and the specSeries file has one fewer than on base. Third,eslint.config.jshas noparserOptions.projectorprojectService, so type-aware linting is off, and no local rule undereslint-rules/reads the filesystem. This diff therefore cannot change the lint result of any file it does not touch. The fullpnpm lintruns in CI.typeas a per-series key for either binding.Deviations
File surface. The claim listed
ChartRenderer.tsx(only thedataKeyarm and the docblock), the specSeries test with a pin next to it, and the changeset. Two edits fall outside that list. Both are prose that this change would otherwise leave false:ChartRenderer.tsx(same file, but not the docblock);ObjectChartSchema.seriesdocblock inpackages/types/src/objectql.ts(the "VERBATIM" claim).The dispatch order says to stop on a breach. The os-dev role file says published text that the change makes false must be fixed, and that the role file wins when the two conflict. So both edits are made and listed here. The claim's file surface needs the seat to add them. If the seat wants them out, removing those two hunks is enough, and the type change does not depend on them.
Commit trailer. Commit
ff726c28cends with the harness-suppliedCo-Authored-Bytrailer, which names the model, instead of the model-free pair. History is not rewritten, because force-push is banned here.Acceptance notes
ChartRendererPropsis not re-exported by name from the@object-ui/plugin-chartsentry. Consumers reach it as the props type of the exportedChartRenderer. In the published 17.6.0 dist it is declared indist/ChartRenderer.d.tsand used by the registry map type indist/index.d.ts, and itsdataKeyarm has notype. The runtime half, objectui#7681, is still a pending changeset, so the declaration and the behaviour ship in the same release.ObjectChartSchema.seriesin@object-ui/types(the TS interface and its zod mirror) is a copy of the internal arm and does not havetype. Whether that published copy should follow is a separate Clause-② decision that this PR does not take. Carrier: none.widget-schema-anchors-7946.test.tssaysseries' element type "is" the internal arm. Its assertion only pinsdataKey: string, which still holds. The comment is test-only and not published, so it is left unchanged.seriesunion has no literal discriminant, so object literals get union-wide excess-property checks, and a{ name, chartType }literal type-checks against the union. This PR leaves that as it is, because the ruling allows no other arm change.Generated by Claude Code