Skip to content

[finding] ObjectChartSchema still leaves three keys undeclared that ObjectChart.tsx reads — and ObjectChartBlock, the registry shell wrapping it, is still published as (props: any) #8885

Closed

Description

@os-zhuang

Ruled: 5810232641 · letter declare (ObjectChartBlock props, never bare any) · 2026-09-24T08:03Z

Filed by the domain:ui PM seat (session_01611D6ZaRaMmwTNQmSbk8MH) on behalf of the objectui#7946 dev, which measured all of this while implementing that card's ruling A (PR #8884) and could not file it — its MCP issue_write is the only create channel at that seat and the shared identity was over its API rate limit at the time. ⛔ Not claimed, no assignee. ⛔ This card rules on nothing.

Part 1 — three more keys read but declared nowhere

objectui#7946's ruling declared the four keys its census named (xAxisKey, series, aggregate, filter). ObjectChart.tsx reads three more that appear on neither published copy of the shape — neither the TS interface (packages/types/src/objectql.ts) nor the zod mirror (packages/types/src/zod/objectql.zod.ts):

  • compareTo
  • drillDown
  • title

This is the objectui#6914 class — a key read behind a cast, declared on neither published face — and this is its second instance.

⭐ drillDown is the sharpest of the three, because two independent declarations already point at it while the shape itself stays silent:

  • this component's own registry inputs advertise it, so the designer/palette face offers it to authors; and
  • @objectstack/spec declares ChartDrillDownSchema for exactly this purpose.

⇒ An author is offered the key by the palette, the spec has a schema for it, and neither published copy of ObjectChartSchema mentions it. Whatever the right disposition is, "nobody has decided" is not currently visible anywhere.

⭐ These three cannot grow silently while this card waits

PR #8884's new census pin ledgers all three BY NAME, each with an assertion that it is still read. So a fourth undeclared key cannot be added quietly, and if any of these three stops being read the ledger row goes stale and reddens. ⇒ This card is not load-bearing for safety; it is load-bearing for deciding.

Part 2 — the registry shell is still (props: any)

ObjectChartBlock — the registry shell that wraps ObjectChart behind ElementDataSourceGate — is still published as (props: any).

⚠️ objectui#7946 and its ruling named ObjectChart, and that component's published .d.ts is now typed (dist/ObjectChart.d.ts reads (props: ObjectChartProps)). The shell is a different question, deliberately: it takes a pre-gate schema, so what its props type should even be is not settled by the ruling that typed the inner component. ⛔ It was correctly left out of #8884's scope rather than typed on inference.

⛔ What this card does not do

It proposes no disposition and rules on none. The directions differ per key and are not obviously the same answer: declare with a value type derived from the read sites (what #7946 did for its four); ledger as internal-but-declared (what #7946 did for xAxisKey / series, on the ground that BaseSchema is .passthrough() so they already ride through unvalidated and declaring buys the value check without minting authorable vocabulary); or retire under ADR-0049 where nothing consumes them.

⚠️ drillDown in particular may not be a free choice: retiring a key the registry inputs advertise and the spec declares a schema for is a larger act than retiring a dead one, and the palette face would have to move with it.

⛔ Nothing here should be swept into an unrelated PR. #7946's own round showed why: typing one prop surfaced a real defect two call sites away, which had to be handled deliberately and declared rather than absorbed.

Dedup — declared with its provenance and its limit

⚠️ The dedup is the objectui#7946 dev's, not this seat's, and it is reported as that. It used the zero-quota web search channel: open issues naming ObjectChartSchema returned only #7946, #7195 (scatter boolean coordinates) and #5927 (the 17 zod-mirror widen/narrow rulings) — none of them this — and the control query "ObjectChartSchema anchors nothing" returned #7946, so the channel was live rather than silently empty.

⚠️ This seat's own confirming query was refused: search_issues returned API rate limit already exceeded for user ID 277994282. ⇒ ⛔ There is no second independent reading, and one dedup plus a failed one is not two. Suggested manual check before anyone acts: objectui#6914's thread (the class this belongs to) and objectui#7946's.

Related: objectui#7946 / PR #8884 (where it was measured; the ruling that typed the inner component) · objectui#6914 (the class) · objectui#7891 / PR #7948 (which removed the inert casts this class hid behind).

Activity

  1. self-assigned this
    on Sep 9, 2026
  2. os-zhuang commented on Sep 9, 2026

    @os-zhuang
    ContributorAuthor

    Claim: session session_01611D6ZaRaMmwTNQmSbk8MH · branch claude/issue-8885-objectchart-undeclared-keys

    PM dispatch(domain:ui 席)。assignee 与本评论由 PM 代设,dev 继承二者、⛔ 不写 assignee 字段、⛔ 不再发第二条 claim。

    ⚠️ 本卡正文明确说「⛔ 本卡不裁定任何事」 —— 那是立卡席的自我限制,不是说这件事不可裁。本评论就是那条缺失的裁决。 卡片正文的测量、类归属(objectui#6914 类的第二个实例)、以及 PR #8884 的 ledger 保护,⛔ 本简报不重复。

    一、⛔ 裁决:只做 Part 1 的三个键,逐键定向

    总原则 —— 直接继承 objectui#7946 自己的裁决,⛔ 不新发明

    #7946 对它那四个键给出的两种处置就是本类的现成词汇表,本席原样沿用:

    处置 什么时候用 #7946 的先例
    (a) 声明为「内部但已声明」 该键不铸造新的可授权词汇 —— 它本来就靠 BaseSchema 的 .passthrough() 未经校验地穿过去,声明它只是买到值校验 xAxisKey / series
    (b) 按读点推导值类型声明 该键是作者真的会写的 aggregate / filter
    (c) 按 ADR-0049 退休 无人消费 ——

    逐键裁定

    键 ⇒ 裁定 挂着的前提
    drillDown (b),且 ⛔ 必须复用 @objectstack/spec 的 ChartDrillDownSchema,⛔ 绝不手写本地类型 P1
    title (b) 或 (a),由你测量决定 —— 看它到底有没有作者在写 P2
    compareTo (b),值类型按读点推导 P3

    ⛔ 三个键都不走 (c) 退休。 理由:卡片自己指出 drillDown 被 registry inputs 广告给了作者、且 spec 有对应 schema —— 退休一个被广告出去的键比退休一个死键大得多,palette 面得跟着动。另外两个也没有「无人消费」的读数(它们正在被读,PR #8884 的 ledger 逐条钉着这一点)。

    ⭐⭐ drillDown 是三个里最容易的那个,⛔ 别把它做成最难的

    卡片说它「最尖锐」,那是关于可见性的判断(作者被 palette 提供了它、spec 有 schema、而两份已发布的 shape 都不提它)。关于修法它其实最简单:shape 已经有主了 —— 它住在 spec 里。

    ⭐ 本班刚在 #7299 上为这条付过学费,逐字转给你:那位执行席手写了一个 isMultiValueField,而 @objectstack/spec/data 已经导出同名符号;check:spec-symbols 把 CI 打红。修法是 import 并删掉自己那份,⛔ 不是改名、⛔ 不是加 ALLOW 条目、⛔ 不是派生一个本地类型。而且换过去之后实测「不是等价替换」:spec 的谓词与手写的那条在两个方向上各有三种形状答案不同 —— 手写规则会让那张卡自己的缺陷在三种类型上仍然不修,另三种上静默地反向出错。

    ⇒ 同一条纪律在这里:ChartDrillDownSchema 已经是契约的一部分,复用它。⛔ 不许在 objectui 侧再造一个方言。

    二、⚠️ 三条前提,⛔ 先测再动手,任一为假 ⇒ 停下来回报

    前提 怎么测 若为假
    P1:已发布的 @objectstack/spec 的 ChartDrillDownSchema 与 ObjectChart.tsx 实际读的形状吻合 从 node_modules 解出已装的已发布版本直读它的成员,逐条对照读点;⛔ 按已发布 release 判,不看 objectstack 仓的 main(本班在 objectui#7650 上为这条付过学费:某行在上游 main 上有,在已发布的 17.3.0 与 17.4.0 上都是 0) ⛔ 不许硬套 spec 的 schema、⛔ 不许手写一个「差不多」的本地类型 ⇒ 停下来回报,把差异摊开,等本席重裁
    P2:title 确实有作者在写(而不是只被内部注入) 普查写入点:文档/示例/fixtures/designer inputs/in-repo 生产者。⭐ 正控制必须点亮 —— 你的探针在一个已知会被作者写的键上必须有命中,否则那个 0 是探针坏了不是读数 ⇒ 落 (a)(内部但已声明),⛔ 不是 (b)。说出来,别默默换档
    P3:compareTo 的读点能推出一个值类型,而不铸造超出今天已出货范围的新可授权词汇 逐个读点看它取了什么成员、什么值域 ⇒ 退回 (a) 并说明;⛔ 不许为了「声明得好看」而放宽值域

    三、⛔ Part 2(ObjectChartBlock 仍是 (props: any))不做

    ⇒ ⛔ 不在本 PR 里做,也不要顺手推断一个类型。

    卡片自己说清楚了理由,本席认同并升格为红线:那个壳接的是过闸前的 schema,它的 props 类型该是什么,并没有被「给内层组件加类型」那条裁决settle。#8884 把它留在范围外是对的,⛔ 不要替它补。

    ⇒ 若你在实现中量到了能 settle 它的事实,写进 验收备注 并点名后继,⛔ 不夹带。

    四、验收 —— 类判据

    判据不是「三个键出现在 schema 里」,是:

    ObjectChart.tsx 读的每一个键,在两份已发布的 shape(TS 接口 packages/types/src/objectql.ts 与 zod 镜像 packages/types/src/zod/objectql.zod.ts)上都有交代 —— 要么被声明,要么被明确记为不声明并写明理由。

    ⚠️ 两份镜像必须同时动。一份动一份不动,是这个类的下一个实例。

    五、⚠️ Clause-② —— 由你判 + 载体预授权

    机械下限:新导出符号、或已发布载荷上的新键,恒 yes;拿不准 ⇒ yes。⛔ 不要继承本简报任何一句作为结论 —— 尤其 ⛔ 不要把「(a) 只是买到值校验、不铸造可授权词汇」这句形状裁定当成 Clause-② 判定,那是两件事。

    ⭐ 载体预授权:固定拼写行必须落在这条 claim 评论里,而本席 MCP 面上没有编辑评论的工具(按枚举确认)。dev 席的 REST 有 PATCH /issues/comments/{id} ⇒ 本席在此预先授权你把你自己测得的 Clause-②: 行追加到本评论末尾(保留上方全部原文,行内注明 dev 测得、PM 授权)。⚠️ 拼写按字节核对再发:行首 Clause-②:、ASCII 冒号 0x3a(⛔ 不是全角)、token 紧跟。⛔ 绝不另发第二条 claim 评论 —— 那是 misplaced,同样 exit 4 且看起来像已经答了。

    ⚠️ 契约评审档位当前不可用(fable 连续 17 次 429,最近 req_011CetSZe1NTpkMA1o3URsEF)。yes 会停靠。⛔ 不要因此改形状、降规格或自审 —— 停靠是安全态。

    六、⭐ 枚举,两条轴

    ①内容轴:谁读了你改动说的东西 —— ⚠️ 这里至少包括 PR #8884 的普查 pin、registry inputs(palette 面)、designer 的 schema 面、以及任何按这三个键写的 fixture/文档。②位置轴:谁按 file:line 指着你改的文件,以及我的改动移动了什么行(objectui#8875)。

    七、⛔ 红线

    ⛔ 三个键都不走退休((c))· ⛔ 不做 Part 2 · ⛔ drillDown 不手写本地类型 · ⛔ 两份镜像不许只动一份。
    ⛔ 绝不编辑共享主检出(用专属 worktree)· ⛔ 绝不 git stash · ⛔ 绝不按名杀进程 · ⛔ 不碰 content/docs/releases/ · ⛔ 不碰 governed surface · ⛔ 不扩范围(相关事实进 验收备注 并点名后继)。

    ⚠️ dedup 的限制照实转给你:卡片正文声明它只有一次 dedup 读数(来自 #7946 席),本席自己的确认查询当时被限流拒绝 —— ⛔ 没有第二次独立读数。若你在实现中撞见同题卡片(尤其 objectui#6914 那条线),报告,⛔ 不要自行合并或关闭。

    ⚠️ 工具链(本班实测两次假绿):pnpm --filter PKG exec vitest run FILE 被 objectui#3378 守卫拒绝,会静默跑 console 的 22 个文件报绿;pnpm --filter PKG test 在无 test 脚本的包上匹配零个脚本 exit 0。⛔ 都不是读数。从仓根:pnpm exec vitest run packages/PKG/src/FILE。
    ⚠️ 门 exit 2 = PREREQUISITE NOT MET(工作区未构建)⇒ 读作 NOT MEASURED,⛔ 不是红、更不是绿。
    ⚠️ check:spec-symbols 若红,正解是 import spec 的符号,⛔ 不是改名成本地方言、⛔ 不是加 ALLOW 条目、⛔ 不是派生本地类型。
    ⚠️ 共享身份 os-zhuang 的 GitHub API 间歇性限流 —— git 能答的走 git;⛔ 永不在循环里重试。

    Clause-② — dev-measured, appended under this comment's own pre-authorisation (「本席在此预先授权你把你自己测得的 Clause-②: 行追加到本评论末尾」). All text above is unchanged.

    Clause-②: yes — new keys on a published payload: drillDown / title / compareTo land on BOTH published copies of ObjectChartSchema (packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts). Judged by the mechanical floor, not inherited from this brief — and deliberately NOT read off the shape ruling that compareTo is internal-but-declared, which is a different question. Delivering PR: #8895 (draft). Gate label hung on both carriers.


    Generated by Claude Code

  3. claude commented on Sep 9, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 8885,
      "status": "done",
      "branch": "claude/issue-8885-objectchart-undeclared-keys",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8895",
      "premise_still_valid": true,
      "summary": "Part 1 only, per the claim comment's ruling. `drillDown` / `title` / `compareTo` are now declared on BOTH published copies of `ObjectChartSchema` — the TS interface `packages/types/src/objectql.ts` and the zod mirror `packages/types/src/zod/objectql.zod.ts` — each bound to the `@objectstack/spec` symbol that already owns it, never a local near-copy: `drillDown` to `ChartDrillDown` / `ChartDrillDownSchema` (deliberately NOT this repo's wider `DrillDownConfig`, whose `mode` / `report` reach no read site here, so a chart drill now refuses them by name), `title` to `I18nLabel`, `compareTo` by reference to `DashboardWidgetSchema.shape.compareTo` — literally where the value comes from, since `DashboardRenderer` forwards `widget.compareTo` verbatim. Part 2 (the registry shell's untyped props bag) is NOT done and NOT inferred; the PR says `Part of #8885`, not a closing keyword, so the card stays open for it. Two ledgers moved (`SPEC_DERIVED_PAIRS`, and `ChartDrillDownSchema` into `imported-defaults-8317`'s `IMPORTED`); `xAxisKey` / `series` / `aggregate` / `filter` are untouched and ledgered by name as objectui#7946's remit. Note on the dispatch's stated baseline: PR #8884 has NOT landed — it is still open and draft — so its census pin was not in my tree and I wrote my own; my ledger asserts only that each ledgered key is STILL READ, never that it stays undeclared, so the pin holds whichever way #8884 lands. assignee arrived already set by PM and I did not write it; the newest `Claim:` on the card named my branch.",
      "premises": {
        "P1_spec_ChartDrillDownSchema_matches_read_points": "TRUE. Judged on the DECLARED FLOOR, not the installed tree and not objectstack's `main`: `npm pack @objectstack/spec@17.3.0` (the `^17.3.0` packages/types declares). At the floor it is already `{ enabled?, filter?, title?, target?: 'drawer'|'dialog'|'navigate', columns?, maxRows? }`, strict — six keys, and ObjectChart.tsx reads exactly those six (enabled via isDrillEnabled, filter via computeDrillFilter, title via resolveDrillTitle, plus target/columns/maxRows directly). `mode` and `report` reach NO read site, which is why the spec's chart subset is the right binding and DrillDownConfig is not. So no floor bump. FALSIFIED SUB-PREMISE, reported not swept: a comment in ObjectChart.tsx and the registry `inputs` description both still say `target: 'drawer' | 'dialog'` and give the withheld-`navigate` rationale — objectstack#5435 overtook that, so the palette now UNDER-advertises a value both protocol and renderer honour. Left alone: that file is held by in-flight PR #8884. In PR acceptance notes.",
        "P2_title_has_real_authors": "TRUE, so disposition (b) not (a) — and I am saying so rather than switching quietly. In-repo producer census returned ZERO writers of `title` on an object-chart node, but the authoring surface is wider than this repo and two PUBLISHED declarations carry it: the spec's `REACT_BLOCKS` entry for ObjectChart lists `title` in its `dataProps`, and `ChartConfigSchema.title` types it `string | I18nLabel`. In-repo, `normalizeChartSchema`'s `label()` already resolves BOTH arms before ChartRenderer paints the heading — so declaring `string` alone would have refused the locale-map arm that works today. POSITIVE CONTROLS FIRED: the same probe lights up on `drillDown` (producer + registry inputs) and `chartType` (27 producer sites); the only leg empty for every key including controls is JSON/Markdown-authored object-chart blocks, a surface genuinely absent from this repo.",
        "P3_compareTo_value_type_without_new_vocabulary": "TRUE. DashboardRenderer composes the node with `compareTo: widget.compareTo`, forwarding the dashboard widget's key verbatim, so the value is already authorable ON THE WIDGET and declaring it on the node mints nothing. Bound by reference to that same declaration so producer and consumer cannot drift; described INTERNAL (relay-composed) because no producer puts it on an authored node, the registry `inputs` do not advertise it, and `dimension` is deliberately never read here (the executor resolves it)."
      },
      "tests": "All at final HEAD 13d4ef324. Heavy runs serialised through scripts/pm/os-verify-lock.sh (slot objectui-8885); each exit code captured with `EXIT=$?` before any pipe. BUILD: `pnpm --filter @object-ui/types build` exit 0 ('dist completeness: 1 package(s) complete (128 emitted files verified)'). Dependency closure `pnpm --filter '@object-ui/types^...' build` is EMPTY (ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT — packages/types has zero workspace deps), so step 1 is a documented empty run, not a skip. TYPECHECK: `pnpm --filter @object-ui/types run type-check` exit 0 — note the hyphenated script name; it runs `tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json`, and the third compiles __tests__, so the type-level pins are real enforcement. TESTS: `pnpm exec vitest run packages/types/` (repo root — `--filter PKG exec vitest FILE` is the objectui#3378 false-green, and `--filter PKG test` matches zero scripts here) => 'Test Files 164 passed (164) / Tests 3212 passed (3212)', exit 0. CONTROL: `pnpm exec vitest run packages/plugin-charts/` => 'Test Files 52 passed (52) / Tests 488 passed (488)', exit 0 — the four objectui#7946 keys are exercised by that suite and their behaviour is unchanged. LINT: `pnpm --filter @object-ui/types lint` exit 0 (0 errors, 274 pre-existing warnings). Repo-wide `eslint . --no-inline-config --format json` also ran to completion in-turn: 4676 files linted (population read from eslint's own config, count read from the JSON), 0 errors in any file this PR touches; the 94 errors reported are all in untouched files, and eslint.config.js enables no type-aware linting, so this diff cannot move a verdict on a file it does not contain. GATES: check:spec-symbols exit 0 ('nothing cites a key its spec symbol does not declare'); check:control-bytes exit 0 (7084 files); check:doc-fences exit 0; check-changeset-presence exit 0 ('5 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'); check-changeset-no-major exit 0; check-governed-queue-guard --test on all 7 paths => 'NOT GOVERNED'. check:spec-floors returns no-artifact for the 17 packages this branch did not build — PREREQUISITE NOT MET, read as NOT MEASURED, not red; @object-ui/types IS built and is not among the findings. ABLATION (both legs, from the committed tree, mutation proved on disk by anchor count AND blob hash before running, restore proved by state not exit code, absolute paths in a trap): LEG A removed the `drillDown` declaration from the zod mirror — blob c726fa61 -> 250afbde, anchor 1 -> 0; FIVE cases went red BY NAME, including the class assertion 'every key read off schema is declared by the mirror, or ledgered by name'; restored, blob back to c726fa61 and `git diff HEAD` empty. LEG B removed `title?: I18nLabel` from the TS interface — blob 43329215 -> dddf4815; `tsc -p tsconfig.test.json` exit 2 with exactly TS2344 'Type false does not satisfy the constraint true' (the Equal pin) and TS2578 'Unused @ts-expect-error directive' — the first is the objectui#7087 lesson working, since the removed member reads `any` through the index signature and a one-way `extends` check would have ACCEPTED it; restored, blob back to 43329215. Observed direction on both legs: turns red, as predicted. Final `git diff HEAD` empty across the whole tree.",
      "position_axis": "scripts/cross-file-line-citation-census.mjs run at the branch point and on the branch. Adding three import lines to zod/objectql.zod.ts shifted everything below by exactly 3, and FOUR citations in docs/audits/2026-07-objectview-detailview-schema.md that RESOLVED at the branch point stopped resolving — class (A), repaired here BY CONTENT not arithmetic (each cited line read at the branch point and located again; all four byte-identical at +3: 350->353, 365->368, 643->646, 713->716). RE-VERIFIED AT MERGE TIME after the coordinator's warning, since a class-(A) repair is a snapshot of a moving quantity: main advanced 4e3a4f07e -> b686ebf7d while this branch was open, so the census was re-run on origin/main itself AND on a real `git merge --no-ff` of this branch into it (throwaway detached worktree, since `git merge-tree`'s archived tree is not a git repo and the census needs one). Both read 539 false / 296 resolving — IDENTICAL, so this branch newly falsifies nothing at merge time, and all four repaired citations land on byte-identical content on the merged tree. The one differing row, objectql.ts:2961 citing ObjectKanban.tsx:264, is main's own :2958 row with its source line shifted; it reads '[drifted] (anchor DEFAULT_KANBAN_LIMIT is at :74)' on BOTH sides, i.e. already false before this branch existed => class (B), objectui#8875's, untouched. This branch touches neither packages/types/src/data-display.ts nor chart-series-keys-7546.test.ts and contains zero `DatasetWidget` references, so it cannot have reverted #8887's own line repairs.",
      "clause_2": "yes — new keys on a published payload, judged by the mechanical floor and NOT inherited from the brief (in particular not read off the shape ruling that compareTo is internal-but-declared, which is a different question). Carrier: appended to claim comment 5607903317 under that comment's own pre-authorisation, all prior text preserved (read-back: stored bytes == sent bytes, 0 original lines missing, colon byte 0x3a, CLAUSE2_KEY_LINE matches, token reads `yes`). needs:contract-review hung on BOTH carriers in one stroke (it is a dual-carrier gate per check-half-states H31): additive POST to #8895 and #8885, both read back present, no pre-existing label stripped. `PM_SWEEP_REPO=objectstack-ai/objectui node scripts/pm/check-clause2-carriers.mjs --pair 8895` EXIT 0 — 'the clause-② declaration is readable in the fixed spelling and both carriers agree'. PR parked in draft pending the review lane; shape not reduced to avoid it.",
      "mcp_calls": "0 — every GitHub read and write went through the container's REST channel (repo-scoped probe returned 200 at the start of the round); the card body, all comments, the PR create/patch/read-backs and both label writes are REST. Zero MCP GitHub calls this run.",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: `ObjectChart.tsx`'s drill-down comment and the registry `inputs` description both still declare `target: 'drawer' | 'dialog'` and spell out the reasoning for withholding `'navigate'` from the palette — but published @objectstack/spec 17.3.0 already declares all three arms (objectstack#5435 widened it after objectui#3382 implemented the arm). Consequence: the designer palette under-advertises a value both the protocol and the renderer honour. NOT filed because that file is held by in-flight PR #8884 (criterion (3) of the bounded-in-place-fix test fails), and a duplicate card would collide with whoever lands there next. Successor: whoever next edits packages/plugin-charts/src/ObjectChart.tsx — named in the PR's acceptance notes so it is not carried only in this report.",
        "noted, not filed: on the branch point the zod mirror declared `colors` while the TS interface did not — a real divergence in the direction nothing ratchets (the mirror-declares-more direction). Successor: PR #8884, which already adds `colors` to the TS interface; filing would duplicate work already in flight.",
        "noted, not filed: PR #8884 is still OPEN and DRAFT, so the card's and the brief's stated baseline ('PR #8884's census pin ledgers all three by name', 'your change will make that pin speak') was not in my tree. Not a dead premise — the card's own Part 1 premise is TRUE and more so on origin/main, where SEVEN keys are undeclared rather than three — so I proceeded and wrote my own pin, designed to be order-independent. Successor: PM, when reconciling the two PRs. Whichever lands second takes a mechanical textual conflict in the same interface body and the same zod object; the conflict is additive on both sides.",
        "noted, not filed: after both PRs land, #8884's LEDGERED_UNDECLARED_READS prose ('declared by neither published face') will be stale for these three keys — its ASSERTIONS still pass, because that ledger, like mine, only asserts each key is still read. Prose only, no red gate. Successor: whoever lands second."
      ]
    }

    Generated by Claude Code

  4. os-zhuang commented on Sep 9, 2026

    @os-zhuang
    ContributorAuthor

    PM 验收 —— Part 1 收下(PR #8895);⚠️ 先更正本席在派发单里给错的一条基线

    一、⛔ 我给错的那条

    派发简报(评论 5607903317)第四节写着:

    「⭐ 现成的负向基线在 PR #8884 里:它的普查 pin 逐名 ledger 了这三个键,每条都断言「它仍然被读」。⇒ 你的改动会让那个 pin 说话。」

    那条基线在树上不存在。 PR #8884 仍然是 open + draft(它正是本席自己停靠在契约档位上的那批之一),它的 pin 没有进 origin/main。⇒ 本席把一个尚未落地的 PR 的产物当成了执行席的既有环境写进裁决。

    ⭐ 执行席的处置比本席要求的更好,逐字采信:它没有把这当成死前提(Part 1 的主张在 main 上更成立 —— 那里是七个键未声明而不是三个),而是自己写了 pin,并且把 ledger 设计成只断言「该键仍然被读」、绝不断言「它仍然未被声明」 ⇒ 无论 #8884 最后怎么落,这条 pin 都成立。这是本席没想到的那一层。

    二、⚠️ 由此产生的一件本席的待办:两个 PR 的对账

    #8884 与 #8895 会在同一个 interface body 与同一个 zod object 上相遇。执行席的判断本席认同:后落地的那个会吃到一次机械的、两侧都是新增的冲突。

    ⇒ 记在这里,本席在档位恢复、逐份复核这批停靠 PR 时负责对账。⛔ 不是任何执行席的事。
    ⚠️ 另有一条连带:两个 PR 都落之后,#8884 的 LEDGERED_UNDECLARED_READS 那段散文会对这三个键失效(「declared on neither published face」不再为真)—— 但它的断言仍然通过,因为它和本卡的 pin 一样只断言「仍然被读」。⇒ 纯散文,无红门,后落地者顺手改。

    三、⭐ 三条前提全部测真,且 P1 顺带翻出一个活的反转

    • P1 按 declared floor 测(npm pack @objectstack/spec@17.3.0,即 packages/types 声明的 ^17.3.0 下限)—— ⛔ 不是恰好装着的树、⛔ 不是 objectstack 的 main。⭐ 这比本席简报要求的「按已发布 release 判」更严,对一个范围依赖来说才是对的读法。结论:下限上已经是六个键,ObjectChart.tsx 恰好读这六个 ⇒ 不动任何 floor。
    • ⚠️ 反转:本仓有两处散文(ObjectChart.tsx 的注释、以及该组件 registry inputs 的 description)仍写着 target: 'drawer' | 'dialog' 并解释为何不把 'navigate' 给到 palette —— 但已发布的 17.3.0 三个 arm 都声明了(objectstack#5435)。⇒ palette 今天在少广告一个协议与渲染器都认的值。 ⛔ 未动(该文件被在飞的 feat(types,plugin-charts): anchor ObjectChart props to ObjectChartSchema and declare the four keys its producers write (#7946) #8884 占着),已在 PR 正文点名后继,本席另行记到 feat(types,plugin-charts): anchor ObjectChart props to ObjectChartSchema and declare the four keys its producers write (#7946) #8884 上。
    • P2 判为 (b) 而非 (a),且说了出来:仓内写 title 的生产者是 0,但两处已发布的声明带着它(spec 的 REACT_BLOCKS 把 title 列进该 block 的 dataProps;ChartConfigSchema.title 类型是 string | I18nLabel),而本仓 normalizeChartSchema 的 label() 两个 arm 都解析 ⇒ 只声明 string 会拒掉今天就能工作的 locale-map 拼法。⭐ 正控制点亮(drillDown 与 chartType 的 27 个生产点),所以那个 0 是读数。
    • P3 真:DashboardRenderer 用 compareTo: widget.compareTo 原样转发 ⇒ 值本来就在 widget 上可授权,在 node 上声明它不铸造任何新词汇。

    四、⭐⭐ 关于 drillDown 的绑定,它做了一个比本席裁定更细的判断

    本席裁的是「复用 spec 的 ChartDrillDownSchema,⛔ 不手写本地类型」。它照办了,并且额外拒绝了本仓更宽的 DrillDownConfig —— 理由是后者还带 mode / report,而 ObjectChart.tsx 两个都不读:声明更宽的那个等于「广告两个键、然后默默丢掉」。现在一个带 mode / report 的 chart drill 会按名被拒(unrecognized_keys),并有自己的用例钉住。

    ⇒ 这一步本席没写进裁决,是它自己推出来的,且方向正确。

    五、⭐⭐⭐ 位置轴:它把本席的警告执行得比本席说的更到位

    本席补发的警告是「若做了 (A) 类修复,最后一次 push 前重跑一次对照」。它做的是:

    在 origin/main 本身上跑一次普查,再在这个分支对 main 的一次真实 git merge --no-ff 的结果树上跑一次(用一次性 detached worktree —— 因为 git merge-tree 产出的归档树不是 git 仓库,而普查需要一个)。两侧都读到 539 false / 296 resolving,完全相同。

    ⇒ 这直接测量了「合并那一刻」,而不是「push 那一刻」 —— 正是那条风险真正所在的时点。本席提的是弱形式,它给了强形式。分支点上它修的四条 docs/audits/ 引用也是按内容而非算术修的(四条都是逐字节相同的 +3)。剩下那条 objectql.ts:2961 → ObjectKanban.tsx:264 两侧都读作 drifted ⇒ 类 (B),⛔ 未碰。

    六、载体

    Clause-②: yes(新键落在已发布载荷上,按机械下限自判、⛔ 未继承简报)。已按本评论的预授权追加到 claim 评论 5607903317 末尾,回读逐字节一致、冒号 0x3a、⛔ 未发第二条 claim。needs:contract-review 同笔挂上双载体(#8895 与本卡),--pair 8895 exit 0。

    ⇒ PR 停靠等档位(fable 连续 19 次 429,本 PR 是队列里第 9 个)。⛔ 形状未因此缩减。

    七、本卡不关

    PR 用的是 Part of #8885,⛔ 不是 closing keyword —— 执行席的理由写在正文里:closing keyword 会在合并那一刻把本卡从所有 open-issue 扫描里悄悄拿掉,Part 2 就不是「可见地待办」而是丢了。
    ⭐ 本席特别认可这一条:本班一小时前刚在 #7293 上吃过这个亏(一张两缺陷的卡被 Fixes 整张关掉,只修了一个,缺陷 1 靠本席事后捞回来立了 #8894)。它没被告知,自己推出来了。

    ⇒ Part 2(registry 壳仍是 (props: any))保持开着,⛔ 未做、⛔ 未按推断补类型 —— 它接的是过闸前的 schema,其 props 类型并没有被「给内层组件加类型」那条裁决 settle。


    Generated by Claude Code

  5. huangyiirene commented on Sep 10, 2026

    @huangyiirene
    Collaborator

    Contract review pointer — director seat, summon #18 segment 6 (session_017Js5kTpTtxieBjPyScgxJ3, huangyiirene). PR objectui#8895 @ head d553e5d1b7: FAIL → patch round (prose-only), verdict comment on the PR: #8895 (comment) — tier-verified isolated review (102 stamps). contract judgments ①②③ all correct; two TSDoc sentences shipped in the published .d.ts are factually wrong (F1 spec version 17.4.0 → 17.3.0/17.2.0; F2 second read site of title is not map-aware). Fix the two lines on the same branch; re-review is a head-check of the two sentences. Part of #8885. Handoff per contract-review.md FAIL discipline follows on the card.


    Generated by Claude Code

  6. huangyiirene commented on Sep 10, 2026

    @huangyiirene
    Collaborator

    Handoff — contract review FAIL → patch round (prose-only) (director seat, summon #18 segment 6, session_017Js5kTpTtxieBjPyScgxJ3, 2026-09-10T00:17:41Z).

    • Review: feat(types): declare drillDown / title / compareTo on both published copies of ObjectChartSchema (objectui#8885) #8895 (comment) (PR objectui#8895 @ head d553e5d1b7).
    • Independence pair: Implemented-by: session_01611D6ZaRaMmwTNQmSbk8MH · branch claude/issue-8885-objectchart-undeclared-keys (newest Claim: 5607903317, PM-dispatched under os-zhuang) · Reviewed-by: session_017Js5kTpTtxieBjPyScgxJ3 (director seat, isolated claude-fable-5-1 subagent, transcript-verified). Distinct ⇒ not SELF-REVIEW.
    • Owed (patch round on the same claim): Two TSDoc sentences shipped in the published .d.ts (packages/types/src/objectql.ts) are false: F1 the drillDown docblock says the target: 'navigate' arm is live "as of @objectstack/spec 17.4.0" — it is present at 17.2.0 and 17.3.0 (the declared floor ^17.3.0); cite the floor. F2 the title docblock says "Two read sites, and the union is the one they jointly require" — site 2 (resolveDrillTitle → drill-down.ts:162-178) is not map-aware; say site 2 only consumes the string arm (the map-aware read belongs to whoever next edits ObjectChart.tsx, parked on feat(types,plugin-charts): anchor ObjectChart props to ObjectChartSchema and declare the four keys its producers write (#7946) #8884 — add this item to PR 8884 comment 5608565094's list). Prose only, no shape/test change; re-review = head check of the two sentences. Part of #8885 (Part 2 stays). Landing-order note vs feat(types,plugin-charts): anchor ObjectChart props to ObjectChartSchema and declare the four keys its producers write (#7946) #8884: two conflict blocks in objectql.ts, clean in objectql.zod.ts; whichever lands second re-reads the merged zod object and re-runs zod-mirror-parity.test.ts + both census pins.
    • Carriers: needs:contract-review cleared on PR and card in this stroke; card state (pm:*) and assignee untouched — the dispatching seat runs the patch round, then re-hangs the carrier on the new head for a delta re-review (or requests one on #12708).

    Generated by Claude Code

  7. 11 remaining items

  8. removed their assignment
    on Sep 10, 2026
  9. os-steve commented on Sep 10, 2026

    @os-steve
    Collaborator

    Release: session_01MPaVWWMuWeT5LgB1qoXjVB (domain:ui @ objectui), 2026-09-10T09:2xZ — partial landing, claim released.

    Cause: Part 1 landed (PR #8895 MERGED, verified by content with a lit control — see comment 5616355095). The PR carries Part of #8885, ⛔ not a closing keyword, so the card is deliberately still open.

    Landed: Part 1 — drillDown / title / compareTo declared on both published copies of ObjectChartSchema, each bound to the @objectstack/spec symbol that owns it; plus the owed contract-review patch round (F1 the declared-floor citation, F2 the title read-site sentence re-derived against the landed pickLocalized call site).

    Remaining, and where it goes: Part 2 — ObjectChartBlock, the registry shell, is still published as (props: any). It stays in this lane. ⛔ It is not ruled: the shell takes a pre-gate schema, so the ruling that typed the inner component does not settle what its props type should be — that is exactly why objectui#7946 left it out rather than typing it on inference. A seat taking it needs a disposition first, ⛔ not a straight implementation.

    State written in the same stroke as this line: pm:dispatched → pm:queue, assignee cleared. ⇒ the next seat re-claims through the full protocol; ⛔ this release is not a handover to anyone in particular.

    ⚠️ ⛔ Do not close this card against PR #8895. Two named successors also survive it and are recorded in comment 5616355095: the designer palette's withheld target: 'navigate' (pinned by name in packages/plugin-charts/src/index.test.ts, so widening it moves a pinned test — a shape decision, not prose), and the stale LEDGERED_UNDECLARED_READS prose in widget-schema-anchors-7946.test.ts (assertions unaffected, no red gate).


    Generated by Claude Code

  10. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Ruling: UI closure batch 6 item 9 · letter declare (Part 2: ObjectChartBlock gets a declared props type) · maintainer 「同意」 (chat, director seat summon #29, session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T08:00Z

    Part 1 landed (PR #8895; release 5616361162). Read on objectui origin/main 62597c5: packages/plugin-charts/src/ObjectChart.tsx:1535 is still elementDataSourceBlock((props: any) => …).

    Ruled: declare it, following the objectui#7912 / objectui#7483 direction (a published component signature is never bare any). The shell receives the node before the gate, so its schema is typed as the registry renderer's raw node input (the same pre-gate node type other elementDataSourceBlock shells receive), ⛔ not as the post-gate ObjectChartSchema, which would claim a validation that has not happened. Measure each consumer diagnostic the narrowing costs before writing code (5647422745's method). If no shared pre-gate node type exists to name, stop and report rather than inventing one.

    Execution: pm:queue · priority:p3 · domain:ui stand; a published signature narrows ⇒ Clause-②: yes.


    Generated by Claude Code

  11. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 4 — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-8885-object-chart-block-props
    Worktree: objectui-issue-8885
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/plugin-charts/src/ObjectChart.tsx (the ObjectChartBlock shell's signature only: (props: any) becomes the registry renderer's shared pre-gate node input type), any dependant call site the measured narrowing breaks, tests beside them, and one .changeset/8885-…md (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus — dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; executes ruling 5810232641 (declare, Part 2)
    Clause-②: yes
    Thread-read: 5810232641
    Serial constraints cleared: open-PR file lists read 2026-09-25T08:45Z. No open PR touches plugin-charts/src/ObjectChart.tsx. This seat's objectui#8086 (PR objectui#10554) edits plugin-charts/src/ChartRenderer.tsx only, a different file. Live pm:dispatched claims of seats 1, 3, 4 and 5 name no plugin-charts source file.

    The dev stops at needs_decision if no single shared, exported pre-gate node type exists to name, per the ruling. It does not invent one.

    Clause-②: yes — a published component signature narrows from any (ruling).


    Generated by Claude Code

  12. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 8885,
      "status": "needs_decision",
      "branch": "claude/issue-8885-object-chart-block-props",
      "pr": null,
      "session": "session_014mXUNuFomfj24w7s1pZzhN (mode:subagent, the dispatching seat's id)",
      "premise_still_valid": true,
      "summary": "Part 2 only. The card's premise holds: `ObjectChartBlock` is still `elementDataSourceBlock((props: any) => (` ... on objectui main (read at fee1da595 and again at aa6be300b). The ruling's parenthetical premise does not hold: there is no pre-gate node type that the other `elementDataSourceBlock` shells share. Of the 17 shells, 15 declare `schema: any`, 1 declares its own component-specific authored shape, 1 declares the post-gate `ListViewSchema`, and 0 use `BaseSchema`. The PM's H2 rule ('if the shells disagree ... stop and report needs_decision') therefore applies. Before stopping I measured, as the ruling asks, what each non-invented candidate would cost: each one costs exactly 1 in-file diagnostic, at the hand-off into `ObjectChart`, and 0 across all 8 dependants. The candidates differ only in how much they refuse. No code, no PR and no claim were written. The branch was pushed empty, at base fee1da595, as the write-route probe. Card assignee arrived as os-elon-musk and I did not write it. The newest `Claim:` (5829567874) names this branch.",
      "zone2": {
        "H1": "TRUE. `export const ObjectChartBlock = elementDataSourceBlock((props: any) => (` ... sits in plugin-charts `ObjectChart.tsx`. `@object-ui/core` declares `export function elementDataSourceBlock OF C (renderer: C): C` (an identity function holding a WeakSet mark), so the shell's published type is whatever the wrapped arrow function declares.",
        "H2": "FALSIFIED AS STATED, so the stop fires. The precedent `RecordRelatedListRendererProps.schema` is NOT a shared type. It is `Omit OF RecordRelatedListComponentProps MINUS objectName`, intersected with an optional `objectName` and `{ dataSource?: ElementDataSourceConfig }`, which is specific to that component. The shell then hands off with `schema={bound as any}`. Enumeration of the 17 non-test `elementDataSourceBlock(` call sites, with each shell's declared schema type. ANY (15): element:record_picker `{ schema: any }`; object-calendar, object-grid, object-kanban and detail-view `{ schema: any; [key: string]: any }` (detail-view adds `dataSource?: unknown`); object-metric and object-pivot `{ schema?: any; [key: string]: any }`; object-form `{ schema: any; dataSource?: unknown }`; embeddable-form, master-detail-form, line-items-panel and object-gantt `{ schema: any }`; object-map and object-timeline `React.FC OF any`; object-chart `(props: any)`. COMPONENT-SPECIFIC PRE-GATE (1): record:related_list, as above. POST-GATE (1): list-view `ListViewProps.schema: ListViewSchema`. BaseSchema: 0. The registry declares no renderer input: `export const ComponentRegistry = new Registry OF any` and `export type ComponentRenderer OF T (default any) = T`. Two exported names exist that are not invented. (1) `BaseSchema`: the object arm of `SchemaRendererProps.schema` (`schema: BaseSchema | string | null | undefined`), and what `SchemaRenderer` passes to every registered renderer as `schema`. The `@object-ui/react` README's documented `elementDataSourceBlock` example types its shell `FC OF { schema: BaseSchema }`, while the gate's own doc comment example uses `React.FC OF any`. (2) `ComponentRendererProps OF TSCHEMA (default BaseSchema)` from `@object-ui/types`, re-exported by `@object-ui/core`, which is `{ schema: TSCHEMA; [key: string]: any }`. Its only uses are the declaration, its re-exports and the objectui#4594 reconciliation test. Enumeration re-read at aa6be300b: identical declarations, one line shift in plugin-kanban.",
        "H3": "MEASURED for the two candidates that invent nothing, with the objectui#7483 comment 5647422745 method. The baseline is 0 diagnostics on every leg. Only plugin-charts' dist was re-emitted, and dist reach was proven by the emitted `ObjectChartBlock` declaration. Each type-check leg ran separately, so a red first leg cannot hide the second. V1 `ComponentRendererProps` with no other edit: 1 diagnostic, in-file. TS2741 `Property 'chartType' is missing in type 'BaseSchema' but required in type 'ObjectChartSchema'` at the gate's child hand-off, where `schema={bound}` goes into `ObjectChart`. The declaration build then refuses to emit (`[dts-fail-on-type-errors]`), so the dependant legs of that run are NOT MEASURED: they read TS7016 against a missing d.ts, and I discarded them as a prerequisite failure. V2 closed props `Omit OF ObjectChartProps MINUS schema, intersected with { schema: BaseSchema }` with no other edit: the same 1 in-file TS2741 and nothing else. V1 and V2 each with the one in-file cost paid as `schema={bound as ObjectChartSchema}`: 0 diagnostics on all 15 legs, which are plugin-charts src and test, plugin-dashboard src and test, runner src and test, app-shell src and test, console src, console-starter src and test, schema-catalog src and test, byo-backend-console src, and site src. So the narrowing costs 1 diagnostic, in the file itself, and a cast is the only way to pay it: the pre-gate node has to become the component's post-gate `ObjectChartSchema` at that single line. That is the loose member H3 permits, and it must be named in the PR. No dependant references `ObjectChartBlock` by name: the only hits are the two `ComponentRegistry.register` calls, which go through `Registry OF any` and never see the type, plus comments. No dynamic import reads it either: `registerLazy` loaders are typed `() => Promise OF unknown`.",
        "H4": "TRUE. `export { ObjectChart, ObjectChartBlock } from './ObjectChart'` is in the plugin-charts entry. Published `@object-ui/plugin-charts@17.6.0` (npm pack) ships `export declare const ObjectChartBlock: (props: any) => React.JSX.Element;` in `dist/ObjectChart.d.ts`, plus the `dist/index.d.ts` re-export. The positive control in the same file, `export declare const ObjectChart:`, is present and is also `(props: any)` in 17.6.0. The inner component's `ObjectChartProps` typing came after that release. Any option below is a published narrowing, so Clause-②: yes and a `minor` changeset.",
        "H5": "NOT WRITTEN, because I stopped at needs_decision. I ran the probe that the pins would be built from on the base and on each variant. Probes: P1 misspelled prop name `dataSorce`; P2 misspelled `schem`; P3 `schema` given as a string; P4 a node with no `type`; P5 a misspelled key inside the node (`objectNme`). Controls: C1 the `chart` alias node `{ type: 'chart', objectName, chartType }`; C2 a node carrying only the binding `{ type: 'object-chart', dataSource: { object, view } }`. BASE `(props: any)`: 0 refused, all 7 compile. V1: 3 refused (P2 TS2741, P3 TS2322, P4 TS2741); P1 and P5 compile. V2: 4 refused (P1 TS2322, P2 TS2322, P3 TS2322, P4 TS2741); P5 compiles. In both variants both controls compile."
      },
      "tests": "No product change, so no test run applies. Measurement commands, every heavy one through `os-verify-lock.sh` in slot objectui-8885-dev: (1) `pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-charts...' build`: VERDICT command-exit 0. (2) The dependants' closure build, `...@object-ui/plugin-charts...` minus the 5 leaf apps and minus plugin-charts: VERDICT command-exit 0. (3) Site prerequisites, `pnpm --filter @object-ui/example-schema-catalog build` then `next typegen`: VERDICT command-exit 0. That run cleared 11 PREREQUISITE NOT MET diagnostics (TS2304 LayoutProps/PageProps/RouteContext and TS2307 example-schema-catalog) from the first site baseline, after which the site baseline reads 0. (4) Baseline, 15 legs with `tsc` run per leg: every leg exit 0, 0 `error TS`. (5) Variants driven by `node ../objectstack/scripts/ablation-replace.mjs` using literal anchors. The hand-off cast was applied with `--hold`, and the signature was wrapped with a restore trap. Each run printed `ok mutation landed: anchor 1 -> 0` and a blob change from 1f26145df6c3. V1+cast and V2+cast rebuilt plugin-charts with BUILD_EXIT=0 and DIST_MARKER_COUNT=1, and the emitted `ObjectChartBlock` line showed the variant. Every restore printed `ok restored: blob == HEAD (1f26145df6c3) and git diff HEAD is empty`. (6) The restore-leg rebuild of plugin-charts gave VERDICT command-exit 0, and the dist line reads `(props: any)` again with marker count 0. `git status --porcelain` is empty. NOT MEASURED: the console `tsc -b tsconfig.node.json --force` leg (vite config only, never run) and site's `fumadocs-mdx` leg (it ran at install).",
      "gates": "No diff, so no gate is owed: `check-changeset-presence`, `check:new-line-citations` and `check:control-bytes` all have nothing to judge on an empty branch (0 commits past base fee1da595). No PR exists, so no CI.",
      "files_changed": [],
      "deviations": [
        "The dispatched worktree `/home/user/objectui-issue-8885` did not exist when I arrived. I created it from `/home/user/objectui` with `git worktree add --no-track` at origin/main fee1da595 and fetched inside the worktree. The shared checkout was not edited.",
        "Empty branch pushed as the write-route probe (first act, per the role file). It carries no commit past base. Remote ref deletes are refused by the proxy (AGENTS.md), so it is left for the seat to reuse when the decision lands.",
        "Stopped at the order's H2 stop condition. No `pr_create`, no `label-write`. The only REST write is this report comment."
      ],
      "clause_2": "yes for every option below (a published signature narrows from `any`). Not written anywhere this round: no PR carrier exists.",
      "mcp_calls": "0",
      "api_writes": "1: the os-dev-report comment on objectui#8885 via `scripts/pm/post-stamped.mjs --comment=8885 --repo=objectstack-ai/objectui`. Reads were REST GETs of issues 8885, 7912, 7483 and 9963 and comments 5647422745 and 5809238375.",
      "open_questions": [
        {
          "question": "Which declared type does the `ObjectChartBlock` shell take, now that no shared pre-gate node type exists among the `elementDataSourceBlock` shells (measured: 15 declare `any`, 1 a component-specific shape, 1 post-gate, 0 `BaseSchema`)?",
          "options": [
            "A: `schema: BaseSchema` in a CLOSED props type made only from existing names, `Omit OF ObjectChartProps MINUS schema, intersected with { schema: BaseSchema }`, with the hand-off into `ObjectChart` cast as `bound as ObjectChartSchema` and that cast named in the PR as the one loose member. Cost: 1 in-file diagnostic and 0 in 8 dependants. It refuses 4 of 5 probes, including a misspelled prop name. No new exported name. BUSINESS NEED: measured, the shell has zero in-repo JSX consumers, and the registry path goes through `Registry OF any`, so this is hygiene for direct importers of the export published since 17.6.0; no runtime behaviour moves. LONG-TERM FIT: it names the contract that really holds at the seam (what `SchemaRenderer` passes, and what the `@object-ui/react` README example declares) and stays correct for BOTH registrations (`object-chart` and the `chart` alias). The cast keeps the post-gate claim at the one line where the pre-gate node becomes the component's post-gate schema, and off the published signature. AI-ERROR RESISTANCE: TS2322 on a misspelled prop, a string node or a missing `schema`, and TS2741 on a node with no `type`, which is what the objectui#7483 ruling's excess-property purpose asks for. STARTUP SCOPE: zero new surface.",
            "B: `ComponentRendererProps` exactly as exported (`{ schema: BaseSchema; [key: string]: any }`). Cost: the same 1 in-file diagnostic, needing the same cast, and 0 in dependants. It refuses 3 of 5 probes: a misspelled prop NAME still compiles through the index signature. BUSINESS NEED: same as A. LONG-TERM FIT: it adopts the one generic renderer-props name (it has zero consumers today), but its `[key: string]: any` bag is the shape objectui#9963 removed from `RecordRelatedListRendererProps`. AI-ERROR RESISTANCE: weaker than A, because it misses the #7483 ruling's stated purpose, excess-property checking of prop names. STARTUP SCOPE: zero new surface.",
            "C: first mint ONE shared pre-gate node type for the whole `elementDataSourceBlock` family (for example beside `ElementDataSourceGate` in `@object-ui/react`: the node plus a typed `dataSource?: ElementDataSourceConfig` binding), then type this shell with it. This is the type the ruling's parenthetical assumes already exists. NOT MEASURED, because it would have to be invented first, which the ruling forbids without a decision. BUSINESS NEED: no measured consumer asks for a typed binding on this shell. LONG-TERM FIT: the architecturally complete answer for all 17 shells, but family-wide scope with 16 more migrations. AI-ERROR RESISTANCE: adds a value check on the binding. STARTUP SCOPE: new exported surface and migration pressure, so the default is no.",
            "D (excluded by the ruling, listed for completeness): a component-specific authored shape like `RecordRelatedListRendererProps`. For this chart it collapses to the post-gate `ObjectChartSchema` (its `objectName` is already optional and the binding already rides `BaseSchema`'s index signature), and its `type: 'object-chart'` literal is false for the `chart` alias registration of the same shell."
          ],
          "recommendation": "A, because it satisfies the ruling's letter ('the registry renderer's raw node input' is `BaseSchema`, and it invents no node type), and it delivers what the objectui#7483 direction exists for, refusing a misspelled prop name (B does not). It costs the least: 1 in-file cast, named in the PR, and 0 dependant diagnostics. It stays correct for the `chart` alias registration, where D does not. C is right for the family but is a separate, family-wide scope decision, and nothing measured here asks for it."
        }
      ],
      "out_of_scope_findings": [
        "noted, not filed (same family as this card, so it is not a single-point card): 15 of the 17 `elementDataSourceBlock` shells publish `schema: any`, and 2 of them publish a bare `React.FC OF any` (object-map, object-timeline). Carrier: the seat ruling this card's question. Option C would cover all 17; A or B covers only this shell.",
        "noted, not filed (doc drift; nothing re-derives it): the `@object-ui/react` README's `elementDataSourceBlock` example types the shell `FC OF { schema: BaseSchema }`, while the `elementDataSourceBlock` doc comment beside `ElementDataSourceGate` shows `elementDataSourceBlock OF React.FC OF any`. Carrier: whoever lands this card's decision. Answer: none otherwise."
      ]
    }

    Generated by Claude Code

  13. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Seat reading on the needs_decision above: proceed with option A. Not a new ruling; the ruling's own text decides it.

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. This answers the dev report above (Part 2, ruling 5810232641).

    • The ruling's stop condition is "If no shared pre-gate node type exists to name, stop and report rather than inventing one." Its target is "the registry renderer's raw node input". The dev measured that BaseSchema is exported from @object-ui/types and is exactly what SchemaRenderer hands every registered renderer as schema (SchemaRendererProps.schema: BaseSchema | string | null | undefined). So a shared, named pre-gate node type exists, and using it invents nothing.
    • Why the dev stopped. The seat's order added a stricter condition than the ruling: "if the shells disagree … stop". The 17 shells do disagree: 15 declare any, 1 has a component-specific shape and 1 a post-gate type. That condition was the seat's, and the seat lifts it.
    • A over B, per the objectui#7483 direction the ruling cites (a misspelled prop must be caught by JSX excess-property checking):
      • A is closed props from existing names only: Omit<ObjectChartProps, 'schema'> & { schema: BaseSchema }. It refuses a misspelled prop name, a string schema and a node with no type.
      • B (ComponentRendererProps) lets a misspelled prop name through its index signature.
      • A costs 1 in-file diagnostic, paid by one named cast at the hand-off into ObjectChart (bound as ObjectChartSchema: where the pre-gate node becomes the post-gate schema), and 0 across the 8 dependants measured.
    • Not C. Minting one family-wide pre-gate type for all 17 shells would be new exported surface with 16 migrations and no measured pull. That is its own decision, not this card's.
    • Clause-②: yes and a minor changeset: 17.6.0 publishes ObjectChartBlock as (props: any).

    If the maintainer reads the ruling differently, the change reverts cheaply. It narrows one shell signature and adds one cast.


    Generated by Claude Code

  14. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 8885,
      "status": "done",
      "branch": "claude/issue-8885-object-chart-block-props",
      "pr": "https://github.com/objectstack-ai/objectui/pull/10573",
      "session": "session_014mXUNuFomfj24w7s1pZzhN (mode:subagent, the dispatching seat's id)",
      "premise_still_valid": true,
      "summary": "Part 2, option A as decided by the seat. That decision supersedes this claim's earlier needs_decision report, comment 5829954656. `ObjectChartBlock`'s parameter goes from `(props: any)` to the closed `Omit OF ObjectChartProps MINUS 'schema'`, intersected with `{ schema: BaseSchema }`. Both are existing exported names, and no new type is minted. `schema` is `BaseSchema`, the node `SchemaRenderer` hands every registered renderer. The one loose member is the hand-off `schema={bound as ObjectChartSchema}` into `ObjectChart`, named in code and in the PR as the line where the pre-gate node becomes the component's post-gate schema. Both registrations (`object-chart` and the `chart` alias) type-check, and all 8 dependants read 0 diagnostics. It comes with a compile-time pin, a `minor` changeset with a BREAKING migration section, and `Fixes #8885` plus `Clause-②: yes` in the PR body. The branch was reused and fast-forwarded to main 3261e6479 before the first edit. The card assignee was not written. The PR assignee was set to os-elon-musk. The newest `Claim:` (5829567874) names this branch.",
      "tests": "Final HEAD 5fb961c13 (commits 53710f77c code+pin, 5fb961c13 changeset; base 3261e6479). Heavy runs went through `os-verify-lock.sh` in slot objectui-8885-dev, with exits read from its VERDICT line or captured before any pipe. TYPE-CHECK: `pnpm run type-check` for plugin-charts (`tsc --noEmit && tsc -p tsconfig.test.json`, script name echoed) gave VERDICT command-exit 0, and `--listFiles` contains `ObjectChartBlock.props-8885.test.tsx` with `ObjectChart.tsx` resolved from source. DEPENDANTS AT HEAD, 15 legs with each leg run separately, against the head dist whose `ObjectChartBlock` declaration reads the new signature: plugin-charts src and test, plugin-dashboard src and test, runner src and test, app-shell src and test, console src, console-starter src and test, schema-catalog src and test, byo-backend-console src, and site src after `next typegen`. Every leg: exit 0, 0 `error TS`. VITEST from repo root: `pnpm exec vitest run --maxWorkers=2 packages/plugin-charts/` plus the three `packages/types` census tests that read `ObjectChart.tsx` as text (object-chart-undeclared-keys-8885, widget-schema-anchors-7946, base-bind-declared) gave 'Test Files 77 passed (77)' and 'Tests 874 passed (874)'. That is 74 plugin-charts test files plus 3, so all ran. RED ON BASE: `ObjectChart.tsx` was set to its base blob (6ad6d4e1 to 1f26145d, proven by hash) with the pin at HEAD. `tsc -p tsconfig.test.json` then exited 2 with 8 errors: TS2344 on assertionShellParamIsNotAny, assertionShellSchemaIsNotAny, assertionSchemaIsTheRawNode and assertionRestIsObjectChartProps, and TS2578 on P1 (misspelled prop name), P2 (misspelled `schema`), P3 (string `schema`) and P4 (node without `type`). Controls C1 (the `chart` alias node), C2 (binding-only node) and C3 (ObjectChart's own props) compiled on both sides. Restored with `git checkout HEAD --` on the absolute path, proven by blob == HEAD 6ad6d4e1 and an empty `git diff HEAD`. GREEN ON HEAD: the type-check above, exit 0. CLOSEDNESS ABLATION through ablation-replace.mjs: adding `[key: string]: any` to the props type ('ok mutation landed: anchor 1 -> 0, blob 6ad6d4e17f77 -> 3ccae02ef1fb') reds exactly assertionRestIsObjectChartProps (TS2344) and P1 (TS2578). The any-guards and P2 to P4 stay green. 'ok restored: blob == HEAD (6ad6d4e17f77)'. Direction observed: turns red, as predicted. DIST: `cmp` of the base-built and head-built plugin-charts `dist/index.js` exits 0 (byte-identical). The `dist/ObjectChart.d.ts` diff is only the `ObjectChartBlock` declaration, its docblock and the `BaseSchema` import. LINT: eslint `--no-inline-config --format json` on the 2 touched source files reported 2 files and 0 errors. ObjectChart.tsx has 41 warnings against 42 on base (one fewer no-explicit-any). The pin has 1 warning, the deliberate `any` in assertionAnyProbeCanFire. Repo-wide `pnpm lint` belongs to CI. PRE-CODE MEASUREMENT (round 1, at fee1da595): the same closed type cost exactly 1 in-file diagnostic (TS2741 `chartType` missing in `BaseSchema`, at the hand-off), paid by the cast; that is the loose member.",
      "gates": [
        { "gate": "node scripts/check-changeset-presence.mjs", "exit": 0, "verdict": "3 file(s) changed, 2 of them published source of a package the release covers" },
        { "gate": "node scripts/check-changeset-no-major.mjs", "exit": 0, "verdict": "No changeset declares a `major` bump." },
        { "gate": "node scripts/check-changeset-fixed.mjs", "exit": 0, "verdict": "All workspace packages are in the changeset fixed group." },
        { "gate": "check:changeset-claims", "exit": 0, "verdict": "report-only" },
        { "gate": "check:pending-changeset-literals", "exit": 0, "verdict": "No test source names a pending changeset." },
        { "gate": "check:new-line-citations", "exit": 0, "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s)" },
        { "gate": "check:control-bytes", "exit": 0, "verdict": "OK (scanned 8655 tracked text file(s))" },
        { "gate": "check:element-data-source-declaration", "exit": 0, "verdict": "all reach the seam and take it from core" },
        { "gate": "check:unreferenced-sources", "exit": 0 },
        { "gate": "check:test-path-roots", "exit": 0 },
        { "gate": "node scripts/check-type-check-coverage.mjs", "exit": 0, "verdict": "test type-check coverage: 43/43 packages compile their tests" },
        { "gate": "check:spec-symbols", "exit": 0, "verdict": "nothing cites a key its spec symbol does not declare" },
        { "gate": "check:doc-fences", "exit": 0 },
        { "gate": "check:shell-escape-residue", "exit": 0 },
        { "gate": "check-governed-queue-guard --test (3 paths)", "exit": 0, "verdict": "NOT GOVERNED" },
        { "gate": "check:readme-exports", "exit": 1, "verdict": "NOT MEASURED, PREREQUISITE NOT MET: 417 self-imports unjudgeable (unbuilt dist), none in plugin-charts, and no README or doc names ObjectChartBlock, so this diff does not reach it" }
      ],
      "gate_derivation": "By hand from objectui's `package.json` and `.github/workflows/` (objectui has no dispatch-gates.mjs). The order's named set: type-check and tests of plugin-charts, check-changeset-presence, check:new-line-citations and check:control-bytes. Added from the diff: the gate-consuming shell reaches check:element-data-source-declaration. The new test file reaches check:test-path-roots, check-type-check-coverage and check:unreferenced-sources. The changeset reaches the no-major, fixed, claims, pending-literals and doc-fences gates. The published type surface reaches the dependant type-checks. Three packages/types census tests read ObjectChart.tsx as text and sit outside the package graph, so they were run by name. No doc or README is touched.",
      "ci": "in_progress at report time; a one-shot read on 5fb961c13 showed 42 check runs: 20 success, 3 skipped, 19 in_progress. Not waited on, per the order.",
      "files_changed": [
        "packages/plugin-charts/src/ObjectChart.tsx",
        "packages/plugin-charts/src/__tests__/ObjectChartBlock.props-8885.test.tsx",
        ".changeset/8885-object-chart-block-props.md"
      ],
      "deviations": [
        "Round 1 of this claim stopped at needs_decision on the order's stricter H2 stop (comment 5829954656). The seat lifted that condition and decided option A. This round executes A on the same claim and branch; the branch was fast-forwarded from fee1da595 to main 3261e6479 before the first edit, with no force push.",
        "The worktree was recreated at the same path from the existing branch (round 1 had removed it), and removed again after the PR opened. `git worktree remove` succeeded without --force.",
        "Beyond the pins the seat listed, the pin file also carries P2 (a misspelled `schema` prop), a control C3 (ObjectChart's own props passed through) and a documented ceiling counter-probe (a misspelled key inside the node still compiles, through BaseSchema's passthrough). Each is stated in the file."
      ],
      "clause_2": "yes: the second line of the PR body starts `Clause-②: yes`, copied from claim 5829567874, and the changeset carries it. No carrier label was written; the order names none.",
      "mcp_calls": "0",
      "api_writes": "4, all through the fleet-write relay. (1) The round-1 os-dev-report comment on #8885 via post-stamped.mjs (POST issues/8885/comments). (2) pr_create via fleet-write/dispatch.mjs (POST /repos/objectstack-ai/objectui/pulls, draft forced), giving PR 10573; body read back byte-identical, 8203 of 8203 bytes. (3) label-write.mjs --issue 10573 --assign os-elon-musk (assignee add); read back MATCHES, and labels were untouched (plugin, plugin: charts and tests, from labeler.yml). (4) This os-dev-report comment via post-stamped.mjs (POST issues/8885/comments). Plus 2 `git push`, which are not REST.",
      "pr_body_replacement": null,
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed (same family, so recorded in PR 10573's Acceptance notes rather than as a single-point card): read at base 3261e6479, 15 of 17 `elementDataSourceBlock` shells publish `schema: any`, and 2 of them (object-map and object-timeline) publish a bare `React.FC OF any`. Carrier: none; option C was not taken.",
        "noted, not filed: the `@object-ui/react` README types the shell `FC OF { schema: BaseSchema }` (as this PR now does), while the `elementDataSourceBlock` doc comment beside `ElementDataSourceGate` shows `React.FC OF any`. It is in PR 10573's Acceptance notes. Carrier: the next edit to that file."
      ]
    }

    Generated by Claude Code

  15. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: objectui#10573 at 5fb961c (Part 2, option A); ready + auto-merge follow this ACCEPT

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. Claim 5829567874. It executes ruling 5810232641 (Part 2) under the seat reading 5830027843 (option A).

    Implemented-by:  claude/issue-8885-object-chart-block-props
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the signature ObjectChartBlock goes from (props: any) to Omit<ObjectChartProps, 'schema'> & { schema: BaseSchema }. Both names are existing exports, and no name is minted. BaseSchema is what SchemaRenderer hands every registered renderer (SchemaRendererProps.schema, whose object arm reaches createElement(Component, { schema })), so it is "the registry renderer's raw node input" the ruling names, ⛔ not the post-gate ObjectChartSchema
    closed at the prop level ObjectChartProps = { schema; dataSource?; onSegmentClick? }, with no index signature and no required member besides schema. ObjectChart reads exactly those three. BaseSchema's passthrough stays inside the node, and the pin states that ceiling
    the one loose member schema={bound as ObjectChartSchema} at the hand-off into ObjectChart, the line where the pre-gate node becomes the post-gate schema. It is named in code and in the PR body. The non-test diff adds no other cast, no any and no @ts- directive
    pins P1–P4 (misspelled prop, missing schema, string schema, node without type) are red on base (4× TS2578) and fire for their stated reasons on head. The reviewer re-probed them in an npm-tarball sandbox. The any-guards are red on base (4× TS2344). Controls C1 (chart alias node), C2 (binding-only node) and C3 (ObjectChart's own props) compile. An open-bag ablation reds exactly the rest-assertion and P1
    no runtime change the non-test diff is one type import, one annotation and one as; the dev reports byte-identical dist/index.js
    census the three packages/types text-census tests that read ObjectChart.tsx stay green, and no new schema.KEY read is added
    Clause-②: yes / semver minor + BREAKING on @object-ui/plugin-charts: 17.6.0 publishes ObjectChartBlock: (props: any) (npm pack). The migration section names what now fails, with a before/after
    pending changesets none falsified: the only other mention, objectchart-schema-anchor-7946, is about the inner ObjectChart
    main moved PR objectui#10571 merged at a5060016 (normalizeChartSchema.ts), and git merge-tree is clean
    contract review PASS at CONTRACT_REVIEW_TIER on this head, record 5830682058. The seat read the reviewer transcript: every turn ran at tier
    governed NOT GOVERNED (3 paths)
    CI 43 check-runs on 5fb961c: 40 success, 3 skipped by design, 0 red
    closing keywords Fixes #8885 only

    Seat edit in the landing stroke

    The PR title becomes fix(plugin-charts)!: …. objectui squash-merges with the title, and the ! makes the commit carry the BREAKING the changeset declares. The reviewer found fix( house-tolerated, with precedent. feat(scope)!: is the majority form on main, and the ! is the part that matters. The body is unchanged.

    Findings, each with its disposition

    • Dev and reviewer: 15 of the 17 elementDataSourceBlock shells publish an any-shaped schema (two as React.FC<any>: map and timeline). This is the family option C would cover, and the seat reading 5830027843 kept it out of this card ⇒ recorded. It is the carrier for a family decision if the maintainer wants one. No card is filed, because it would be a scope decision rather than a defect.
    • Dev and reviewer: the @object-ui/react README types the shell FC<{ schema: BaseSchema }> (as this PR now does), while the doc comment beside ElementDataSourceGate shows elementDataSourceBlock<React.FC<any>> ⇒ recorded; the carrier is the next edit to that file.
    • Reviewer nit: the changeset's prose "Migration:" sentence leaves the string-schema case to the code block ⇒ Acceptance notes.

    Deviations recorded

    • Round 1 stopped at needs_decision on the seat order's stricter H2 stop. That stop was the seat's error, recorded in 5830027843. Round 2 ran on the same claim and branch, fast-forwarded without a force push.
    • The PR assignee is set (os-elon-musk), because this dev's label-write went through.

    State

    In one stroke: the title edit, ready and auto-merge (squash), through the relay ops issue_patch + pr_ready + automerge_enable.


    Generated by Claude Code

  16. added 2 commits that reference this issue on Sep 28, 2026
    47ba790
    fb13e85
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions