# CreatePipelineStage

## Permission Scope

stage

## Overview

Creates a new stage on a pipeline at a specified position. Stages define the columns of a pipeline and are ordered by position. Each stage has a category (NOT_STARTED, IN_PROGRESS, DONE, CANCELED) that classifies the stage for cross-pipeline reporting; it does not affect item lifecycle behavior.

## Business Rules

- Pipeline must exist
- Pipeline must be ACTIVE (not ARCHIVED)
- Pipeline must not be locked — locked pipelines keep the lane template seeded at creation (see CreatePipeline `stages`), unlike user-configurable pipelines
- Name is required and must be non-empty
- Name must be unique within the pipeline
- Position is required and is treated as a 1-based slot index, consistent with ReorderPipelineStage: out-of-range values are clamped, and existing sibling positions are renormalized to stay contiguous so two stages never share a position
- Category is required and must be a valid enum value (NOT_STARTED, IN_PROGRESS, DONE, CANCELED)
- Color is optional
- Consumer extension fields (declared via the `fields` extension point) are passed through to the insert

## Process Flow

```mermaid
flowchart TD
    A[Receive createPipelineStage input] --> B{Pipeline exists?}
    B -->|No| C[Return PIPELINE_NOT_FOUND]
    B -->|Yes| D{Pipeline ACTIVE?}
    D -->|No| E[Return PIPELINE_ARCHIVED]
    D -->|Yes| DD{Pipeline is locked?}
    DD -->|Yes| EE[Return PIPELINE_LOCKED]
    DD -->|No| F{Name non-empty?}
    F -->|No| G[Return INVALID_NAME]
    F -->|Yes| H{Name unique within pipeline?}
    H -->|No| I[Return DUPLICATE_STAGE_NAME]
    H -->|Yes| J{Category valid?}
    J -->|No| K[Return INVALID_CATEGORY]
    J -->|Yes| L[Clamp position to slot range]
    L --> M[Create stage at slot]
    M --> N[Renormalize sibling positions]
    N --> O[Return created PipelineStage]
```

## External Dependencies

- None

## Error Scenarios

- **PIPELINE_NOT_FOUND**: Specified pipeline ID does not exist
- **PIPELINE_ARCHIVED**: Pipeline is archived
- **PIPELINE_LOCKED**: Locked pipeline lanes are fixed to the template seeded at creation and cannot be modified
- **INVALID_NAME**: Name is empty or blank
- **DUPLICATE_STAGE_NAME**: A stage with the same name already exists on the pipeline
- **INVALID_CATEGORY**: Provided category is not a valid enum value

## Test Cases

- creates stage on active pipeline
- clamps an out-of-range position to the end without touching siblings
- inserts at a middle slot and renormalizes trailing sibling positions
- returns error when pipeline not found
- returns error when pipeline is archived
- returns error when pipeline is locked
- returns error when name is empty
- returns error when stage name duplicates another on the same pipeline
- returns error when category is invalid
