Found by the os-dev seat while landing objectui#8365 (PR #9236). ⛔ Not claimed, not repaired there: it is a different package and a different renderer, i.e. validation surface outside that card's fence.
The defect — the same shape objectui#8365 just closed, one renderer over
plugin-view's generateViewSchema kanban branch resolves the lane and then spreads the rest of the config after its own groupBy:
const kanbanCfg = viewOptions.kanban || {};
const groupBy = kanbanCfg.groupByField || kanbanCfg.groupField || 'status';
const { columns: _c, groupByField: _gbf, groupField: _gf, titleField: _tf, conditionalFormatting: _cf, ...restKanban } = kanbanCfg;
return { type: 'object-kanban', ...baseProps, groupBy, titleField: ..., cardFields, ...restKanban, ... };
groupBy is not in that destructure, so a viewOptions.kanban.groupBy survives into restKanban and the trailing spread overrides the lane the branch just resolved from groupByField. That is exactly the defect objectui#8365 measured and closed in ListView.
Why it is a SECOND route, not a duplicate
generateViewSchema runs precisely when no host supplied renderListView — the authored object-view element — so it never passes through ListView and PR #9236's destructure fix does not reach it. The same distinction plugin-view's own calendar branch records for objectui#7029.
What PR #9236 already does cover
The CONTRACT half is global: @object-ui/types' view-level KanbanConfig mirror now declares groupBy as a named alias refusal pointing at groupByField, and the legacy options.kanban nesting takes the same message through a check. So a view carrying the key is refused at every validating door for BOTH routes. What remains here is a BEHAVIOUR gap, not a contract gap: a document that never went through a validator still re-points this renderer's lane.
Suggested repair
Add groupBy to the destructure, exactly as PR #9236 did for ListView, and pin it with the same distinguishing fixture (two DIFFERENT lane names, so the arm can fail):
viewOptions.kanban = { groupBy: 'LANE_FROM_STRAY_GROUPBY', groupByField: 'LANE_FROM_CANONICAL' }
=> the generated object-kanban node must carry LANE_FROM_CANONICAL
⚠️ One difference from the ListView twin worth measuring before writing the pin: this branch floors the lane at the literal 'status' when neither declared key is present, where ListView falls back to detectStatusField(objectDef). So the "stray key alone" control behaves differently here and should be measured rather than copied.
Dedup — declared rather than implied
One search_issues call over open AND closed issues in this repo, phrased as a sentence describing the defect: 22 results, top 10 read. The control fired — objectui#8365 itself came back first, so the reading is a reading. Nearest neighbours, neither of them this: objectui#7773 (both adapters writing the retired groupField ALONGSIDE groupBy onto the generated node — node-local, closed) and objectui#8213 (the producer that fed the ListView override, closed). No card names this branch's spread order.
Filed by the os-dev seat that delivered objectui#8365, session session_01UzHd6hDYatoDn17BuwKxnZ, recorded here as prose because an attribution footer does not survive issue creation.
Generated by Claude Code
Found by the
os-devseat while landing objectui#8365 (PR #9236). ⛔ Not claimed, not repaired there: it is a different package and a different renderer, i.e. validation surface outside that card's fence.The defect — the same shape objectui#8365 just closed, one renderer over
plugin-view'sgenerateViewSchemakanban branch resolves the lane and then spreads the rest of the config after its owngroupBy:groupByis not in that destructure, so aviewOptions.kanban.groupBysurvives intorestKanbanand the trailing spread overrides the lane the branch just resolved fromgroupByField. That is exactly the defect objectui#8365 measured and closed inListView.Why it is a SECOND route, not a duplicate
generateViewSchemaruns precisely when no host suppliedrenderListView— the authoredobject-viewelement — so it never passes throughListViewand PR #9236's destructure fix does not reach it. The same distinctionplugin-view's own calendar branch records for objectui#7029.What PR #9236 already does cover
The CONTRACT half is global:
@object-ui/types' view-levelKanbanConfigmirror now declaresgroupByas a named alias refusal pointing atgroupByField, and the legacyoptions.kanbannesting takes the same message through a check. So a view carrying the key is refused at every validating door for BOTH routes. What remains here is a BEHAVIOUR gap, not a contract gap: a document that never went through a validator still re-points this renderer's lane.Suggested repair
Add
groupByto the destructure, exactly as PR #9236 did forListView, and pin it with the same distinguishing fixture (two DIFFERENT lane names, so the arm can fail):ListViewtwin worth measuring before writing the pin: this branch floors the lane at the literal'status'when neither declared key is present, whereListViewfalls back todetectStatusField(objectDef). So the "stray key alone" control behaves differently here and should be measured rather than copied.Dedup — declared rather than implied
One
search_issuescall over open AND closed issues in this repo, phrased as a sentence describing the defect: 22 results, top 10 read. The control fired — objectui#8365 itself came back first, so the reading is a reading. Nearest neighbours, neither of them this: objectui#7773 (both adapters writing the retiredgroupFieldALONGSIDEgroupByonto the generated node — node-local, closed) and objectui#8213 (the producer that fed theListViewoverride, closed). No card names this branch's spread order.Filed by the
os-devseat that delivered objectui#8365, sessionsession_01UzHd6hDYatoDn17BuwKxnZ, recorded here as prose because an attribution footer does not survive issue creation.Generated by Claude Code