Skip to content

bug(plugin-view): a stray groupBy in viewOptions.kanban overrides the lane generateViewSchema just resolved — the second route, untouched by objectui#8365 #9242

Description

@os-tesla

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

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions