linear-sop

Linear ticket management best practices. Use when creating issues, updating status, or attaching evidence. Provides evidence templates for dev/staging/done phases.

linear
sop

SKILL.md

GitHub

Linear SOP Skill

Purpose

Guide consistent Linear ticket management. Provides evidence templates for the mandatory dev/staging/UAT evidence policy.

When This Skill Applies

Invoke this skill when:

  • Creating new Linear issues
  • Updating ticket status
  • Attaching evidence to tickets
  • Parsing acceptance criteria
  • Working with UUIDs and issue IDs

Linear MCP Tools

Reading Issues

# Get issue by identifier
mcp__{{MCP_LINEAR_SERVER}}__get_issue({ id: "{{TICKET_PREFIX}}-459" })

# List issues with filters
mcp__{{MCP_LINEAR_SERVER}}__list_issues({
  team: "{{PROJECT_TEAM_NAME}}",
  state: "In Progress",
  assignee: "me",
})

Creating Issues

mcp__{{MCP_LINEAR_SERVER}}__create_issue({
  title: "feat(scope): description",
  team: "{{PROJECT_TEAM_NAME}}",
  description: "## Summary\n\n...",
  labels: ["feature", "sprint-1"],
  parentId: "parent-uuid",  // Optional - for sub-issues
})

Updating Issues

mcp__{{MCP_LINEAR_SERVER}}__update_issue({
  id: "{{TICKET_PREFIX}}-459",
  state: "Done",
})

Adding Comments

mcp__{{MCP_LINEAR_SERVER}}__create_comment({
  issueId: "{{TICKET_PREFIX}}-459",
  body: "**Dev Evidence**\n\n...",
})

Program Structure

For work that spans many issues, Linear has objects above the issue. Use them; do not flatten a program into a flat list of tickets.

The Hierarchy

Initiative          the program (one per program)
  └── Project       a Unit of Work — one coherent outcome
       ├── Milestone    an AI-DLC phase: Inception, Construction, Operations
       └── Issue        a Story
            └── Sub-issue   a Mob Elaboration task (created during Inception, not before)

Prerequisite: labels must already exist

Program build-out assumes these label namespaces are pre-created in the workspace. Create them before building the program, not during:

  • bolt:0 … bolt:N — which Bolt an issue belongs to
  • agent:* — the lead role (must match an actual agent name in .claude/agents/)

Labels are workspace-scoped in Linear — do not create team-scoped duplicates.

Streams

Linear sub-initiatives require an Enterprise plan. If your workspace has it, model program streams as sub-initiatives under the initiative. If it does not, encode the stream as project priority instead — highest-risk stream gets Urgent/High, follow-up stream gets Medium. Both are valid; pick based on your plan tier.

Dependency Wiring

Build the dependency DAG with issue relations:

mcp__{{MCP_LINEAR_SERVER}}__update_issue({
  id: "{{TICKET_PREFIX}}-XXX",
  blocks: ["{{TICKET_PREFIX}}-YYY"],       // this issue must land first
  blockedBy: ["{{TICKET_PREFIX}}-ZZZ"],    // this issue waits on that one
})

Use relatedTo for soft links that inform but do not block.

Wire so the enforcement lands before the thing it enforces — see the safe-ai-dlc skill for the four dependency-wiring heuristics.

Re-parenting existing issues

When a program absorbs tickets that already exist, update them into the project — never recreate them. Duplicates break traceability and split the evidence trail.

Evidence Policy (MUST)

Every issue requires evidence at each phase:

Phase Required? Content
Dev MUST Implementation proof
Staging MUST UAT validation (or N/A)
Done MUST Final verification

Evidence Templates

Dev Evidence Template

**Dev Evidence**

**PR**: https://github.com/{{ORG_NAME}}/{{REPO_NAME}}/pull/XXX
**Commit**: [short-hash]
**Branch**: {{TICKET_PREFIX}}-XXX-description

**Implementation:**

- [x] Feature implemented
- [x] Tests passing
- [x] Lint passing

**Verification:**

\`\`\`bash
yarn ci:validate

# Output: All checks passed

\`\`\`

Staging/UAT Evidence Template

**Staging Evidence**

**Environment**: Pop OS dev server
**URL**: http://pop-os:3000

**Validation Steps:**

1. Deployed to staging: [timestamp]
2. Smoke test passed: [yes/no]
3. Feature verified: [description]

**UAT Status:** [Passed/Pending/N/A]

If N/A, reason: [e.g., "Dev tooling only - no user-facing changes"]

Done Evidence Template

**Done Evidence**

**PR Merged**: https://github.com/{{ORG_NAME}}/{{REPO_NAME}}/pull/XXX
**Merge Commit**: [hash]

**Final Checklist:**

- [x] All acceptance criteria met
- [x] Documentation updated (if applicable)
- [x] No regressions detected

Acceptance Criteria Parsing

When reading issue descriptions, extract ACs:

## Acceptance Criteria

- [ ] User can perform action X
- [ ] System responds with Y
- [ ] Error handling for Z

Convert to testable checklist:

const acceptanceCriteria = [
  { criterion: "User can perform action X", verified: false },
  { criterion: "System responds with Y", verified: false },
  { criterion: "Error handling for Z", verified: false },
];

Status Workflow

Backlog -> Ready -> In Progress -> Testing -> Ready for Review -> Done

GitHub-Linear Auto-Sync

Tickets referenced in commit messages (e.g., [{{TICKET_PREFIX}}-123]) automatically move to Done when the PR merges. Child stories not referenced in any commit message must be manually closed after merge.

Best practice: Reference Feature-level tickets in commit messages. After merge, manually close orphaned child stories that weren't referenced.

Status Update Guidelines

From To When
Backlog Ready Sprint planning
Ready In Progress Work starts
In Progress Testing PR created
Testing Ready for Review Tests pass, UAT complete
Ready for Review Done POPM approval or auto-sync via PR merge

UUID Handling

Linear uses UUIDs internally. When working with APIs:

// Issue identifiers (human-readable)
const issueId = "{{TICKET_PREFIX}}-459";

// UUIDs (API operations)
const uuid = "ef6a5fa0-2b46-417f-8266-dea2d187b10a";

// Get UUID from identifier via MCP tool
// mcp__{{MCP_LINEAR_SERVER}}__get_issue({ id: "{{TICKET_PREFIX}}-459" })
// Returns issue object with .id property containing UUID

Common Operations

Link PR to Issue

PRs are automatically linked when:

  • Branch name contains {{TICKET_PREFIX}}-XXX
  • PR title contains [{{TICKET_PREFIX}}-XXX]

Create Sub-Issue

mcp__{{MCP_LINEAR_SERVER}}__create_issue({
  title: "Sub-task description",
  team: "{{PROJECT_TEAM_NAME}}",
  parentId: "parent-issue-uuid",
})

Query by Label

mcp__{{MCP_LINEAR_SERVER}}__list_issues({
  label: "sprint-1",
  team: "{{PROJECT_TEAM_NAME}}",
})

Authoritative References

  • Agent Workflow SOP: docs/sop/AGENT_WORKFLOW_SOP.md
  • Linear MCP Docs: Built into Claude Code
  • CONTRIBUTING.md: Workflow documentation