---
name: add-issue
description: >-
  Turn the current conversation, a PRD, a grilling session, or pasted notes into a single
  GitLab issue in turbine-platform/turbine. Use whenever the user says "add issue", "make an
  issue", "create an issue", "turn this into an issue", "turn the PRD into an issue", or wants
  to capture work as a ticket. Produces a short, plain-language issue (what / why / done-when),
  attaches it to a chosen epic (with suggestions), copies the epic's area label and milestone
  (override allowed), and — when run
  after a PRD — writes the issue link into that PRD (which is how the commit and release skills
  later find it, with no dependence on git branches). Always previews before creating.
---

# Add an issue

Capture one piece of work as a GitLab issue on the turbine roadmap. The reader is anyone — a
manager, a new hire, a stakeholder — not someone who sat in the design session. Even when the
input is a jargon-heavy PRD, the issue stays plain and user-facing.

Project: `turbine-platform/turbine` (project id `20196`). Group: `turbine-platform` (id `1254326`).
Just run `glab` — the PATH wrapper handles the corporate proxy automatically, no prefix.

## The template — keep it this short

```
<one sentence: what this delivers, in plain words>

<1-3 sentences: what actually changes for a user>

**Why:** <one sentence — why it matters>

**Done when:**
- [ ] <plain, checkable criterion>
- [ ] <plain, checkable criterion>
```

Two to four acceptance checkboxes, no more. If it sprawls past that, it's probably more than one
issue — split it. The `/release` skill turns these checkboxes into the MR's Test Plan, so write
them as things someone can actually verify.

## The rules

1. **Load `writing-clearly-and-concisely` first — always.** Then draft. Active voice, concrete
   words, omit needless words.

2. **No jargon, no inside-session language** (same as the epic skill). A PRD is full of internal
   terms — strip them. Cut ADR references, issue/PRD/Phase/slice references, ticket numbers,
   internal type/class names (Contribution, Extension, SPI, Resolvable…), file paths, and
   "as we discussed". Say what the work does for a user, not how it's built.

3. **Always ask which epic it belongs to** with an `AskUserQuestion` (single-select — an issue
   has at most one epic). List the open epics:

   ```
   glab api "groups/1254326/epics?per_page=100&state=opened"
   ```

   One option per epic (use its title), plus a "None — standalone" option. Pre-suggest the
   likely epic in the option descriptions based on the issue's content. The issue **inherits the
   chosen epic's `area::` label** — read it off the epic. If "None", ask which area applies
   (the 12: core, quality-checks, contracts, linting-and-validation, lsp, cli, api, orchestration,
   dashboard, onboarding, scaffolding, integrations).

   **Milestone — default from the epic, override allowed.** Milestones do NOT cascade from an epic
   to its issues automatically, so set it explicitly: read the chosen epic's milestone and default
   the issue to it. That copy is what makes "issues under an epic ship in its release" actually
   hold. Offer an override — a different open milestone (`glab api "groups/1254326/milestones?per_page=50&state=active"`)
   or none; a standalone issue with no epic may still take a milestone of its own. Read the epic's
   milestone via the work-item layer (REST doesn't expose it): get its `work_item_id`
   (`glab api "groups/1254326/epics/<EPIC_IID>"`), then:
   ```
   glab api graphql -f query='{ workItem(id:"gid://gitlab/WorkItem/<WORK_ITEM_ID>") { widgets { ... on WorkItemWidgetMilestone { milestone { id title } } } } }'
   ```
   The numeric id (trailing segment of the milestone's `gid`, or from the milestone list) is what
   you pass as `milestone_id` on the issue. A group milestone id works on a project issue.

4. **Always preview before creating.** Show the full issue — title, description, epic, area label,
   milestone, and target project — then a select to approve / change / cancel.

5. **PRD back-reference.** If this issue comes from a PRD (run right after `/to-prd`, or the user
   points at one), find that PRD under `ai-docs/plans/<topic>/prd.md` (confirm which if unclear),
   and after creating the issue add a line just under the PRD's title:

   ```
   **GitLab issue:** <issue web_url>
   ```

   If the issue isn't from a PRD, skip this.

## Flow

1. Load `writing-clearly-and-concisely`. Draft the issue into the template. Apply rule 2 hard.
2. Ask the epic (rule 3); derive the area label and default milestone from it.
3. Preview everything; wait for approve (rule 4).
4. Create the issue. Write the description to a temp file first (newlines + backticks), then `cat`:
   ```
   # description already written to /tmp/issue-body.md
   DESC="$(cat /tmp/issue-body.md)"
   glab api -X POST "projects/20196/issues" \
     -f title="<title>" \
     -f labels="area::<area>" \
     -f description="$DESC" \
     -f milestone_id="<MS_ID>"
   ```
   Drop the `milestone_id` line when no milestone applies; a group milestone's numeric id works here.
   Keep the response's `iid` (for display + the `#N` references) and `id` (global id, for the epic
   link) and `web_url`.
5. Attach to the epic (skip if "None"). Use the issue's **global `id`**, not its iid:
   ```
   glab api -X POST "groups/1254326/epics/<EPIC_IID>/issues/<ISSUE_ID>"
   ```
6. PRD back-reference (rule 5), if applicable — insert the `**GitLab issue:** <web_url>` line under
   the PRD title.
7. Report the issue URL and which epic it's attached to. Don't create or assume a git branch —
   the PRD link from step 6 is what ties future commits and the MR to this issue, branch or not.

## Example (the voice to match)

Title: `PAX cron runner for Turbine checks` — epic `Run Turbine checks from any scheduler`, area `orchestration`

> Let a team run Turbine's data-quality checks from a PAX cron job, the same way they already can from Airflow and Dagster.
>
> A scheduled PAX job starts the checks, waits for the result, and fails when a check fails — so a bad dataset stops the run instead of flowing downstream.
>
> **Why:** teams on PAX get the same safety net as the other schedulers, with no glue code to write.
>
> **Done when:**
> - [ ] a PAX cron job can run Turbine checks against a contract and report pass/fail
> - [ ] a failing check fails the job
> - [ ] a short setup guide and a working example exist
