Skip to content

bug(llc): Kanban board renders zero cards always — frontend reads an 'items' key the board API never sends #13993

Closed

Description

@mrveiss

Found while reviewing PR #13955; independently verified. Supersedes the framing of #13954.

The Kanban board renders zero cards, in every column, always

Three defects stacked. The first alone is sufficient.

1. Response shape mismatch — the frontend reads a key the backend never sends.

  • autobot-backend/llc/api/boards.py:245-248 returns {"board": ..., "columns": columns_with_items}.
    There is no top-level items key; items are nested inside each column.
  • autobot-frontend/src/views/llc/KanbanBoardView.vue:226 — items.value = itemsData.items ?? [].
  • services/api.ts is a raw JSON passthrough — nothing rewrites the envelope.

So items is unconditionally [] and every column renders empty.

2. The payload omits the two fields the column/swimlane filters need.
_work_item_summary() (boards.py:95-107) emits neither assignee_type nor column_id.
grep -n "assignee_type" autobot-backend/llc/api/boards.py returns nothing. Even if (1) were fixed
by flattening the nested items, both humanItems() and agentItems() would still return empty.

3. The vocabulary mismatch — this is #13954.
KanbanBoardView.vue:159 filters on assignee_type === 'human'; the backend only ever writes
'user'. Real, but third in the chain.

Also: autobot-frontend/src/views/llc/workItemTypes.ts:40 types the field 'human' | 'agent' | null
— 'user' is missing entirely, so the correct fix is a type change, not only the comparison. And the
comment at workItemTypes.ts:11 ("column_id and assignee_type are only present on board API
responses") is inverted: they are present on the work-items response (api/work_items.py:382)
and absent from the board response.

Why this matters beyond the board

A feature shipped, has a view, has tests, and displays nothing — and nothing reported it. That is the
lying-detector class tracked in #13852: no error, no empty-state distinction between "no work" and
"never received any work". A board with zero cards looks exactly like a board with an empty backlog.

Ask

  1. Decide the canonical shape: flatten to a top-level items, or have the frontend read
    columns[].items. The backend already nests them, so the frontend read is probably the bug.
  2. Add assignee_type and column_id to _work_item_summary().
  3. Fix the vocabulary (bug(llc): Kanban swimlane humanItems() filters on assignee_type === 'human' but backend only ever writes 'user' #13954) and the workItemTypes.ts type + inverted comment.
  4. A test that fails when the board renders no cards for a board that has items — the missing guard
    that let all three land.

Activity

  1. mrveiss commented on Aug 11, 2026

    @mrveiss
    OwnerAuthor

    PR #14043 — awaiting CI + review.

    Canonical shape decision: the nested columns[].items response is correct; the frontend reads were the bug. Column membership is derived from each column's status_filter rather than stored on the item, so the grouping only exists in board context — flattening server-side would discard the relationship the endpoint exists to compute. Rationale in the PR body.

    All four Ask items delivered. Two things beyond the issue text, found by grepping every caller of the endpoint rather than only the two files named:

    Also corrected the workItemTypes.ts provenance comment twice: the original was inverted, and the first correction was still wrong. assignee_type is emitted by both the work-items response (work_items.py:381) and now the board-items response; only column_id is board-items-only.

    Closing #13954 here — its stated fix is fully delivered and no 'human' literal remains anywhere in the frontend.

    Filed, not fixed here:

    Mutation proof (4 mutations, red→restore→green) and all verification output are in the PR body.

  2. mrveiss commented on Aug 11, 2026

    @mrveiss
    OwnerAuthor

    Delivered by PR #14043, merged as 93f64153f. Verified in base: boards.py now emits assignee_type/column_id.

    Three causes, all verified empirically rather than taken from the report: the frontend read a top-level items key the endpoint never returns (items are nested per column), _work_item_summary() never emitted assignee_type/column_id, and the frontend filtered on assignee_type === 'human' while the backend only ever writes 'user' or 'agent'.

    SprintBoardView had the identical nesting bug against the same endpoint and was fixed in the same PR — one root cause, one change.

    Review confirmed the part that mattered: no writer of 'human' exists anywhere (checked every writer plus migrations and fixtures), so the 'user'-only filter cannot silently drop cards. The only "human" literal in the module belongs to an unrelated CoWorkerType enum.

    Follow-up #14044 — now that cards render, clicking one opens a detail panel with blank description, labels and acceptance criteria: the board payload omits them and WorkItemDetail never re-fetches. The backend has that data, so it reads as data loss.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions