---
name: add-epic
description: >-
  Turn the current conversation, a grilling session, or any pasted notes into a single
  GitLab roadmap epic in the turbine-platform group. Use this whenever the user says
  "add epic", "make an epic", "turn this into an epic", "create a roadmap epic", or wants
  to capture work just discussed as an epic. Produces a short, plain-language epic
  (what / why / done-when), asks which release milestone it targets (no deadlines), asks which existing epics it depends on,
  strips all jargon and internal references, and always previews before creating.
---

# Add a roadmap epic

Capture work as one concise GitLab epic on the turbine-platform roadmap. The reader is
anyone — a manager, a new hire, a stakeholder — not someone who sat in the design session.

Group: `1000078-app-keten-shared/applications/turbine-platform` (group id `1254326`).
Just run `glab` — a PATH wrapper handles the corporate proxy automatically, no prefix needed.

## The template — keep it this short

```
<one sentence: what changes, in plain words>

<2-4 sentences: what actually happens. Concrete. Concise and Clear>

**Why:** <one sentence — the payoff, why it's worth doing>

**Done when:** <one sentence — a condition someone could check off>
```

That's the whole epic. If it runs longer than ~8 lines plus the two bold lines, cut it.

## The four rules

1. **Always ask which release milestone it targets — a picker, no deadline.** Epics carry no due
   date here; the milestone is how an epic is slotted to a release. List the open milestones and
   present them with an `AskUserQuestion` (single-select), plus a "None — backlog" option for an
   epic not yet slotted to a release:

   ```
   glab api "groups/1254326/milestones?per_page=50&state=active"
   ```

2. **Always ask about dependencies** with an `AskUserQuestion` **multi-select**. First list
   the open epics:

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

   Build one option per existing epic (use its title). Pre-suggest the likely ones in the
   option descriptions based on the new epic's content — e.g. most feature work depends on
   the microkernel rebuild. The user may pick none.

3. **No jargon, no inside-session language.** The description must read clean to an outsider.
   Strip every one of these:
   - ADR references ("see ADR-0026"), issue/PRD/Phase/slice references, ticket numbers.
   - Internal type or class names (Contribution, Extension, SPI, Resolvable, RunContext…).
     Translate to plain words: "plug-in", "add-on", "the part that reads the database".
   - File paths, module names, and anything that only means something to the team.
   - References to "this session", "as we discussed", "the grilling above".
     When in doubt, say what it _does_ for a user, not how it's built.

4. **Always preview before creating.** Show the full epic — title, description, area label,
   milestone, dependencies — in the chat. Create only after the user says go.
   Use a multiple-choice gate for this.

## Pick the area label

Every epic carries exactly one scoped `area::` label (it colours and filters the roadmap).
Choose the single best fit; if it's genuinely unclear, ask. Valid labels:

`area::core` · `area::quality-checks` · `area::contracts` · `area::linting-and-validation` ·
`area::lsp` · `area::cli` · `area::api` · `area::orchestration` · `area::dashboard` ·
`area::onboarding` · `area::scaffolding` · `area::integrations`

## Flow

1. Load the `writing-clearly-and-concisely` skill first — always. Then draft the epic from
   the input into the template. Apply rule 3 hard, plus Strunk's rules: active voice,
   concrete words, omit needless words.
2. Pick the area label. Ask the milestone (rule 1).
3. Ask the dependency multi-select (rule 2).
4. Preview everything in chat. Show select for the user to pic between approve or change or cancel.
5. Create it. Write the description to a temp file first (it has newlines and backticks),
   then pass it through `cat` so nothing gets mangled:
   ```
   # description already written to /tmp/epic-body.md
   DESC="$(cat /tmp/epic-body.md)"
   glab api -X POST "groups/1254326/epics" \
     -f title="<title>" \
     -f labels="area::<area>" \
     -f description="$DESC"
   ```
   Keep the response's `iid`, `web_url`, and `work_item_id` (the last is needed for the milestone).
6. Set the milestone (skip if the user picked "None — backlog"). Epics take a milestone only
   through the GraphQL work-item layer — the REST epics endpoint silently ignores `milestone_id`.
   Use the milestone's global `id` (from the rule-1 list) and the epic's `work_item_id`:
   ```
   glab api graphql -f query='mutation { workItemUpdate(input: {id: "gid://gitlab/WorkItem/<WORK_ITEM_ID>", milestoneWidget: {milestoneId: "gid://gitlab/Milestone/<MS_ID>"}}) { errors } }'
   ```
7. For each dependency the user selected (its iid is `<DEP_IID>`), link it as "blocked by"
   so the new epic depends on it:
   ```
   glab api -X POST \
     "groups/1254326/epics/<NEW_IID>/related_epics" \
     -F target_group_id=1254326 -F target_epic_iid=<DEP_IID> -f link_type=is_blocked_by
   ```
   If the instance rejects `is_blocked_by`, retry with `-f link_type=relates_to`.
8. Report the new epic's web URL and its milestone.
