You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> ### ⛔ CORRECTED 2026-08-18 — read this first
> An earlier version of this body claimed onNavigate is absent from the ObjectGridSchema interface and only type-checks because of BaseSchema's index signature. That was false. It is explicitly declared at packages/types/src/objectql.ts:847, with a doc comment. The error came from a grep bounded to lines 532–760 of an interface that runs 532–888. The body below is corrected, the affected argument is withdrawn, and the PM recommendation is withdrawn with it — see the correction comment for what moved and why.
Split out of #5091 by the repo:objectui PM seat (round 6, session session_01RV6yuVCxymHYE16PL9vQkE) at dispatch time, and deliberately excluded from that card's dispatch.
Why this is a separate card
#5091 catalogued four keys ObjectGrid reads but GRID_QUERY_INPUTS does not declare. A later comment added a fifth — schema.onNavigate — on the reasoning that it belonged to the same decision, and it was attached to #5091 rather than filed separately so one decision would not be split across two cards.
The maintainer's 2026-08-18 ruling on #5091 (verbatim 「同意」) then enumerated only the original four: rowActionDefs → into the manifest; columnState / hideRowHeightToggle / maxInlineRowActions → non-author surface with exemption comments. onNavigate does not appear in it.
So the ruling and the card no longer cover the same key set. Rather than let a PM's reading close that gap, #5091 was dispatched for the four ruled keys with onNavigate explicitly out of scope, and the fifth comes here for its own answer.
declared on ObjectGridSchema (interface spans 532–888), with the doc comment "Callback for page-level navigation (used by 'page' mode). Called with recordId and action ('view' | 'edit')."
packages/plugin-grid/src/index.tsx no hit — absent from GRID_QUERY_INPUTS
It was invisible to #5091's original sweep because that sweep matched the cast form (schema as any).KEY, and this one is a plain read — the mirror image of the blind spot that produced the earlier misjudgement.
The actual shape of the problem
It is not an undeclared key absorbed by a loose index signature (the corrected reading). @object-ui/types declares it deliberately and documents it. The problem is narrower and now sits in exactly one place:
The renderer reads it and the TS type declares it, while the manifest surface — GRID_QUERY_INPUTS, the designer panel, the generated sdui-intrinsics.d.ts — denies it exists. That is the same "renderer reads it, manifest denies it" condition #4648 and #5091 exist to close.
In the same useNavigationOverlay call, schema.navigation and schema.objectName are both on the manifest surface; only onNavigate is not.
The argument that survives the correction, and is now the strongest one
A schema is a serialisable document, and a function cannot survive a metadata round-trip. Whatever declares it, onNavigate can never be written by an author in JSON or YAML, never round-trip through metadata, and never be produced by an AI writing a schema document. A (recordId, action) => void in a stored document is not expressible.
So the question is not whether it is declared — it is — but whether a callback that only a programmatic caller can supply belongs on the schema type at all, when nine sibling callbacks live on ObjectGridComponentProps for precisely that reason.
For contrast, verified key by key: onRowClick, onRowSelect, onCellChange, onRowSave, onBatchSave, onEdit, onDelete, onBulkDelete, onAddRecord exist only on ObjectGridComponentProps, with zero schema.on* read points. onNavigate is the one that is on both.
Four-prism
Platform coherence — nine callbacks are props-only; one is on the schema with a doc comment. Either that tenth is a deliberate exception that should be stated as one, or it is inconsistent. It already cost a documentation claim: the README and docs page said "the grid never reads a callback off the schema", narrowed to "never reads any of these nine" because of this key.
Measured business pull — none found for authoring it in metadata, and none is possible: JSON cannot carry a function. Programmatic callers are served by the props channel today.
AI-agent error-resistance — an agent reading ObjectGrid.tsx sees a callback taken off schema, checks @object-ui/types, finds it declared and documented, and reasonably concludes callbacks may be authored on a schema. It then emits metadata that silently does nothing. The corrected facts make this worse, not better: before, only the read site suggested it; now the type and its doc comment appear to confirm it.
Startup scope discipline — with the key explicitly declared, removing it is a breaking public type change plus a deprecation cycle, not the cheap tidy-up the earlier version of this card assumed.
The options
A. Move it off the schema read point and remove the declaration — onNavigate joins its nine siblings on ObjectGridComponentProps. Ends with one clean rule and restores the docs sentence as a universal. Cost, corrected: a breaking public type change on @object-ui/types plus a deprecation cycle — the same profile that decided FormSchema.onChange is a declared public callback the form renderer never calls — authoring it is a silent no-op #4259against removal. Requires checking for callers passing it through a schema object.
B. Declare it in GRID_QUERY_INPUTS so all three surfaces agree. Cheapest to execute and makes the manifest match the type. But it publishes to the designer panel a key no author can express, which is the objection that started this card.
C. Keep it as an explicit, documented exception — leave the type declaration and the read, add an exemption comment at the read site and a note on the type saying it is programmatic-only and deliberately outside the manifest. Cheapest that changes nothing observable; leaves the docs sentence narrowed.
PM recommendation: withdrawn. The earlier recommendation of A rested on the false premise that nothing declared the key. With the declaration real and deliberate, A's cost profile changes enough that I do not think a PM should be picking between these — it is a public-surface question with a real deprecation cost on one side and a published-but-unauthorable key on the other.
This is on the human floor: it moves a published surface, and #5091's ruling is the neighbouring decision it must stay consistent with.
Refs #5091 (the four ruled keys; its rowActionDefs line is also back with the maintainer, see PR5241), #5240 (userActions, a sixth key in the same family), #4648 (the prior round of this rule), #5065 / #5090 (same sweep).
> ### ⛔ CORRECTED 2026-08-18 — read this first
> An earlier version of this body claimed
onNavigateis absent from theObjectGridSchemainterface and only type-checks because ofBaseSchema's index signature. That was false. It is explicitly declared atpackages/types/src/objectql.ts:847, with a doc comment. The error came from a grep bounded to lines 532–760 of an interface that runs 532–888. The body below is corrected, the affected argument is withdrawn, and the PM recommendation is withdrawn with it — see the correction comment for what moved and why.Split out of #5091 by the
repo:objectuiPM seat (round 6, sessionsession_01RV6yuVCxymHYE16PL9vQkE) at dispatch time, and deliberately excluded from that card's dispatch.Why this is a separate card
#5091 catalogued four keys
ObjectGridreads butGRID_QUERY_INPUTSdoes not declare. A later comment added a fifth —schema.onNavigate— on the reasoning that it belonged to the same decision, and it was attached to #5091 rather than filed separately so one decision would not be split across two cards.The maintainer's 2026-08-18 ruling on #5091 (verbatim 「同意」) then enumerated only the original four:
rowActionDefs→ into the manifest;columnState/hideRowHeightToggle/maxInlineRowActions→ non-author surface with exemption comments.onNavigatedoes not appear in it.So the ruling and the card no longer cover the same key set. Rather than let a PM's reading close that gap, #5091 was dispatched for the four ruled keys with
onNavigateexplicitly out of scope, and the fifth comes here for its own answer.Measured on
origin/mainread inside the
useNavigationOverlay({ navigation, objectName, onNavigate, onRowClick })call.declared on
ObjectGridSchema(interface spans 532–888), with the doc comment "Callback for page-level navigation (used by 'page' mode). Called with recordId and action ('view' | 'edit')."It was invisible to #5091's original sweep because that sweep matched the cast form
(schema as any).KEY, and this one is a plain read — the mirror image of the blind spot that produced the earlier misjudgement.The actual shape of the problem
It is not an undeclared key absorbed by a loose index signature (the corrected reading).
@object-ui/typesdeclares it deliberately and documents it. The problem is narrower and now sits in exactly one place:The renderer reads it and the TS type declares it, while the manifest surface —
GRID_QUERY_INPUTS, the designer panel, the generatedsdui-intrinsics.d.ts— denies it exists. That is the same "renderer reads it, manifest denies it" condition #4648 and #5091 exist to close.In the same
useNavigationOverlaycall,schema.navigationandschema.objectNameare both on the manifest surface; onlyonNavigateis not.The argument that survives the correction, and is now the strongest one
A schema is a serialisable document, and a function cannot survive a metadata round-trip. Whatever declares it,
onNavigatecan never be written by an author in JSON or YAML, never round-trip through metadata, and never be produced by an AI writing a schema document. A(recordId, action) => voidin a stored document is not expressible.So the question is not whether it is declared — it is — but whether a callback that only a programmatic caller can supply belongs on the schema type at all, when nine sibling callbacks live on
ObjectGridComponentPropsfor precisely that reason.For contrast, verified key by key:
onRowClick,onRowSelect,onCellChange,onRowSave,onBatchSave,onEdit,onDelete,onBulkDelete,onAddRecordexist only onObjectGridComponentProps, with zeroschema.on*read points.onNavigateis the one that is on both.Four-prism
ObjectGrid.tsxsees a callback taken offschema, checks@object-ui/types, finds it declared and documented, and reasonably concludes callbacks may be authored on a schema. It then emits metadata that silently does nothing. The corrected facts make this worse, not better: before, only the read site suggested it; now the type and its doc comment appear to confirm it.The options
onNavigatejoins its nine siblings onObjectGridComponentProps. Ends with one clean rule and restores the docs sentence as a universal. Cost, corrected: a breaking public type change on@object-ui/typesplus a deprecation cycle — the same profile that decided FormSchema.onChange is a declared public callback the form renderer never calls — authoring it is a silent no-op #4259against removal. Requires checking for callers passing it through a schema object.GRID_QUERY_INPUTSso all three surfaces agree. Cheapest to execute and makes the manifest match the type. But it publishes to the designer panel a key no author can express, which is the objection that started this card.PM recommendation: withdrawn. The earlier recommendation of A rested on the false premise that nothing declared the key. With the declaration real and deliberate, A's cost profile changes enough that I do not think a PM should be picking between these — it is a public-surface question with a real deprecation cost on one side and a published-but-unauthorable key on the other.
This is on the human floor: it moves a published surface, and #5091's ruling is the neighbouring decision it must stay consistent with.
Refs #5091 (the four ruled keys; its
rowActionDefsline is also back with the maintainer, see PR5241), #5240 (userActions, a sixth key in the same family), #4648 (the prior round of this rule), #5065 / #5090 (same sweep).