Skip to content

Commit fe027c2

Browse files
committed
fix(lint): walk kanban.titleField at calendar's level in the list-view position table
`POSITIONS` declares, per view face, which field-reference keys are walked and at what level. `kanban` was the only item-titled face with no `titleField` row, and since the key became authorable on `KanbanConfigSchema` a misspelt field name cleared the schema door, was walked by nothing, and left the board titled from the ADR-0079 display-name chain instead of the field the author named. The level is `warning`, the one `calendar` takes: the key is OPTIONAL on both schemas, and objectui's board (`resolveKanbanTitleField` -> `rec[titleField]` -> `getRecordDisplayName`) renders every card regardless. `timeline` and `gantt` spell the key required and take `error`; they are not the siblings this row copies. Claude-Session: https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3 Co-authored-by: Claude <noreply@anthropic.com>
1 parent a7bafc2 commit fe027c2

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
"@objectstack/lint": minor
3+
---
4+
5+
fix(lint): `list-view-field-unknown` walks `kanban.titleField` — the one item-titled face the position table never listed (#18565)
6+
7+
Clause-②: no
8+
9+
`POSITIONS` in `validate-list-view-field-refs.ts` declares, per view face, which field-reference keys are walked and at what level, and `kanban` was the only item-titled face with no `titleField` row. From #16894 the key is authorable on `KanbanConfigSchema`, so from that release a misspelt field name cleared the schema door, was walked by nothing, and the board fell back to the ADR-0079 record display name — a title the author did not ask for, on a board that renders correctly, with no gate reporting the miss. The byte-identical typo one block away on `calendar` or `timeline` was reported.
10+
11+
Measured on this branch, one list view carrying every walked position, one mutation at a time:
12+
13+
| probe | before | after |
14+
|:--|:--|:--|
15+
| `kanban.titleField` naming a field that does not exist | silent | `warning` `list-view-field-unknown` at `views[0].list.kanban.titleField` |
16+
| `kanban.titleField` naming a real field | silent | silent |
17+
| the other 51 walked positions | 51 reported, 1 silent (this one) | the same 51, each at its same severity |
18+
19+
Over the repo's own example apps (`app-crm`, `app-todo`, `app-multi-package`, `app-showcase`) the findings count is **0 before and 0 after**: five kanban blocks are authored there and none carries `titleField`, so nothing existing starts reporting. Injecting `titleField: 'zz_no_such_field'` into those same boards flips 0 → 1 warning in `app-crm` and `app-showcase`.
20+
21+
**`warning`, the level `calendar` takes — not the level of the two siblings that spell the key required.** `KanbanConfigSchema` declares `titleField` OPTIONAL (#16894 copied `CalendarConfigSchema` for this exact key and names `TimelineConfigSchema` / `GanttConfigSchema`, the two that spell it required, as the siblings it deliberately does not copy), and the board resolves an unresolvable name through the ADR-0079 display-name chain: measured in objectui `dda8f3815`, `resolveKanbanTitleField` returns the written name, the card reads `rec[titleField]`, finds nothing and falls to `getRecordDisplayName`. Every card still renders — the warning tier's own case in this rule's module note ("the renderer drops one decoration and renders the rest: an optional colour / title / tooltip / cover binding"), where `kanban.groupByField` is the error tier's, collapsing every card into one uncolumned lane.
22+
23+
No rule id, no severity and no message shape changes for any other position; `list-view-field-unknown` gains one more place it can be reported from.

‎packages/lint/src/validate-list-view-field-refs.ts‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,21 @@ const POSITIONS: Record<string, BlockPositions> = {
322322
kanban: {
323323
// `columns` here are the fields shown ON a card, not the board's columns:
324324
// a stale entry leaves one blank line on the card and the board renders.
325-
scalars: { groupByField: 'error', summarizeField: 'warning' },
325+
//
326+
// [#18565] `titleField` takes CALENDAR's level, not the level of the two
327+
// siblings that spell the key required. `KanbanConfigSchema` declares it
328+
// OPTIONAL (#16894, which copied `CalendarConfigSchema` for this exact key
329+
// and names `TimelineConfigSchema` / `GanttConfigSchema` — the two whose
330+
// rows below read `error` — as the siblings it deliberately does NOT
331+
// copy), and the board resolves a name no record carries through the
332+
// ADR-0079 display-name chain: measured in objectui `dda8f3815`,
333+
// `resolveKanbanTitleField` returns the written name, the card reads
334+
// `rec[titleField]`, finds nothing and falls to `getRecordDisplayName`.
335+
// Every card still renders, titled from a value the author did not ask
336+
// for — the warning tier's own case (one decoration dropped, the rest
337+
// rendered), where `groupByField` above is the error tier's (every card
338+
// collapses into one uncolumned lane).
339+
scalars: { groupByField: 'error', summarizeField: 'warning', titleField: 'warning' },
326340
lists: { columns: 'warning' },
327341
},
328342
calendar: {

0 commit comments

Comments
 (0)