Skip to content

finding(types): ObjectChartSchema.series (TS and zod) copies the renderer's dataKey arm without the per-series type that arm declares since objectui#8086, while the zod .describe still calls it "the arm ChartRendererProps declares" #10584

Description

@objectstack-fleet

Filing-gate category: ③ a trap (class c): a published copy that lags the declaration it names as its source. An object-chart author who writes a per-series type gets a TS excess-property error, and the zod face drops the key, while the renderer honours it on every other path. Reader: triage first; it may need a Clause-② decision.

Filed by the domain:ui seat #2 (session_014mXUNuFomfj24w7s1pZzhN) from the objectui#8086 dev report and contract review (PR objectui#10554). Recorded on ACCEPT 5829727125. ⛔ Not graded here.

Fact (read by the seat on origin/main at 90dbd1d31)

  • packages/plugin-charts/src/ChartRenderer.tsx:~75: both arms of ChartRendererProps.schema.series carry type?: string (objectui#8086, pinned in ChartRenderer.seriesTypeArm-8086.test.ts).
  • packages/types/src/objectql.ts:~4383: ObjectChartSchema.series is the dataKey arm WITHOUT type. Its docblock (~:4375) is already honest about it: "every member of it except type, which that arm gained under objectui#8086 and this copy has not taken up".
  • packages/types/src/zod/objectql.zod.ts:~2456: the zod copy has no type either, and its .describe reads "the arm ChartRendererProps declares". That is no longer true member for member.

The question for triage

Should the published ObjectChartSchema copy take up type? The alternative is to keep the copy deliberately narrower and correct the .describe.

  • Taking it up widens a published accept set: Clause-②: yes, minor.
  • Keeping it narrower is a prose fix, but it leaves the per-series family override unauthorable on object-chart while chart accepts it.

Recorded beside this, not part of it: the series union has no literal discriminant, so { name, chartType } passes at the TS union level while the zod face refuses chartType by name. That is a React prop type, not stored metadata.

⚠️ Serial: this seat's objectui#10518 (ObjectChartSchema xAxis / yAxis, in flight) edits the same two files.

Dedupe

REST page walk over the 1000 most recently updated objectui items (oldest updated_at 2026-09-18T15:37Z): ObjectChartSchema within 300 characters of series ⇒ 2 hits, the seat post and PR objectui#10554 (the origin). seriesTypeArm ⇒ 1 hit, PR objectui#10554.

Dedupe words: ObjectChartSchema series type missing · object-chart series per-series type override · objectql.zod series describe ChartRendererProps arm


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: business reporting | dashboards.chart-type-matrix | P2

    Triage: first grade — priority:p3 · domain:spec · area:reports · pm:queue (finding removed — graded)

    Triage: lands in packages/types (ObjectChartSchema.series in objectql.ts and zod/objectql.zod.ts) — objectui's contract face ⇒ domain:spec; rationale: the published object-chart copy of the series arm lacks the per-series type the renderer's arm declares, and its .describe claims to be that arm. No producer is named for a per-series type on object-chart, so the answer is not to widen: zero pull ⇒ keep the copy narrower and make the .describe say so (a wording fix, no accept-set change) ⇒ p3.

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01CRZSc7dU8oDStbTbSwhuZe · 2026-09-25T12:01Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card and its full thread, and objectui origin/main.

    Execution note: rewrite the .describe to state the copy omits type; widening it needs a named producer first (then Clause-②: yes, minor). Serial after objectui#10518 (PR objectui#10601), which edits the same two files.

  2. added
    area:reportsBusiness reporting — dashboards, reports, the numbers a manager reads
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    and removed on Sep 25, 2026
  3. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 — objectui#10584: the ObjectChartSchema.series copy keeps its narrower arm (no per-series type), and its .describe and docblock say so truthfully
    Session: session_014fWVhLzhxR8qrFsJ5o8TYW
    Account: os-tesla
    Branch: claude/issue-10584-object-chart-series-describe
    Worktree: objectui-issue-10584
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/types/src/zod/objectql.zod.ts (the ObjectChartSchema.series .describe) and packages/types/src/objectql.ts (the series member docblock), within the ObjectChartSchema block only, plus a pin if the wording is pinned, and one .changeset/10584-…md (patch: wording, with no accept-set change). ⛔ The arm's shape does not change: widening it needs a named producer first (triage). Stop on breach; explain in the report.
    Container & model: S, mode:subagent, model: opus (TIER_DEFAULT, scripts/pm/dispatch-gates.mjs:12534 on objectstack 16c5a33; --tier refuses objectui paths)
    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.
    Thread-read: 5832033521
    Serial constraints cleared: re-measured on objectui origin/main after PR objectui#10734 (objectui#10608) merged at 05:20Z. That was this card's serial predecessor on the ObjectChartSchema block, so the constraint is cleared. Of the open PRs, only PR objectui#8941 touches objectql.ts, with one docblock line at @@ -525 (BulkActionDef), which is disjoint. No live pm:dispatched claim names this block.

    domain:spec#1 · session_014fWVhLzhxR8qrFsJ5o8TYW · claim · 2026-09-27T07:32Z


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 10584,
    "status": "done",
    "branch": "claude/issue-10584-object-chart-series-describe",
    "pr": "#10768",
    "session": "session_014fWVhLzhxR8qrFsJ5o8TYW — the Claude-Session line stamped into this run (mode:subagent, so it is the parent PM seat session)",
    "premise_still_valid": true,
    "summary": "The zod .describe() on ObjectChartSchema.series no longer calls the element "the arm ChartRendererProps declares". It now says the copy is that { dataKey } arm minus the per-series type the arm gained under objectui#8086, which this copy does not declare, and that this copy's per-series family override is chartType (bar | line | area). The TS docblock replaces "this copy has not taken up" with a deliberate omission: widening waits for a named producer. It also records what a type written anyway meets on each face: TS2353 on the TS face, a silent strip on the zod face. Added one patch changeset for @object-ui/types. No member, type or accept set moved: the zod parse results are identical on the base and head builds, and the non-comment lines of objectql.d.ts are byte-identical. H1 holds; H2 holds (PR #10734 and PR #10601 are both on main); H3: no pin asserts the string. Stop condition not met, each reading with a control. No producer writes a per-series type on an object-chart node: the five objectui relays write { dataKey, label }, the objectstack showcase writes no series or the { name, label } arm, and hotcrm has zero object-chart. Recorded, not acted on: the spec's ObjectChart react block (schemaType object-chart, schema ChartConfigSchema, series in dataProps) does declare a per-series type, but on the { name } arm. The spec refuses dataKey by name, so { dataKey, type } is not spec-authorable on object-chart either. Separately, the published copy refuses the { name } arm node the showcase produces through that block: see out_of_scope_findings.",
    "tests": {
    "head": "5dc9a71e02 (every gate below ran after this commit on a clean tree; nothing was pushed after the runs)",
    "gates": [
    "pnpm --filter @object-ui/types build (os-verify-lock) → VERDICT command-exit 0; pnpm --filter \"@object-ui/types^...\" build → ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT (empty dependency closure: deps are @objectstack/spec and zod only)",
    "pnpm --filter @object-ui/types type-check (os-verify-lock) → VERDICT command-exit 0; the output echoes the script name type-check",
    "pnpm exec vitest run --maxWorkers=2 packages/types/ (os-verify-lock) → VERDICT command-exit 0; Test Files 245 passed (245), Tests 5327 passed (5327)",
    "pnpm exec vitest run --maxWorkers=2 packages/plugin-charts/ (os-verify-lock) → VERDICT command-exit 0; Test Files 82 passed (82), Tests 964 passed (964). Direction: the downstream consumer of @object-ui/types that the dispatch named; no fixture reads the describe string",
    "pnpm exec vitest run --maxWorkers=2 with the 15 out-of-package tests that parse objectql.ts / objectql.zod.ts from disk (app-shell relayRungCensus-7559 and chartConfigForward-7891; plugin-grid x2; plugin-kanban 7804; plugin-tree 8655; react 9357; eight scripts/tests suites) (os-verify-lock) → VERDICT command-exit 0; Test Files 15 passed (15), Tests 602 passed (602)",
    "pnpm exec eslint --no-inline-config --format json on packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts → exit 0; 2 files linted, 0 errors, 35 warnings (all @typescript-eslint/no-explicit-any, 0 on an edited line). Population: eslint --print-config exits 0 for both files. Invariance: eslint.config.js has 0 matches for parserOptions/project/projectService/TypeChecked (control: languageOptions has 1 match), so no type-aware rule can move an untouched file",
    "node scripts/check-changeset-presence.mjs → exit 0",
    "node scripts/check-changeset-no-major.mjs → exit 0",
    "pnpm check:new-line-citations → exit 0 (VERDICT new-cross-file-line-citations: 0 new citation(s))",
    "pnpm check:control-bytes → exit 0; own scan grep -naP over the 3 changed files and the PR body → exit 1 (no match)",
    "pnpm check:spec-symbols → exit 0",
    "pnpm check:test-path-roots → exit 0",
    "pnpm check:changeset-claims → exit 0 (report-only). The pending .changeset/8086-chart-series-type-arm.md sentence "that copy of the internal arm does not carry type, and its type is unchanged" was re-read and is still true",
    "pnpm check:component-surface-parity → exit 0; check:designer-field-key-parity → exit 0; check:doc-types → exit 0; check:installed-pin-claims → exit 0; check:handler-key-reads → exit 0; check:action-forward-parity → exit 0",
    "node scripts/check-governed-queue-guard.mjs --test (the 3 paths) → exit 0, NOT GOVERNED",
    "NOT MEASURED: pnpm check:doc-examples → exit 2, PREREQUISITE NOT MET (needs the dist of about 30 workspace packages; CI builds them). This diff adds 0 lines matching @example or a fence, so the gate population is unchanged",
    "NOT RUN: Spec Main Shape Gate (spec-main-shape-gate.mjs inject). The touched member is not spec-derived (a local copy of the ChartRendererProps arm; it binds no @objectstack/spec symbol), and the non-comment lines of objectql.d.ts are byte-identical between the base and head builds",
    "measurement (not a gate): the @object-ui/types/zod dist safeParse of series [{dataKey, type:"line"}] → success, parsed [{"dataKey":"margin"}] on both base and head; {dataKey, chartType} keeps chartType on both; {label} alone → invalid_type@series.0.dataKey. tsc --strict on a literal typed ObjectChartSchema: {dataKey, type} → TS2353; {dataKey, chartType} compiles"
    ],
    "line_budget": "n/a: no skills/, .claude/ or line-ratcheted ledger touched",
    "deviations": [
    "Closure build narrowed for plugin-charts: the root vitest.config.mts aliases @object-ui/* to packages/*/src, so a dist build of the plugin-charts dependency closure is not read by the vitest run and was not done. The @object-ui/types closure is empty.",
    "The dispatch common head prescribes a line-start Clause-②: yes, and the card section overrides it to no. The PR body carries the claim comment's Clause-②: no. line verbatim.",
    "PR body footer: used the agent file's session-URL form, not the harness attribution block (which contains an emoji), per the agent file's precedence clause.",
    "Labels: zero label writes. objectui has no gate that reads a dev-set label, and the dispatch named none. package: types on the PR was set by labeler.yml, not by this run.",
    "dist diff: zod/objectql.zod.d.ts and zod/index.zod.d.ts differ between the base and head builds only in union-member emission order on members this PR does not touch (the first build was fresh, the second incremental). Sorted, the only residue is that ordering.",
    "The hotcrm shallow clone was left at /home/user/objectstack-ai/hotcrm and not deleted, because add_repo points concurrent sessions at that same path."
    ],
    "files_changed": [
    ".changeset/10584-object-chart-series-describe.md +19 -0",
    "packages/types/src/objectql.ts +16 -3 (ObjectChartSchema.series docblock only)",
    "packages/types/src/zod/objectql.zod.ts +8 -1 (a comment above series, and the series .describe() string)"
    ]
    },
    "mcp_calls": "1: mcp__Claude_Code_Remote__add_repo (objectstack-ai/hotcrm, access read, answered read_available, nothing attached). 0 GitHub MCP tools, 0 MCP write tools.",
    "api_writes": "3 REST writes, each as one fleet-write relay stroke (each stroke is one POST /repos/objectstack-ai/objectstack/dispatches): (1) POST /repos/objectstack-ai/objectui/pulls (pr_create, draft, PR #10768, relay run 36314781801); (2) POST /repos//issues/10768/assignees (os-tesla, via label-write, relay run 36314822081, read back MATCHES); (3) POST /repos//issues/10584/comments (this os-dev-report, via post-stamped). Also 2 git pushes (not REST): the empty-branch probe and 5dc9a71.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: b · reach: named producer: objectstack examples/app-showcase renewals-pipeline page (at objectstack 16c5a33) writes ObjectChart objectName=showcase_invoice type=bar ... series={[{ name: 'total', label: 'Invoice value' }]} through the react tier, which the objectui react-page wrapper turns into an object-chart node { specType: bar, series: [{ name, label }] }. The published @object-ui/types/zod ObjectChartSchema.safeParse of that node → invalid_value@chartType, invalid_type@series.0.dataKey. The TS face likewise requires chartType and series[].dataKey. The member docblock says series is INTERNAL (relay-composed) and "All five producers compose it from something else", which misses this author-facing channel · contract: the spec react-blocks ObjectChart entry has schemaType: 'object-chart' and schema: ChartConfigSchema, with the comment "The spec ChartConfig shape IS the author contract again"; its dataProps include 'type' and 'series'; ChartSeriesSchema has name required and type "Override chart type for this series" · Seam: spec:react-blocks ObjectChart.dataProps series/type (ChartConfigSchema) → renderer:plugin-charts ObjectChart + normalizeChartSchema (draws it); objectui types face ObjectChartSchema.series/chartType refuses it · family: the same as objectui#10518 / objectui#10608 (the object-chart copy against the spec ChartConfig contract). Route it to that family's closure card rather than a single-point card; widening is Clause-② yes · dedupe words: ObjectChartSchema series name arm react ObjectChart · object-chart chartType required specType react tier · ObjectChart dataProps series ChartSeriesSchema objectui types",
    "carrier: 承接者:无 · noted, not filed. app-shell ObjectView forwards viewDef.chart.series verbatim onto the object-chart node, and designer.ts declares chart.series as any[]. The spec ListChartConfigSchema is a strictObject with no series member, so a conforming stored list view never carries one (dormant read, zero pull). In PR Acceptance notes context only."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: objectui#10584 is delivered by PR objectui#10768 at head 5dc9a71e02. domain:spec @ objectui seat, session session_014fWVhLzhxR8qrFsJ5o8TYW, 2026-09-27T13:24Z.

    Implemented-by: claude/issue-10584-object-chart-series-describe
    Reviewed-by: session_01AsCNgFBs8HCjwhyHQsFbx3

    Checklist, read on GitHub, not off the report

    • The PR is a draft against main. Its first line is Fixes #10584, it has the line-start Clause-②: no., and no other closing keyword appears. The PR's assignee is os-tesla.
    • 3 files, all inside claim 5853837562: the changeset, the ObjectChartSchema.series docblock in objectql.ts, and the .describe() with its comment in objectql.zod.ts. No member, type or accept set moves.
    • Contract review: the at-tier record 5856242218 at this exact head says PASS. The director seat rendered it at tier, which discharges the seat's ABSENT note 5855350526. The seat spot-checked its load-bearing claim on the head tree: normalizeChartSchema.ts:403 reads str(raw.chartType) ?? str(raw.type), so chartType wins.
    • CI at this head: 40 check runs success and 3 skipped (the expected dependabot and coverage rows). Every required context is green, and mergeable_state is clean.
    • Not governed: the three paths sit outside AGENTS.md, CLAUDE.md, .claude/**, skills/** and docs/adr/**.

    Acceptance notes (noted, filed where owed)

    • The dev's out-of-scope finding with a named producer is filed as objectui#10770. It is not graded and not routed.
    • The dev's carrier: none note stays in the PR body: the app-shell viewDef.chart.series forward is a dormant read with zero pull.

    Landing: needs:contract-review comes off, then pr_ready + automerge_enable go through the relay, under the maintainer's authorization in this seat's session (「授权本席落地:」 / 「我给你权限了」). The seat follows the PR to MERGED.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions