Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

finding: object-grid.data — two spec authorities disagree on the KIND (ViewDataSchema object vs ComponentPropsMap['object-grid'].data array), so whichever the declaration matches, the other refuses it #6207

Closed

Description

@yinlianghui-tw

Blocked-by: #7122

Found while implementing #4971 (the declared-arm ⊆ spec-accepted gate). Filed unassigned, not claiming. Not fixed in that PR — #4971's dispatch is explicit that the accept set and every declaration stay unchanged, so this is carried there as a reasoned, issue-backed exemption pointing here.

Two entries of the same contract, opposite kinds

Both are @objectstack/spec@17.2.0, both describe object-grid's data:

spec authority kind its own description
ViewDataSchema — what ObjectGridSchema.data?: ViewData (packages/types/src/objectql.ts:556) resolves to object, discriminated on provider (object / api / value / schema), each arm strict inline rows live at { provider: 'value', items: [...] }
ComponentPropsMap['object-grid'].data array (z.array(z.unknown()).optional()) 'Static inline rows — bypasses the object query'

Measured on the installed pin:

ComponentPropsMap['object-grid'].safeParse({ data: [{ id: 1 }] })                  → success
ComponentPropsMap['object-grid'].safeParse({ data: { provider: 'value', items: [] } })
  → [{"expected":"array","code":"invalid_type","path":["data"],
      "message":"Invalid input: expected array, received object"}]

The declaration (plugin-grid/src/index.tsx:225, type: 'object') matches the first authority — deliberately, and it is pinned there: #5090 / PR #5108 changed it from 'array' to 'object' against ViewDataSchema's own verdicts, and packages/plugin-grid/src/__tests__/gridDataInputContract.test.ts holds it. So it is the ComponentPropsMap entry that now refuses the published arm.

Why this is not a re-file of #5090

#5090 was declaration-vs-contract with ONE contract. This is contract-vs-contract: the fix #5090 landed is what makes the second authority's disagreement visible, and no change to the declaration can satisfy both — 'object' is refused by ComponentPropsMap, 'array' is refused by ViewDataSchema and by tsc (TS2322, measured on #5090). Flipping the declaration back would re-open #5090 exactly.

Why it matters

ComponentPropsMap is the authority the repo-wide parity gates read (apps/console/src/__tests__/registry-inputs-spec-parity.test.ts — both key-name directions and, since #4971, the arm direction). While the two disagree, one of them is teaching authors a shape the other refuses, and the gate that would notice has to be told to look away on this key.

Resolution is upstream, not here

This repo does not edit @objectstack/spec (AGENTS.md #0 / #0.1) — the two entries have to converge on one kind upstream. The likely shape (not a decision this card can take): ComponentPropsMap['object-grid'].data becomes ViewDataSchema, which is what ObjectGridSchema already resolves to and what the designer publishes; the array form is the deprecated staticData shortcut the #4648 carve-out already refuses to publish.

How to re-derive

sed -n '225p' packages/plugin-grid/src/index.tsx
grep -n 'data?: ViewData' packages/types/src/objectql.ts
pnpm exec vitest run apps/console/src/__tests__/registry-inputs-spec-parity.test.ts   # the #4971 arm gate; entry `object-grid.data:object`
pnpm exec vitest run packages/plugin-grid/src/__tests__/gridDataInputContract.test.ts # the #5090 pin, against ViewDataSchema

Deleting the exemption entry in registry-inputs-spec-parity.test.ts is what closes this card — the gate's stale-exemption test demands it the moment the two authorities converge.


Generated by Claude Code

Activity

  1. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    on Aug 25, 2026
  2. added theissue type on Aug 25, 2026
  3. claude commented on Aug 25, 2026

    @claude
    Contributor

    Triage: → needs-user-decision + domain:spec — contract-vs-contract inside @objectstack/spec itself: ViewDataSchema (object, provider-discriminated; the authority #5090 ruled and pinned the declaration against) versus ComponentPropsMap['object-grid'].data (bare array, described as 'static inline rows — bypasses the object query'). Not a re-file of #5090, and not blanket-inheritable from it either: the props-map entry's own describe-text suggests a deliberate second semantic, so this is a decision, not a queue card. Type: Bug.

    ① 项目长远合理性:同一个键在同一份 spec 里两种 KIND 是最贵的契约债 —— 谁消费 ComponentPropsMap 谁就拒绝已 pin 的合法行为;收敛到 ViewDataSchema(#5090 已裁的权威)是缩小特例。
    ② 实际业务拉动:实测 { provider:'value', items:[…] }(pinned 合法形)被 ComponentPropsMap 拒绝 —— 任何走 props-map 校验的工具链(sdui-parser / os validate)会把合法页面判红。
    ③ 防 AI 犯错:两个权威并存时,AI 修代码必然「修向离它最近的那个」,而且两个方向都有测试可绿 —— 单一权威 + 删 #4971 豁免条目才封死这条错路。
    ④ 创业阶段不扩散:若「裸数组 = 静默直通 inline rows」真有独立用途,也应显式并入 ViewDataSchema 的 value 臂,而不是留第二个 KIND;默认收敛、不新增。
    推荐:A = ComponentPropsMap['object-grid'].data 对齐 ViewDataSchema(object),沿 #5090 权威;B = 保留 array 并在 ViewDataSchema 增 array 臂(需真实拉动证据)。回一个字母即可。
    置信缺口:未盘点 array 形今天是否有真实消费方(生成物/模板里写裸数组 data 的页面);有则 A 需带迁移面。


    Generated by Claude Code

  4. os-steve commented on Aug 25, 2026

    @os-steve
    Collaborator

    Maintainer ruling (2026-08-25, batch adjudication, batch 4; verbatim: 「同意」): Option A — ComponentPropsMap['object-grid'].data converges onto ViewDataSchema (the #5090-ruled, pinned authority); the bare-array form is the deprecated shortcut the #4648 carve-out already refuses to publish. Migration check (bare-array authors in generated artifacts/templates) rides the upstream change.

    Execution is upstream in @objectstack/spec — filed as objectstack-ai/objectstack#12039 (family-folded with ui#6206's key, spec lane queue, Clause-② yes).

    Blocked-by: objectstack-ai/objectstack#12039

    Unlock criterion (cross-repo, consumer-installable): a released spec version carrying the convergence reaches this repo's installed pin — not merely the upstream merge. On unlock, this card's close is exactly the #4971 stale-exemption deletion: remove object-grid.data:object from registry-inputs-spec-parity.test.ts and let the gate verify convergence. State transition: needs-user-decision → pm:blocked.


    Generated by Claude Code

  5. yinlianghui commented on Sep 2, 2026

    @yinlianghui
    Contributor

    Pre-brief for the moment the pin unlocks (spec@objectui seat, session session_01V3hPr7riucnMfhcHY86Msd, 2026-09-02; read-only measurement on both origin/mains, no state change — still pm:blocked).

    Release ask lives on objectstack#14324.


    Generated by Claude Code

  6. os-zhuang commented on Sep 7, 2026

    @os-zhuang
    Contributor

    CLOSED — resolved upstream(两个 spec 权威已收敛)。⭐ 本席自己的读数,不是前任的散文。 domain:spec @ objectui 执行席,session session_01QtGhnU3WnnWyiWeYQhw2aX,读于 2026-09-07T21:5xZ,origin/main 4b5e07a5。与姊妹卡 #6206 同批同因。

    ① 阻塞已解除

    卡头 Blocked-by: #7122。现读:#7122 已关,completed,os-justin 于 2026-09-07T11:32:03Z 经合入的 PR #8311 关闭 ⇒ 该行自今天上午即陈旧,pm:blocked 随之失效。

    ② 卡片自己写死的关闭判据已满足

    Deleting the exemption entry in registry-inputs-spec-parity.test.ts is what closes this card — the gate's stale-exemption test demands it the moment the two authorities converge.

    现读该文件 on origin/main:OFF_SPEC_ARM_EXEMPTIONS 为空;'object-grid.data:object' 在整个文件里 0 命中(控制项:文件 3774 行,存在且非空)。⇒ 条目已删。

    ③ 收敛的方向,与本卡当初的预测一致

    闸门 docblock 逐字记录:

    object-grid.data:object (objectui#6207) — the two spec authorities that disagreed have converged. ComponentPropsMap[object-grid].data was z.array(z.unknown()); it now answers invalid_union at data.provider for an object probe, i.e. the discriminated ViewDataSchema shape ObjectGridSchema.data already resolved to.

    ⇒ 正是本卡「Resolution is upstream」一节预测的那个形状:ComponentPropsMap['object-grid'].data 变成了 ViewDataSchema。而 #5090 / PR #5108 当初刻意选的 object 臂,如今成了契约自己的选择 —— ⛔ 声明逐字未动,是契约向它靠拢。

    ④ 为什么这不是「读了别人一句话就信」

    ⚠️ docblock 里那条探针读数是清空该表的人测的,不是我 —— 本容器没有 node_modules,⛔ 我无法自己对着已安装产物复跑,这条腿照实声明。

    ⭐ 但关闭不依赖那段散文。 依赖的是我自己读到的结构性事实:该闸门带 carries no stale arm exemption 自检 —— 分歧还在的话,删掉条目就会让闸门变红。而 main 是绿的(本轮刚有 PR 经合并队列落地)。⇒ 若两个权威仍在打架,main 此刻就该红着要求把条目加回来。它没有。

    pm:blocked 摘除,卡关为 completed,domain:spec 维持。


    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

No one assigned

    Labels

    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions