Skip to content

docs(api): schema-reference.md lists 3 RUNTIME-SLOT handler keys in its JSON authorable-property tables, which the zod mirror refuses by name — plus one z.function() mirror survivor of #6124's sweep #7351

Closed

Description

@os-litant

Filed by the dev of #7340 / PR #7350 (docs half of #6124) as an out-of-scope finding measured while censusing content/docs for retired handler keys. Not fixed there: #7340 explicitly scopes out the 36 runtime-slot keys ("they keep their function type; pages may keep them"), so this needs a triage decision rather than a unilateral edit.

⚠️ An earlier revision of this body listed five rows and called all five "refused by name". That was wrong and is corrected below: only three are refusals, one is a correct row, and one is a separate types finding. The numbers below were re-measured per key against packages/types/src/zod/*.zod.ts.

Finding 1 (docs) — three authorable-property rows name a key the validator refuses

content/docs/api/schema-reference.md documents JSON node schemas — every example on the page is a JSON document — and each section closes with a | Property | Type | Description | table of authorable properties. Three of those rows name an on* key whose mirror member is handlerKeyRefusal(key, 'runtime-slot', ...), i.e. refused by name at authoring time:

line key owner mirror doc Type cell
924 onCardMove KanbanSchema handlerKeyRefusal(..., 'runtime-slot') function
925 onCardClick KanbanSchema handlerKeyRefusal(..., 'runtime-slot') function
1042 onViewChange CalendarViewSchema handlerKeyRefusal(..., 'runtime-slot') function

Line numbers on origin/main @ 4704aa4bb; PR #7350 removes two retired rows at 926–927, so the kanban rows keep their numbers and the calendar row shifts up by 2 once it lands.

The #6124 wording is explicit that these are "a host-supplied function, NOT authorable metadata: JSON has no function value, so the zod twin refuses this key by name and points at the node-type spelling." A JSON author reading this table has no way to know that: the other rows (columns, draggable) are authorable and these are not, and the Type column reads function either way.

Measured NOT a defect, recorded so it is not re-reported: ViewSwitcherSchema.onViewChange (line 1192, doc Type string) is mirrored as z.string() describing "an event NAME, not a callback or a handler expression" — the page is right about it, and the key belongs to the z.string() dialect population #7344 tracks, not here.

Finding 2 (types) — one on* mirror member is still z.function()

CalendarViewSchema.onEventClick (packages/types/src/zod/complex.zod.ts:145) is still declared

onEventClick: z
  .function()
  .optional()
  .describe('Host-only event click handler (authored JSON cannot produce a function)')

That is the exact shape #6124 was opened about ("28 zod-mirror keys are declared z.function(), which NO JSON document can satisfy"), surviving PR #7339's sweep — its sibling on the same schema, onViewChange, became a refusal in that PR. A repo-wide scan finds it is the ONLY remaining on* member with this shape (the four other surviving z.function() members are non-handler keys: cell, renderCellEditor, validate, custom).

⚠️ Check #7344 before acting: it tracks the per-key treatment PR #7339 did not cover (8 z.string(), 3 z.any()). This z.function() case is not named in its title, but it may be inside its scope — fold it in there rather than duplicating if so.

Options for finding 1

  • A — mark the rows: keep them, add a "host-supplied; not authorable in JSON" note in the Description cell (mirroring the disposition the tombstone JSDoc and the refusal message both carry).
  • B — remove them from this page's authorable tables and document the runtime-slot surface once, centrally, with a pointer.
  • C — no change: accept that a function type in the Type column already reads as "not a JSON value".

No recommendation offered — this is a docs-surface convention call, and the #7340 card already ruled that component pages may keep runtime-slot rows; whether the JSON schema reference is the same case is the actual question. If A or B is chosen, the pin added by PR #7350 (packages/types/src/__tests__/component-docs-retired-handler-keys-7340.test.ts) already carries the machinery: it resolves each doc row's (interface, key) pair against the shipped declaration and can tell runtime-slot from retired without a hand-list. Its CONTROL block currently asserts the opposite (that KanbanSchema.onCardMove / .onCardClick ARE present and callable), so whichever option lands must update that block deliberately.

Activity

  1. changed the title [-]docs(api): `schema-reference.md` lists 5 RUNTIME-SLOT handler keys in its JSON authorable-property tables, which the zod mirror refuses by name[/-] [+]docs(api): `schema-reference.md` lists 3 RUNTIME-SLOT handler keys in its JSON authorable-property tables, which the zod mirror refuses by name — plus one `z.function()` mirror survivor of #6124's sweep[/+] on Sep 2, 2026
  2. added
    documentationImprovements or additions to documentation
    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
    on Sep 5, 2026
  3. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    分诊 — domain:devx / priority:p3 / pm:queue / documentation / finding

    锚定 (anchoring):剩余工作落在 content/docs/api/schema-reference.md + PR #7350 加的那个 pin ⇒ domain:devx。

    ⭐ Finding 2 已经修好了 —— 关闭这一半

    卡片说 CalendarViewSchema.onEventClick 仍是 z.function(),是 #6124 那次 sweep 的幸存者。在 origin/main a472b07 上它已经是 refusal 了:

    packages/types/src/zod/complex.zod.ts:145   // objectui#7344: the multi-line `z.function()` spelling PR #7339's anchored
    packages/types/src/zod/complex.zod.ts:147   // `onViewChange` below.
    packages/types/src/zod/complex.zod.ts:148   onEventClick: handlerKeyRefusal('onEventClick', 'runtime-slot', 'Host-only event click handler'),
    packages/types/src/zod/complex.zod.ts:149   onViewChange: handlerKeyRefusal('onViewChange', 'runtime-slot', 'Host-only view change handler'),
    

    :145 的注释点名 objectui#7344 —— 也就是卡片自己让人"acting 前先看 #7344,可能在它范围内"的那张卡,确实把它收了。

    顺带把全仓 z.function() 的现状留在这里,省得下一个人再数:

    packages/types/src/zod/base.zod.ts:418          EventHandlersSchema = z.record(z.string(), z.function())   ← 不是 on* 成员,是 record
    packages/types/src/zod/data-display.zod.ts:123  cell
    packages/types/src/zod/data-display.zod.ts:280  renderCellEditor
    packages/types/src/zod/form.zod.ts:148          validate
    packages/types/src/zod/form.zod.ts:159          custom
    

    正是卡片点名的那四个非 handler 键(外加一个 record 形状)。on* 成员里 z.function() 现在是 0。 卡片的 Finding 2 到此为止,⛔ 不需要再动。

    Finding 1 仍然成立 —— 三行都在

    ⚠️ 行号已漂(卡片测于 4704aa4bb,PR #7350 此后落地):

    content/docs/api/schema-reference.md:925    | `onCardMove` | `function` | Callback when a card is moved: … |      (卡片写 924)
    content/docs/api/schema-reference.md:926    | `onCardClick` | `function` | Callback when a card is clicked. |    (卡片写 925)
    content/docs/api/schema-reference.md:1041   | `onViewChange` | `function` | Host-only: same rule as `onEventClick`. |  (卡片写 1042)
    

    对应的 mirror 侧三处 handlerKeyRefusal(complex.zod.ts:68 / :69 / :149)也都在 —— 按名拒绝属实。

    ⭐ 卡片主动标注的那条"测过、不是缺陷"也复核为真,保留以免被重新上报:

    content/docs/api/schema-reference.md:1191   | `onViewChange` | `string` | Expression or callback invoked on view change. |
    

    ViewSwitcherSchema.onViewChange 的 Type 单元格是 string,与它 z.string() 的 mirror 一致 —— 这一行是对的,属于 #7344 追的 z.string() 方言人口,不属于本卡。

    ⚠️ 另注意 :1041 那行的 Description 已经写着 "Host-only: same rule as onEventClick" —— 也就是说三行里已经有一行做了选项 A 的事。这是接手者选路时的重要输入:现状不是"三行都无标注",而是"一行标了、两行没标",本身就是不一致。

    定级理由

    priority:p3:

    • 无运行期缺陷(这三个键本来就是宿主提供的函数槽,JSON 作者本来就写不了)。
    • 代价是文档误导:卡片说得准 —— 同一张表里 columns / draggable 是可授权的、这三个不是,而 Type 列两边都写 function,JSON 作者没有任何办法从这张表分辨。
    • 但影响面窄(三行),且已有一行示范了正确写法。

    定型:文档约定,不踩 manual floor

    三个选项都不改任何代码行为、不改 accept set、不改门禁强度。

    ⛔ 给执行席的边界

    ⛔ 本席不替这个约定拍板(卡片明说"No recommendation offered — this is a docs-surface convention call",且 #7340 已裁"组件页可以保留 runtime-slot 行",本页是不是同一 case 才是真问题)。但给三条硬约束:

    1. 选项 C(不改)需要正面论证才能选。 现状已经自相矛盾 —— :1041 标了、:925/:926 没标。选 C 等于宣布"function 这个 Type 值本身就够",那就该把 :1041 的标注也删掉以求一致。⛔ 不允许"什么都不做"当成 C 交付。
    2. 选 A 或 B 都必须同时更新 PR docs(components): stop teaching #6124's retired handler keys as authorable props #7350 加的那个 pin。 卡片写明了,且这是硬要求:packages/types/src/__tests__/component-docs-retired-handler-keys-7340.test.ts 的 CONTROL 块当前断言的正是相反的事(KanbanSchema.onCardMove / .onCardClick 存在且可调用)。⛔ 不同步更新会让 pin 变成一条说谎的钉子。
    3. 本卡范围只到这三行 + 那个 pin。 ⛔ 不要顺手去清 types: 8 on* handler mirrors still declare the z.string() expression dialect and 3 declare z.any() — the per-key treatment the #6182 ruling assigned to #6124's sweep, not covered by PR #7339 #7344 追的 z.string() / z.any() 方言人口,也不要动 :1191 那条正确的行。

    若选 A,最省事且与现状一致的做法是把 :1041 已有的措辞复制到另外两行 —— 但这是执行席的判断,不是本席的裁决。


    Generated by Claude Code

  4. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    Deferred behind #7923 — serial, not folded. domain:devx @ objectui execution seat, PM session session_01MM7kaS4dPpYHV5BsMyu4tQ, R45, 2026-09-06T06:55Z.

    Both cards land in content/docs/api/schema-reference.md, so fold-or-serial is answered here against the five gates: gate ① fails — #7923 is an undeclared entry-level key in one JSON example (delete default, add defaultListView), this card is three runtime-slot rows in the authorable-property tables plus a z.function() mirror survivor, and this card still carries an A/B/C convention choice. Different defect shape, different fix ⇒ serial; #7923 goes first as the older queued Bug.

    Known pits recorded now for whoever dispatches this card next:


    Generated by Claude Code

  5. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    Serialisation discharged — #7923 landed (PR #7991 merged 2026-09-06T07:39:21Z; main bac5e54). domain:devx @ objectui execution seat, PM session session_01MM7kaS4dPpYHV5BsMyu4tQ, R45, 2026-09-06T07:48Z. No label change; this card is dispatchable at the next free slot with the pits recorded in 5557566494 — its three row line numbers are re-taken on bac5e54 in the seat's next reading, and the A/B/C convention question in the body is still the dev's first thing to settle with the triage comment before editing.


    Generated by Claude Code

  6. baozhoutao commented on Sep 6, 2026

    @baozhoutao
    Contributor

    Closed as completed — both findings are already on main; the premise no longer holds

    domain:devx @ objectui execution seat, PM session session_01MM7kaS4dPpYHV5BsMyu4tQ, R45, 2026-09-06T07:49Z. Pre-dispatch premise check on origin/main bac5e54, ⛔ not on the card's text:

    finding card's claim reading on main
    1 — three authorable-table rows name refused runtime-slot keys with Type function and no note rows at the old :924 / :925 / :1042 :967 onCardMove … "Runtime slot supplied by a React host, (cardId, fromColumnId, toColumnId, newIndex); not authorable in JSON." · :968 onCardClick … "not authorable in JSON." · :1093 onViewChange … "Host-only: same rule as onEventClick." — option A (mark the rows) is what landed
    2 — CalendarViewSchema.onEventClick still z.function() in complex.zod.ts :145 z.function().optional() packages/types/src/zod/complex.zod.ts:241 onEventClick: handlerKeyRefusal('onEventClick', 'runtime-slot', 'Host-only event click handler') — the refusal shape, matching its sibling onViewChange at :242
    the ViewSwitcherSchema.onViewChange row the card says is correct string :1243 onViewChange · string — unchanged, still correct
    control — the 7340 pin's CONTROL block still lists KanbanSchema.onCardMove / onCardClick / onQuickAdd as present runtime slots (component-docs-retired-handler-keys-7340.test.ts:259–261), consistent with option A (rows kept, marked)

    Nothing left to dispatch. The shallow clone cannot name the PR that landed the rewording (history horizon at 6ea524f); whoever reopens this on a different reading should quote the row text on the current main. pm:queue stripped in the same write; domain:devx / finding / documentation stay (ownership, not state). Maintainer or triage may reopen.


    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

    documentationImprovements or additions to documentationdomain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repofindingpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions