# PipelineItem

## Description

PipelineItem is a generic work item that moves through stages on a pipeline. Each item has a title, optional description, current stage reference, assignee, priority (LOW/MEDIUM/HIGH/URGENT), optional due date, a position integer for ordering within a stage, and an auto-incremented `itemNumber` scoped to the pipeline (like GitHub issue numbers within a repository). Items belong to exactly one pipeline; any organizational scoping is carried by the pipeline or by consumer extension fields.

The item has an explicit `lifecycle` field orthogonal to the stage category. Lifecycle tracks the item's own readiness: DRAFT for items still being prepared by their creator (hidden from operational lists), OPEN for published items being worked on, and CLOSED when an operator (or domain wrapper) has explicitly closed the item. Reaching a DONE/CANCELED-category stage is no longer sufficient on its own to close the item — closing is always explicit. Domain modules can extend items with their own fields by holding a foreign key to PipelineItem, and may layer their own approval workflows on top (approval state lives on the domain entity, not on PipelineItem).

## Domain Model Definitions

### Model type

Stateful

#### State Transitions

```mermaid
stateDiagram-v2
    [*] --> DRAFT: CreatePipelineItem (asDraft=true)
    [*] --> OPEN: CreatePipelineItem (default)
    DRAFT --> OPEN: OpenPipelineItem
    OPEN --> CLOSED: ClosePipelineItem
    CLOSED --> OPEN: ReopenPipelineItem
```

| Operation | From | To | Command |
|-----------|------|----|---------|
| open | DRAFT | OPEN | [OpenPipelineItem](../command/OpenPipelineItem.md) |
| close | OPEN | CLOSED | [ClosePipelineItem](../command/ClosePipelineItem.md) |
| reopen | CLOSED | OPEN | [ReopenPipelineItem](../command/ReopenPipelineItem.md) |

### Command Definitions

- [CreatePipelineItem](../command/CreatePipelineItem.md) - Create a new item in OPEN or DRAFT lifecycle, placed in the first stage of the pipeline
- [UpdatePipelineItem](../command/UpdatePipelineItem.md) - Update mutable fields (title, description, assigneeId, priority, dueDate, position) of an existing item
- [MovePipelineItem](../command/MovePipelineItem.md) - Move an item to a different stage; never auto-closes
- [ReorderPipelineItem](../command/ReorderPipelineItem.md) - Change an item's position within its current stage, renormalizing sibling positions
- [DeletePipelineItem](../command/DeletePipelineItem.md) - Permanently delete an item together with its dependent rows
- [ClosePipelineItem](../command/ClosePipelineItem.md) - Explicitly close an OPEN item, setting lifecycle to CLOSED
- [OpenPipelineItem](../command/OpenPipelineItem.md) - Publish a DRAFT item, setting lifecycle to OPEN
- [ReopenPipelineItem](../command/ReopenPipelineItem.md) - Reopen a CLOSED item, returning it to OPEN lifecycle in the same stage

### Query Definitions

- [ListPipelineItemsByStage](../query/ListPipelineItemsByStage.md) - List items within a stage, ordered by position

### Models

- PipelineItem

### Invariants

- Title is required and must be non-empty
- Pipeline ID is required and must reference an existing ACTIVE pipeline
- PipelineStage ID is required and must reference a stage belonging to the item's pipeline
- Items are created in lifecycle OPEN by default; callers may opt in to DRAFT
- Items are created with default priority MEDIUM
- Items cannot be created on an ARCHIVED pipeline
- Position is required and must be an integer for ordering within a stage
- `itemNumber` is required and is never null on a persisted item; CreatePipelineItem always assigns it from the pipeline's monotonic counter. Unlike `Pipeline.itemNumberSeq` (nullable until the first item is issued), an item has no lifecycle state in which its number is unset
- Only OPEN items can be moved to a new stage; CLOSED items must be reopened first, DRAFT items must be opened first
- Moving an item to a DONE or CANCELED category stage does NOT change lifecycle — closing is an explicit action via ClosePipelineItem
- Only DRAFT items can be opened (published)
- Only OPEN items can be closed
- Only CLOSED items can be reopened
- CLOSED items cannot be updated; they must be reopened first
- Only OPEN items can be reordered within their stage
- Priority must be one of LOW, MEDIUM, HIGH, or URGENT
- Assignee ID is optional; when the consuming app injects `userManagement.getUser`, it must reference an existing user

### Relationships

- **Belongs To Pipeline**: Each item belongs to a pipeline via `pipelineId`
- **Belongs To PipelineStage**: Each item is in a stage via `stageId`
- **Has Many PipelineStageTransition**: PipelineStage movements are recorded in PipelineStageTransition entries via `itemId`
- **Has Many PipelineItemComment**: User-authored comments on the item are linked via `itemId`
- **Has Many PipelineItemChange**: All non-stage audit events (content edits, field changes, lifecycle transitions, label attach/detach) are linked via `itemId`
- **Referenced By PipelineItemLabel**: Label attachments reference the item via `itemId` on the PipelineItemLabel join table
- **References User**: Each item optionally references an assignee via `assigneeId` from the user-management module
