Escalated by the domain:devx @ objectui execution seat (#5748), PM session session_019b5UBNMtTzKbVtZZGvFuxe, from #6152's measurement. ⛔ This cannot be read off the code — it is a product question about the authoring contract, and the seat is not guessing it.
The measurement
A census of every on* key mirrored in packages/types/src/zod/ found 73 mirrored handler keys in two incompatible dialects:
| dialect | count |
|---|
z.function() | 56 |
z.string() — a handler expression | 11 (onClick, onInstall, onPreview, onSave, onCancel, onBack, onViewChange, onChange) |
z.any() | 3 |
| named schema | 3 |
⚠️Both dialects appear in files that also mirror the other, so this is not a clean per-file or per-surface split that could be inferred. Two answers coexist in one codebase with nothing declaring which is intended.
Why it needs a person
The two dialects make incompatible promises to an author:
z.function()cannot be satisfied by any serialized authored document. A JSON or YAML schema can never produce a function, so the key is declared-but-unauthorable — it exists for a runtime caller, not for a metadata author.z.string() says the opposite: an author may write a handler as an expression, and something resolves it.
⭐ objectui#4453 already narrowed one such key to typeof === 'function', so an authored string handler is silently DROPPED (packages/plugin-calendar/src/calendar-view-renderer.tsx:322-331). If that is the intended direction, the 11 z.string() mirrors are advertising a capability the runtime discards — the "declared but not enforced" shape this whole family exists to close, pointing the other way.
What it decides
⭐ It changes the remedy for a lane already in flight.#6152 ruled that 23 callback-shaped declared-but-unmirrored keys are runtime-only and non-authorable (reclassified, not mirrored). That ruling is safe under either answer here — but:
- If
z.function() is intended, the 11 z.string() mirrors are legacy to retire, and the 23 stay runtime-only. Clean. - If the expression dialect is intended, then the remedy for those 23 is not "reclassify" but ⭐ "offer an authored expression key beside each runtime callback" — a materially larger and different piece of work.
- If both are intended for different surfaces (blocks/app author expressions; component schemas carry runtime callbacks), then the rule needs stating somewhere a tool can read, because today nothing does.
⚠️#5155's standing ruling places rejection at the zod/publish boundary. That makes these mirrors the authoritative statement of what an author may write — which is exactly why two contradictory statements in that layer matter more than they would in prose.
What is NOT being asked
⛔ Not asking anyone to pick a favourite. Not proposing a sweep. ⛔ #6152's option A is not blocked by this and should land on its own — the 23 keys are runtime slots today under either answer, and adding authored-expression keys later is additive rather than contradictory.
The question is only: which dialect is the contract, so the next card in this family stops re-deriving it from a 56-to-11 vote.
Reproduce
rg -n 'on[A-Z][A-Za-z]*:\s*z\.(function|string|any)' packages/types/src/zod/
Refs: #6152 (where it was measured, and the lane it changes) · #6058 / PR #6149 (the ledger that surfaced it) · #4453 (an authored string handler is dropped) · #5155 (rejection lives at the zod/publish boundary) · #6122 / PR #6142 (no renderer reads 16 schema-level event slots).
Escalated by the
domain:devx@ objectui execution seat (#5748), PM sessionsession_019b5UBNMtTzKbVtZZGvFuxe, from #6152's measurement. ⛔ This cannot be read off the code — it is a product question about the authoring contract, and the seat is not guessing it.The measurement
A census of every
on*key mirrored inpackages/types/src/zod/found 73 mirrored handler keys in two incompatible dialects:z.function()z.string()— a handler expressiononClick,onInstall,onPreview,onSave,onCancel,onBack,onViewChange,onChange)z.any()Why it needs a person
The two dialects make incompatible promises to an author:
z.function()cannot be satisfied by any serialized authored document. A JSON or YAML schema can never produce a function, so the key is declared-but-unauthorable — it exists for a runtime caller, not for a metadata author.z.string()says the opposite: an author may write a handler as an expression, and something resolves it.⭐ objectui#4453 already narrowed one such key to
typeof === 'function', so an authored string handler is silently DROPPED (packages/plugin-calendar/src/calendar-view-renderer.tsx:322-331). If that is the intended direction, the 11z.string()mirrors are advertising a capability the runtime discards — the "declared but not enforced" shape this whole family exists to close, pointing the other way.What it decides
⭐ It changes the remedy for a lane already in flight.#6152 ruled that 23 callback-shaped declared-but-unmirrored keys are runtime-only and non-authorable (reclassified, not mirrored). That ruling is safe under either answer here — but:
z.function()is intended, the 11z.string()mirrors are legacy to retire, and the 23 stay runtime-only. Clean.What is NOT being asked
⛔ Not asking anyone to pick a favourite. Not proposing a sweep. ⛔ #6152's option A is not blocked by this and should land on its own — the 23 keys are runtime slots today under either answer, and adding authored-expression keys later is additive rather than contradictory.
The question is only: which dialect is the contract, so the next card in this family stops re-deriving it from a 56-to-11 vote.
Reproduce
Refs: #6152 (where it was measured, and the lane it changes) · #6058 / PR #6149 (the ledger that surfaced it) · #4453 (an authored string handler is dropped) · #5155 (rejection lives at the zod/publish boundary) · #6122 / PR #6142 (no renderer reads 16 schema-level event slots).