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
Found while implementing #5270 (the named-view sort arity fix). Filed unassigned, not claiming. Deliberately NOT fixed there — #5270's ruling is the arity of the slot the view sort is written into, and this is a different mechanism (a key name that no reader knows) whose correct fix is not mechanical. See "Why this needs adjudication" below.
Verified on origin/main @ 12841b617.
The declaration
packages/plugin-view/src/ObjectView.tsx:206-214 — the host-composition views prop:
QuerySortEntry — the shared sink (packages/core/src/utils/sort-query.ts)
order
ObjectViewProps.views[].sort
direction
Nothing reads direction
activeView is the resolved views entry (ObjectView.tsx:551) and its sort reaches exactly three consumers, none of which knows the word:
:611 non-grid fetch — $orderby: sort, raw. serializeOrderBy (packages/data-objectstack/src/index.ts:341) folds each entry as shorthand(item.field, item.order), and String(undefined).toLowerCase() !== 'desc', so every entry is ascending.
:1244mergedSort, handed to the delegated renderListView schema's sort key.
Counter-probed: grep -n direction packages/plugin-view/src/ObjectView.tsx returns only the declaration at :211, an unrelated prose use at :342, and <Drawer direction="right"> at :1158 — while viewSort in the same file returns 3 hits, so the zero is a reading and not a bad grep.
Consequence
A host that composes views={[{ id, label, type: 'grid', sort: [{ field: 'created_at', direction: 'desc' }] }]} — the exact shape the prop declares — gets an ascending list, and (on the grid path) an ascending arrow above it. There is no failure signal: the declaration says the value is well-formed, and the direction is dropped at three independent readers rather than rejected at one.
The spelling is live, not theoretical: packages/plugin-view/src/index.tsx:179 registers sort: [{ field: 'name', direction: 'asc' }] as a defaultProps example, and packages/app-shell/src/views/view-config-adapter.test.ts round-trips { field, direction } fixtures through the studio adapter (which itself is spelling-agnostic — sort?: unknown[]).
Distinct from SortUI, which legitimately owns direction on its ownSortUISchema and converts at its boundaries (SortUI.tsx:54 / :71). This issue is only about the views prop.
Why this needs adjudication rather than a one-line fix
#4869 already ruled on this exact class, for defaultSort:
direction is a declaration bug → the prop becomes order, matching every other sort surface, and the two in-repo direction producers listed above are corrected. Cost: a breaking change to a public prop's shape (objectui ships its own breaks as minor per AGENTS.md §版本号策略), and any external host spelling direction starts failing loudly instead of quietly.
Route 2 is the one that makes AI-authored composition hard to get wrong — one spelling, declared = enforced — but it is a public-surface break and should not be taken by a dev agent on its own authority.
Dedup
Searched open issues (views sort direction, ObjectViewProps sort, sort direction spelling, plus the file path). Nothing on this. Related: #4869 (the sort-sink convergence card, which names this class), #5270 (the arity of the grid slot, same expression, different mechanism), #5269 (the table.columns forwarding gap, same file).
Blocked-by: #4869 — the sink's contract is the thing route 1 would extend, so that card's shape should settle first.
Found while implementing #5270 (the named-view
sortarity fix). Filed unassigned, not claiming. Deliberately NOT fixed there — #5270's ruling is the arity of the slot the view sort is written into, and this is a different mechanism (a key name that no reader knows) whose correct fix is not mechanical. See "Why this needs adjudication" below.Verified on
origin/main@12841b617.The declaration
packages/plugin-view/src/ObjectView.tsx:206-214— the host-compositionviewsprop:Note
direction. Every other sort surface in the repo spells the same fieldorder:SortConfig(packages/types/src/objectql.ts:212)orderNamedListView.sort(:1579)orderObjectGridSchema.sort/.defaultSort(:578/:673)orderQuerySortEntry— the shared sink (packages/core/src/utils/sort-query.ts)orderObjectViewProps.views[].sortdirectionNothing reads
directionactiveViewis the resolvedviewsentry (ObjectView.tsx:551) and itssortreaches exactly three consumers, none of which knows the word::611non-grid fetch —$orderby: sort, raw.serializeOrderBy(packages/data-objectstack/src/index.ts:341) folds each entry asshorthand(item.field, item.order), andString(undefined).toLowerCase() !== 'desc', so every entry is ascending.:1078the grid path — after A named view'ssortarray is forwarded intogridSchema.defaultSort, declared a SINGLE{ field, order }— ObjectGrid re-wraps it andparseSchemaSortdrops it, so the grid shows no sort at all #5270 this reachesObjectGridSchema.sort, whereObjectGridbuilds`${s.field} ${s.order}`(ObjectGrid.tsx:1117-1119) → the wire string"name undefined", andparseSchemaSort(:69) reads a missingorderas ascending, so the header draws an ascending arrow.:1244mergedSort, handed to the delegatedrenderListViewschema'ssortkey.Counter-probed:
grep -n direction packages/plugin-view/src/ObjectView.tsxreturns only the declaration at:211, an unrelated prose use at:342, and<Drawer direction="right">at:1158— whileviewSortin the same file returns 3 hits, so the zero is a reading and not a bad grep.Consequence
A host that composes
views={[{ id, label, type: 'grid', sort: [{ field: 'created_at', direction: 'desc' }] }]}— the exact shape the prop declares — gets an ascending list, and (on the grid path) an ascending arrow above it. There is no failure signal: the declaration says the value is well-formed, and the direction is dropped at three independent readers rather than rejected at one.The spelling is live, not theoretical:
packages/plugin-view/src/index.tsx:179registerssort: [{ field: 'name', direction: 'asc' }]as adefaultPropsexample, andpackages/app-shell/src/views/view-config-adapter.test.tsround-trips{ field, direction }fixtures through the studio adapter (which itself is spelling-agnostic —sort?: unknown[]).Distinct from
SortUI, which legitimately ownsdirectionon its ownSortUISchemaand converts at its boundaries (SortUI.tsx:54/:71). This issue is only about theviewsprop.Why this needs adjudication rather than a one-line fix
#4869 already ruled on this exact class, for
defaultSort:So the two candidate routes are a decision, not a refactor:
directionis a declared authoring surface → it belongs in the sink's contract (convertSortToQueryParams), andObjectViewtranslates at the prop boundary. Cost: a third accepted spelling repo-wide, against the convergence [finding] ObjectView 是最后一处不走共享 sort sink 的读点 ——$orderby: sort原样透传,归一化外包给了某一个 adapter #4869 is driving.directionis a declaration bug → the prop becomesorder, matching every other sort surface, and the two in-repodirectionproducers listed above are corrected. Cost: a breaking change to a public prop's shape (objectui ships its own breaks asminorper AGENTS.md §版本号策略), and any external host spellingdirectionstarts failing loudly instead of quietly.Route 2 is the one that makes AI-authored composition hard to get wrong — one spelling, declared = enforced — but it is a public-surface break and should not be taken by a dev agent on its own authority.
Dedup
Searched open issues (
views sort direction,ObjectViewProps sort,sort direction spelling, plus the file path). Nothing on this. Related: #4869 (the sort-sink convergence card, which names this class), #5270 (the arity of the grid slot, same expression, different mechanism), #5269 (thetable.columnsforwarding gap, same file).Blocked-by: #4869 — the sink's contract is the thing route 1 would extend, so that card's shape should settle first.