Skip to content

Optional first-class type field, and configurable display fields #13

Description

@DeLuke84

Motivation

This is the other half of #11, from the same angle as the mouse support in #8: the board is driven by agents, but a human operator looks at it periodically to see where things stand. For that glance there are two questions — what kind of task is this, and for a parent, what's in it and how are its children doing. #11 answers the second. This one is the first.

Type has no home in the model today. parent is a real field, so hierarchy is already first-class, but the thing that says what kind of node sits at each end of that edge is a freeform tag. And a tag can't reach the places where it would actually help:

  • It can't fill a display slot. [in-progress/medium] shows status and priority; there's no way to put the type there, because nothing tells the tool which of a task's tags is the type.
  • It can't be a group-by axis. --group-by tag exists, but it flattens every tag dimension into one list — type, size, milestone, whatever else a board uses — as peers, because they're indistinguishable from the tool's side.
  • It has no order. Even grouped, tags sort alphabetically: bug, epic, milestone, story rather than the hierarchy order those four actually have.

The priority slot is the one that stings in practice. Priority is the right thing to show on a board whose work order comes from a priority ladder. On a board where order comes from dependencies and blockers — which this tool supports directly via depends_on, --blocked and --unblocked — priority tends to sit at one value for everything, and the slot shows a constant while the attribute you navigate by isn't shown at all.

Proposal

1. Optional type, declared in config like the other enumerations

config.yml already declares statuses, priorities and classes as lists. types fits as the fourth, and an empty default means nothing changes for existing boards:

types:            # default: [] — feature off until a board opts in
  - milestone
  - epic
  - story
  - bug
  • type on the task: optional string, validated against the list when it's non-empty, ignored when empty.
  • --json gains type — additive.
  • create / edit gain --type; list gains a --type filter and --group-by type, which should be cheap given group-by already handles class and priority. A declared list also makes that grouping orderable instead of alphabetical.

2. Configurable display fields

Let the board choose what the chip shows instead of changing the default for everyone:

display:
  compact_fields: [status, priority]   # default, unchanged

Honored by list --compact, board, and the TUI card.

Non-goals

  • No auto-migration. Existing type-ish tags stay where they are; type arrives empty and gets backfilled by whoever wants it. An upgrade that rewrites every task file isn't worth it for this — a documented one-liner is enough.
  • No semantics attached to type. It doesn't gate parent/child (any task can have children today and should keep being able to), doesn't affect pick, doesn't imply an order, doesn't restrict statuses.
  • Not a replacement for tags. Boards happy with the tag convention keep working untouched — that's what the empty default is for.
  • No hierarchy validation (cycles, self-reference, existence) — same non-goal as Show child tasks when viewing an epic (show + TUI), like a Jira epic panel #11.

Open questions

  1. types as a config-declared list, or a freeform string with no list? I lean declared, for consistency with statuses/priorities/classes and because it gives grouping a defined order.
  2. Should display.compact_fields take an arbitrary list, or a fixed pair to keep the chip from growing?
  3. Does the TUI want type beyond the card chip — a filter or tab dimension — or is the chip plus --group-by type enough for v1?

For context

The board this comes from: ~110 tasks, milestone / epic / story / bug as tags, sizes as another tag set, order driven by dependencies rather than priority — so all 110 sit at medium, and the chip spends its slot on that while the type I'm actually scanning for is buried among the tags. Happy to implement after #11 lands, so the display change and the schema change stay in separate PRs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions