---
name: release
description:
  "Pre-push quality gate + GitLab MR creation via glab for this repo. Runs
  ruff/ty/pytest (never adds noqa/type:ignore without explicit approval), stages & commits
  via /commit, pushes the branch, and creates the GitLab MR with a user-facing description —
  plain-language changelog sections (Added / Changed / Fixed / Removed), stripped of every
  PRD / ADR / issue-file / internal reference, the same outsider voice as /add-epic. Repo-local:
  adds Closes #N to the MR so the linked GitLab issue auto-closes (moves to Done) on merge.
  GitLab-aware throughout glab, never gh; MR, never PR."
roles:
  - developer
---

# Release

Quality gate that validates, fixes, commits, pushes, and opens a GitLab merge request. Strict-order phases: ruff → ty → pytest → commit → MR description → push → MR.

This is the turbine repo-local release skill — it supersedes the global one. Same flow, plus it closes the linked GitLab issue on merge.

Iron laws still bind: every phase's pass-claim is backed by reading fresh output; non-trivial pytest failures route through `/diagnose`; any suppression-flag push-back goes through review.

## Platform Enforcement

**GitLab only.** `glab` is wrapped on PATH to route through the corporate proxy automatically — just call `glab`, no prefix. Never call `gh`. Never say "PR".

## Workflow

Execute these phases **in strict order.** A phase must pass before moving to the next.

### Phase 1 — Ruff

```bash
uv run ruff check .
```

Fix violations in source (no suppressions). Re-run until clean.

- **NEVER** add `# noqa` or extend `[tool.ruff] ignore`. If you think suppression is the only option, STOP and escalate via `AskUserQuestion`.

### Phase 2 — Type Check

```bash
uv run ty check
```

Fix by correcting code or adding proper annotations. Re-run until clean.

- **NEVER** add `# type: ignore` / `# ty: ignore`. Same escalation as Phase 1.

### Phase 3 — Tests

```bash
uv run pytest
```

- **Small/obvious fixes** (caused by your Phase 1/2 edits): fix directly, re-run.
- **Large/unclear failures:** STOP, route through `/diagnose`.

### Phase 4 — Stage, Review, Commit

Invoke the `/commit` skill workflow (the repo-local one). It handles the test pre-gate, Conventional Commits, the `Refs #N` issue footer, the confirmation dropdown, and the pre-commit hook. If `/commit` reports nothing to commit, continue to Phase 5.

### Phase 5 — Draft the MR description (user-facing)

Load the `writing-clearly-and-concisely` skill for all prose here.

The MR description is read by an outsider — a manager, a new hire, a stakeholder — not by someone
who sat in the design session or read the PRD. Write what changed for a user, in plain words, never
how it was built. Same voice and same jargon ban as `/add-epic`.

1. Read what actually changed:
   ```bash
   git log --oneline main..HEAD
   git diff --stat main..HEAD
   ```

2. Strip every internal reference (same rule as `/add-epic` and `/add-issue`):
   - No PRD, ADR, Phase, slice, or issue-file references; no ticket numbers, file paths, or module names.
   - No internal type or class names (Contribution, Extension, SPI, Resolvable, RunContext…) — say what it does in plain words.
   - No "this session", "as we discussed", "the plan above".

3. Sort the changes into changelog sections — the same set as `CHANGELOG.md`. Include only the
   sections that have content, in this order. One terse, plain bullet per change, imperative, no
   trailing period:
   ```markdown
   ### Added
   - <new capability, in plain words>

   ### Changed
   - <what behaves differently now>

   ### Fixed
   - <what was broken and now works>

   ### Removed
   - <what's gone>
   ```
   Lead with a `### Breaking Changes` section only when something needs migration.

### Phase 6 — Push and Create MR

1. **Push:**

   ```bash
   git push -u origin HEAD
   ```

2. **Find the linked GitLab issue(s) — from the PRD, not the branch.** This work belongs to one
   or more PRDs under `ai-docs/plans/<topic>/`. Each PRD carries a back-reference line written by
   `/add-issue`, just under its title:

   ```
   **GitLab issue:** https://…/turbine-platform/turbine/-/issues/<iid>
   ```

   Identify the PRD(s) this release covers (from the commits, the issue files, or the conversation —
   never assume the branch), and pull each `<iid>`:

   ```bash
   # for each PRD this release covers
   grep -hoE 'issues/[0-9]+' ai-docs/plans/<topic>/prd.md | grep -oE '[0-9]+'
   ```

   The MR description MUST include one `Closes #<iid>` line per issue found. On merge to the default
   branch GitLab auto-closes each — moving the issue to Done — and links this MR to it. This is the
   only place the close keyword belongs (never in commits). If you genuinely can't tie the release
   to a PRD/issue, ask the user rather than guessing; if there's truly none, skip the line.

3. **Assemble the MR body.** Put the `Closes #<iid>` line(s) from step 2 first — one per issue —
   so GitLab parses them, then the user-facing changelog sections drafted in Phase 5:

   ```markdown
   Closes #<iid>

   ### Added
   - <plain bullet>

   ### Changed
   - <plain bullet>

   ### Fixed
   - <plain bullet>

   ### Removed
   - <plain bullet>
   ```

   Include only the sections that have content. Drop the `Closes` line(s) when no PRD/issue applies.
   No Summary-of-issues, no Test Plan, no PRD / ADR / issue-file references — the body reads clean to
   an outsider, exactly as drafted in Phase 5.

4. **Create the MR via `glab`:**

   ```bash
   glab mr create \
     --title "<conventional-commits title, under 72 chars>" \
     --description "$(cat <<'EOF'
   <the MR body from step 3, including the Closes #N line>
   EOF
   )" \
     --source-branch "$(git branch --show-current)" \
     --target-branch "main"
   ```

   - Title: conventional-commits format, under 72 chars.
   - Pass the body via HEREDOC so formatting is preserved.

5. **Open the MR URL:**

   ```bash
   glab mr view --web
   ```

   Fallback:

   ```bash
   MR_URL=$(glab mr view --output json | python -c 'import sys, json; print(json.load(sys.stdin)["web_url"])')
   open "$MR_URL"
   ```

6. **Update the backlog.** Invoke `/backlog done <prd-name> <branch>` if a PRD backlog applies.

## Constraints

### MUST

- Run all three checks in order (ruff → ty → pytest)
- Fix issues by correcting code, not suppressing warnings
- Use `glab` for MR creation — never `gh`
- Put `Closes #<iid>` in the MR description for each PRD/issue this release covers (found via the PRD, not the branch)
- Write the MR body as user-facing changelog sections (Added / Changed / Fixed / Removed), stripped of every PRD / ADR / issue-file / internal reference
- Show the MR URL

### MUST NOT

- Add `# noqa` / `# type: ignore` without explicit approval
- Commit without approval (via `/commit`)
- Skip any of the three check phases
- Use `git add .` / `git add -A`
- Add `Co-Authored-By` lines
- Force push
- Call `gh` — GitLab only, `glab`, MR not PR
