MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-2098

Carry hasDescription on the work-item LIST row, so the /items row ⋯ menu can pick a leaf's Plan / Re-plan face by rule 2

Done
Description

The data half of MOTIR-2097's rule 2"a LEAF with a description shows Re-plan, not Plan" (Yue, 2026-08-04) — for the ONE surface that cannot satisfy it today.

Why it is its own card

MOTIR-2097 lands the whole rule from one shared function, and two of the three surfaces feed it everything it needs: the detail page holds item.descriptionMd, and the quick-view peek already carries descriptionMd on QuickViewData. The /items row ⋯ menu does not:

  • IssueRowData (app/(authed)/items/_components/issueRows.ts) carries kind, hasChildren and statusCategory — enough for rules 1 and 3, which is exactly what MOTIR-2097 ships there — but no description signal.
  • WorkItemListItemDto (lib/dto/workItems.ts) has no descriptionMd.
  • The tree read's forest CTE projects a fixed column set that does NOT include descriptionMd — stated in workItemRepository.ts's own docblock (the same constraint that already forces the filter AST to join work_item back onto the CTE for its matched flag). So this is a repository-level change, not a mapper tweak.

That makes it a different SIZE and a different RISK from MOTIR-2097's pure-UI predicate work, so it ships as its own PR rather than inflating that one.

What to build

Carry a boolean hasDescription — NOT the description body — from the list/forest read through to IssueRowData:

  • Project it in the forest CTE (a descriptionMd IS NOT NULL AND descriptionMd <> '' expression, so the CTE's column set grows by one BOOLEAN and never by the body text — the tree read fans out over many rows and the body is large).
  • Add it to WorkItemListItemDto and the flat-list read on the same terms, so both list shapes agree.
  • Thread it through the row shapers in issueRows.ts onto IssueRowData.
  • Feed it to the shared face function in WorkItemRowActions, replacing the named degrade MOTIR-2097 leaves behind (that card is required to comment the degrade rather than hide it — delete the comment as you satisfy it).

Acceptance criteria

  • A LEAF row (task / bug / subtask) with a description offers Re-plan in the ⋯ menu; the same row without one offers Plan / Expand. Rules 1 and 3 keep behaving exactly as MOTIR-2097 shipped them.
  • The face is decided by the SAME shared function MOTIR-2097 extracted — this card adds an input, it does not add a second copy of the rule.
  • An empty-string description counts as NO description (it is what an emptied editor writes).
  • The tree/list reads do not select the description BODY.

Known ripples (from the auto-memory corpus)

Adding a field to a shared list DTO breaks exact-shape .toEqual assertions in route and mapper tests — run the WHOLE affected test directories, not the single file you edited, and expect fixtures across tests/work-items, tests/api and the tree/list component tests to need the new key.

Blocked by: MOTIR-2097 — it creates the shared function this one feeds.