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-70

2.1.1 Issue-type metadata + the kind→type mapping

Done
Description

Estimate: 12m · Depends on: 1.4.2

Story 1.4's work_item.kind column already holds epic/story/task/bug/subtask. This Subtask adds the product-facing type layer: a single source of truth (a typed module, e.g. lib/issues/issueTypes.ts) mapping each user-facing issue type to its metadata — display label, icon, color token, and the set of allowed child types. The five v1 issue types are epic, story, task, bug, subtask — the same five Jira ships by default, and exactly the five values Story 1.4's WorkItemKind enum + DB triggers already enforce, so the metadata map stays total over the kind enum (a subtask row is a legal DB state, so any picker/icon/validation lookup must resolve for it). (Amended after Subtask 2.1.1 review — the original card under-scoped this to four and excluded subtask; corrected to five.) (The planning-side type column — code/design/copy/legal — is a separate axis owned by the AI layer and is NOT what this Subtask touches.)

Why a metadata module, not a DB table: the type set is small, fixed for v1, and read on nearly every render (icons, pickers, validation). A typed in-code map gives compile-time safety and zero query cost. If per-project custom issue types become a requirement later, this module is the single place that grows into a table-backed lookup — but YAGNI for v1 (durable shape: a typed constant, not a premature config table).

Acceptance criteria

  • A typed module exports the five issue types with: label, icon (lucide component ref), color token (from the design system), and allowedChildTypes.
  • The allowed-children map encodes: epic → [story, task, bug]; story → [task, bug, subtask]; task → [bug, subtask]; bug → [subtask]; subtask → []. (Inverts Story 1.4's kind-parent constraint incl. subtask.parent ∈ {story, task, bug}; this is the product-readable form of it. Note bug is NOT a leaf — subtask is the single leaf.)
  • A helper canParent(parentType, childType): boolean the service layer uses for validation.
  • Unit tests over canParent for every legal + illegal pair.

Context refs

  • prisma/schema.prisma — the work_item model + kind enum from Story 1.4
  • motir-core/CLAUDE.md — 4-layer rule
  • Design-system color tokens + icon set (Story 1.0.5)