Skip to content

Project board: a finished card loses its title, its priority and the board it opens — the Done group reads #task-id #2198

Closed

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 8e88ea5310b4454c9e79b67d65bf3936
Branch: dev/3-board-done-rows
Base: 9ede925
At: 2026-11-02T16:15:32Z
Owner: Dev-3
Tier: T2

What happens today

On a Project board, every finished card in the Done group is drawn as #task-<id> with no priority, and it cannot be opened at all. The work-in-flight rows are fine; only the archive loses everything that lived on the task record.

Two facts meet here, both on live main 9ede9258:

  1. The row the host sends carries an id and who holds the card, not its text. core/src/host/project-board.js:494-518 pushes id, source, column, assignee, holder, speaksFor, updatedAt, taskClass, reworkOf, handoff, evidence, lease, audit, runId, nodeId — and no title, no priority, no board. The client therefore joins a second read: core/src/client/project-board.js:258-260 says so in words ("the row carries an id and who holds it, not its text"), and :291-292 builds title/priority from that joined record.
  2. That second read never contains a finished card. core/src/host/tasks.js:1379-1409 (case 'tasks') filters rows.filter(openTask), and openTask = (task) => !TERMINAL_MATCH.has(task.status) with TERMINAL_MATCH = {accepted, cancelled, failed} (core/src/host/tasks.js:77). Those are exactly the statuses the board puts in the Done column: core/src/shared/task-board.js COLUMN_OF maps accepted/cancelled/failed → done, and core/src/host/project-board.js:524-525 splits the rows on that column.

So for the Done group the join finds nothing, title is null, and the card falls back to its id at core/src/client/project-board.js:530 (row.title ?? '#' + row.id). The same hole makes the card unopenable: boardOfRow(row, task) (:154-165) returns null when there is no task record, so open stays undefined at :352/:488 and the card is not a button.

Reproduction (measured, not inferred)

On a clean tree of 9ede9258, with a real rt.projectBoard read and one accepted group card:

  • core/test/project-board.test.js — the row for that card has title === undefined; the same record is absent from rt.taskEndpoint('tasks', {}, null), because that read returns open cards only.
  • core/test/project-board-view.test.js — with the host's done rows and tasks: [], the view draws view.done.rows[0].title === null and the card text is #task-<id>; priority is empty; no board for the card to open.

Both fail on 9ede9258 before any change (not ok 1 - a finished card carries its title and priority on the row the Done column draws, and not ok 1 - #P-167: a finished card keeps its title and priority with no task record to join).

Expected behaviour

A finished card keeps what it was: its title, its priority, and the board it belongs to — the same three things a work-in-flight card shows, read from the row the host sends rather than from a second read that does not contain it. A reader looking at a Project's history sees "Ship the release · high", not "#task-4f3c9a1b2c8d7e6f".

The rows in flight keep working exactly as they do today; the joined read stays as the fallback for them.

Scope

  • core/src/host/project-board.js — the row carries title (empty → null), priority (via priorityOf, so a record written before the field existed reads normal for a reader who never set one), and board (boardOf(task)'s {kind, id}, or nothing for a workflow-carried row). No other field's meaning or order changes.
  • core/src/client/project-board.js — the row wins, the joined record is the fallback (text(row.title) || text(task?.title) || text(task?.note), and the same for priority); boardOfRow prefers the row's board and falls back to deriving it from the record. The :258 comment describing the old rule is corrected in the same edit.
  • Two tests: the host row shape, and the done view with tasks: [].
  • Regenerated core/client.js, the patches/ds-bot/* mirrors, changelog.d/<this issue>-board-done-rows.fixed.md, and one line each in docs/subsystems/core-host.md, docs/subsystems/core-client.md, and docs/subsystems/workflow.md (the last one because the finished-card row shape is documented there too).

Out of scope: columnOf/status semantics, the archive paging in kanban.js, the Bot's Tasks board (that is #2066's surface), and any change to what tasks returns.

If the second half (the card opening its board) turns out to need a larger change than a row field and a fallback, ship the first half and say so here — I will open the follow-up rather than grow this pull request.

Prior art / duplicates

Searched before opening (project board done column title, Done column #task, accepted card board row) plus the closed set around the archive:

  • #2066 / #2077 — the Bot's Tasks board footer missing the finished time (core/src/client/kanban.js); different read, different surface, already closed.
  • #1855 — the finished cards moved out of rows into their own done group; that is why this defect is reachable at all, not a fix for it.
  • #1029/#2045/#2047 — Done archive counts and paging, not row content.
  • #1713/#1716 — who may read the board and keeping a card on one board; those changed source, not the text or the board a finished card carries.

No open or closed issue covers a finished Project card losing its title, priority and board.

Acceptance

  1. The host row for an accepted (and for a cancelled/failed) card carries title, priority and the board when the record names one; a card with no title reads null, never the string "null" or "undefined".
  2. The Done group draws the card's real title and priority, and the card opens its board; with the joined record absent the view does not fall back to #task-….
  3. With the joined record present (a card in flight), nothing changes: same title, same priority, same board.
  4. The two new tests fail on 9ede9258 and pass after the fix; npm run verify green, patches check/canonical clean, arch-docs: OK.

Activity

  1. HugoXK commented on Nov 2, 2026

    @HugoXK
    ContributorAuthor

    Release

    Written-by: FlyBot Lead
    Released: 8e88ea5310b4454c9e79b67d65bf3936
    Reason: merged via PR
    At: 2026-11-02T18:55:14Z

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