---
description: When a Linear-tracked story is finished (merged or abandoned locally), return to main, pull, delete the local story branch
alwaysApply: true
---

# Story end (Linear)

When the user **ends story work** on a ticketed branch—phrases like “end story”, “story is merged”, “clean up branch after NEO-…”, or they confirm the PR is **merged** to `main`—run this **git** sequence so local state matches the remote default branch.

## 1. Preconditions

- **Merged:** Prefer deleting the local branch only after **`main`** on the remote includes the story (PR merged). If the PR is **not** merged, `git branch -d` will refuse; use **`git branch -D`** only when the user explicitly wants to drop unmerged work.
- **Uncommitted changes:** Stash, commit, or discard before switching branches; do not leave a dirty tree without the user’s choice.

## 2. Steps (run in order)

1. **`git checkout main`**
2. **`git pull origin main`** (or `git pull` if `main` already tracks `origin/main` and that is correct for this repo)
3. **`git branch -d <story-branch>`** — use the branch that was used for the issue (first path segment should be the Linear issue id, e.g. `NEO-10-move-validation`). If Git reports “not fully merged”, confirm whether **`origin/main`** already contains the story (e.g. squash merge or follow-up commits only cherry-picked to `main`). If yes, **`git branch -D <story-branch>`** is OK **only with user confirmation** so local unpushed tip is not lost by mistake.

## 2a. When `main` is push-protected

If the user asks to **push** changes that sit on **`main`** and **`git push origin main` fails** (required PR / status checks), create a branch from current `main` (e.g. `chore/…`), **`git push -u origin`** that branch, then open the PR with the **GitHub MCP** **`create_pull_request`** tool and a title keyed per [commit-and-review](commit-and-review.md) **Opening a PR when the user asks** (or give the **`pull/new/...`** URL **and** remind them to fix the title to **`NEO-123:`**). **`git reset --hard origin/main`** if you had temporarily advanced local `main` so local `main` matches remote until the PR merges.

## 3. What not to do

- Do **not** delete **`main`** or **`origin/*`**.
- Do **not** assume the remote story branch should be deleted unless the user asks (many teams keep `origin/NEO-…` for history or delete via GitHub UI).

## 4. Linear issue status

- **Do not** call Linear `save_issue` to change **state** until the user has **explicitly** chosen the target status. Typical names here are **`In Test`** or **`Done`**; use `list_issue_statuses` (Linear MCP, server **`plugin-linear-linear`**) if names differ on your team.
- If the user only says “end story” / “merge cleanup” / similar **without** naming a target status: run the **git** steps in §2, then run **§4a** (required ask) and **wait for the user’s choice** before updating the issue. **Never assume Done** without that confirmation.
- **Exception:** If the **same user message** already names the status (e.g. “end story, move NEO-18 to **Done**”), you may update Linear after git cleanup without a second ask.
- When Linear MCP is available, perform the update with **`save_issue`** (`id` = issue identifier, `state` = chosen status).
- If MCP is unavailable or the update fails, tell the user and ask them to update Linear manually.

### 4a. Required ask (agents — do not skip)

After §2 (and any local branch deletes that succeeded), prompt for the **Linear next state** in a way that matches **story kickoff** blocking decisions: **selectable multiple choice when the product supports it**, not only free-form prose buried after long git output.

**Preferred (Agent mode):** Use Cursor’s **`AskQuestion`** tool (multiple-choice) as the **first** user-facing step after git, **before** a long git dump—or put a **one-line** git summary first, then **`AskQuestion`** immediately. Example question:

- **Prompt:** `Which Linear state should we set this story to?` (name the **issue key** in the prompt if known, e.g. **NEO-25**, or ask which issue in a second question if ambiguous.)
- **Options** (adapt labels to `list_issue_statuses` for the **Neon Sprawl** team—or the issue’s team—if names differ):
  - **`in-test`** → label **In Test**
  - **`done`** → label **Done**
  - **`skip`** → label **Skip — do not change Linear** (user can clarify in chat afterward)

After the user selects **`in-test`** or **`done`**, call **`save_issue`** with `state` matching that status (name or type from Linear). If they pick **`skip`**, do not call `save_issue` for state.

**Fallback (no `AskQuestion`, e.g. Ask mode):** Use the prose template: ask which **status name** and **issue key**, with **In Test** / **Done** / **Skip** spelled out.

Then give any **git** details (branch deleted, `main` ahead, etc.) **after** the question or below the choice result.

## Related

- [story-kickoff](story-kickoff.md) — start of story workflow  
- [git-workflow](git-workflow.md) — branch vs `main`  
- [linear-git-naming](linear-git-naming.md) — branch names  
- [commit-and-review](commit-and-review.md) — push and **GitHub MCP `create_pull_request`** only when the user requests it; PR title **`NEO-*:`** prefix
