---
name: glab-issue-create
description: "Generate actionable GitLab issues from code context, specs, bugs, or refactoring needs. Use when the user says /glab-issue-create, /glab-issue, /issue, 'create a ticket', 'create an issue', 'write a ticket', or needs to formalize work into a GitLab issue."
argument-hint: "[issue title or description] [--from-airtable <recID> to seed from an Airtable support ticket]"
allowed-tools:
  - Read
  - Glob
  - Grep
  - Bash
  - AskUserQuestion
---

Generate an actionable GitLab issue from the provided context (code, specs, bugs, refactoring) and create it directly via the `glab` CLI.

## Required tools

- `glab`

Run `pysae-ai-tools tools require <tools>` before starting; if it exits non-zero, abort and report the install command from stderr to the user.

## Mode detection

Detect the execution context using `detect_context`:
```bash
CTX=$(pysae-ai-tools internal detect-context)
IS_CI=$(echo "$CTX" | jq -r '.is_ci')
PROJECT_ID=$(echo "$CTX" | jq -r '.project_id // empty')
PROJECT_PATH=$(echo "$CTX" | jq -r '.project_path // empty')
```

In CI mode (`IS_CI` is `true`):
- **Never use `AskUserQuestion`** — skip the confirmation step (Step 6) and create the issue directly with auto-detected values

## Airtable-seeded mode (`--from-airtable <recID>`)

When `$ARGUMENTS` contains `--from-airtable <recID>`, the issue is seeded from an existing **Airtable support ticket** (Customer Service base). Typical flow: `/support-ticket-create` has already created the Airtable ticket, and we now propagate it to GitLab for the dev team. All the standard rules below still apply — we just pre-fill some fields and add two extra labels.

### Extra steps (before the normal workflow)

1. **Read the Airtable ticket** via MCP Airtable (`mcp__airtable__get_record` or equivalent) on base `app79vpJ07qFIOEm1`, table `tblHjCvyOcdq0Kw0z`, record `<recID>`. Extract: `Nom`, `Sujet`, `Criticité`, `Impact`, `Notes`, `Contact`, `Compte`. See [../references/support-airtable.md](../references/support-airtable.md).
2. **Map `Sujet` → GitLab project** and **`Criticité` → priority label** from [../references/support-vocabulary.md](../references/support-vocabulary.md#sujet-airtable--repo-gitlab). These override any auto-detection from the context.
3. **Pre-fill the title** with the English translation of the Airtable `Nom` (always English — translate if FR).
4. **Pre-fill the description using the project's `bug.md` template** (loaded dynamically — see [MR templates / Issue templates](#gitlab-issue-templates-dynamic) below). **Description body in French**, title stays English. If the Airtable `Notes` are already in French, reuse them as-is; if they are in English (rare), translate them to French. Always preserve GitLab file links, technical terms, code snippets, and `group_id` values verbatim — do not translate identifiers.

   **Mapping Airtable Notes (3-parts) → sections du template `bug.md`** :

   | Source dans la Notes Airtable | Section du template `bug.md` |
   |---|---|
   | Observations Patrick — comportement observé, page/action concernée | **🧩 Contexte** (1-2 phrases : où, quoi, pour qui) |
   | Observations Patrick — captures, logs d'erreur, IDs Datadog | **📸 Éléments de diagnostic** (logs, captures) |
   | Observations Patrick — ses tests, appels API, URLs testées | **🔁 Étapes pour reproduire** (numérotées) + **🔧 Informations techniques → URL ou Endpoint concerné** |
   | Observations Patrick — comportement erroné précis | **❌ Résultat observé** |
   | Comportement attendu (déduit du contexte ou inféré du code) | **✅ Résultat attendu** |
   | Environnement (prod / dev / review), client/réseau impacté | **🔧 Informations techniques** (env, version app, navigateur si pertinent) |
   | Liens utiles — Datadog, Intercom, GitLab source | **📸 Éléments de diagnostic** (en bas, sous forme de bullets `- Datadog : <url>` / `- Intercom : <url>` / `- Code source : <url>`) |
   | Pré-analyse Claude — Cause racine / Chemin d'exécution / Quoi faire | **Section additionnelle `## 🧠 Pré-analyse`** ajoutée juste **avant** la ligne `**Airtable ticket url :**` (le template `bug.md` ne couvre pas cette analyse — on l'ajoute pour les devs) |

   La ligne `**Airtable ticket url :**` est **déjà dans le template `bug.md`** (commentée par `_(If issue is ":telephone_receiver: Support" related)_`). Remplir avec l'URL construite à l'étape 5.
5. **Fill in the Airtable interface URL** in the template's placeholder line `**Airtable ticket url :**` (already present at the bottom of `bug.md`). Build the URL from `recID` — see [support-airtable.md § URL interface Airtable](../references/support-airtable.md#url-interface-airtable-obligatoire-dans-les-issues-gitlab). Replace the placeholder URL with the constructed one, do not duplicate the line.
6. **Add two extra labels** to the normal set (do not replace them): `~"workflow::To Do"` (board column) and `~"Support 📞"` (group-level label on the `pysae` group — automatically available on every project, never invent it as a project label). The full label set becomes:
   ```
   ~<domain> ~type::bug ~priority::<P1|P2|P3> ~"workflow::To Do" ~"Support 📞" ~augmented
   ```
   Note: in Airtable-seeded mode the board column is **always** `workflow::To Do` (the bug came from a real client incident, scoped via `support-bug-investigate`, and is queued for immediate work — never `Refinement` or `Ready`).
7. **Skip epic matching** (support bugs are not attached to roadmap epics).

### Post-creation steps (after `glab issue create`)

8. **Update the Airtable ticket** via MCP Airtable: append the GitLab issue URL to the `Ticket Gitlab` field (field ID `fldjuMRjWBX0XiQjm`, type `multilineText`). Parameters:
   ```
   baseId        = app79vpJ07qFIOEm1
   tableIdOrName = tblHjCvyOcdq0Kw0z
   recordId      = <recID>
   fields        = {"Ticket Gitlab": "<issue web_url>"}
   ```
9. **Propose direct MR** to the user if the root cause is 100% identified and the fix is small (1-5 files, no DB migration, no public API change). Do not auto-chain — always ask first: *« Cause racine claire et petit fix : on enchaîne avec `/support-mr-fix` ? »*

## Workflow

1. **Analyze context** — examine all mentioned files, selected code, logs, specs
2. **Identify scope** — extract exact file paths, function names, components, dependencies
3. **Suggest weight** — propose Fibonacci weight based on scope analysis (see [../references/gitlab-weight.md](../references/gitlab-weight.md))
4. **Detect labels** — infer domain, type, priority, and **board column** from context (see [../references/gitlab-labels.md](../references/gitlab-labels.md))
5. **Match parent epic** — fetch open epics and pick the best match (see [Parent epic](#parent-epic) below)
6. **Ask for confirmation** (local mode only) — present weight, labels (including board column), and suggested parent epic; ask user to confirm or adjust. In CI mode, skip and use auto-detected values
7. **Create issue via glab** — create the issue directly using `glab issue create` (see [Output format](#output-format) below)

## Critical rules

- **Zero hallucination**: if information is not visible in context, use `<PLACEHOLDER>` or state it needs verification
- **Title in English**, action-oriented (User Story: "As [role] I want to..." / Other: "[Verb] + [complement]"). **No prefix of any kind** in the title — no scope (`[NDP]:`, `API -`), no conventional commit prefix (`feat:`, `fix:`, `chore:`), no parenthetical scope (`perf(ndp)`). Labels handle all classification
- **Description and body sections**: entirely in French (Steps, Expected Outcome, Risques, etc.)
- **Langue française** : respecter les [règles de rédaction en français](../references/french-writing-rules.md) pour tout texte généré
- **Emojis**: preserve exactly as they appear in the loaded template — do not add or remove any
- **No nested backticks** — they break GitLab markdown on copy-paste
- **Escape `#N` patterns** — in descriptions, numbered lists like `#1`, `#2`, `#3` create unwanted links to GitLab issues. Escape them as `\#1`, `\#2`, `\#3`. Only use bare `#N` when intentionally referencing a real issue (e.g. `Closes #42`)
- **No git commands** (commit, push) in steps — devs manage their own workflow
- **Do not infantilize developers** — provide just enough info to understand the problem and the resolution direction
- Use `<details>` blocks for code diffs (with 4-space indentation, no fenced code blocks inside)
- End the description body with GitLab quick actions: `/label`, `/weight`
- **Auto board placement** (MANDATORY): every issue MUST receive exactly one board column label so it appears on the [Pysae board](https://gitlab.com/groups/pysae/-/boards/546268). Apply the auto-detection rules from [../references/gitlab-labels.md](../references/gitlab-labels.md) — default to `~Refinement` when no stronger signal exists. Never create an issue without a board column label.
- **Auto-assign**: resolve the current username via `glab api user | jq -r '.username'` and pass `--assignee <username>` to `glab issue create`. Do NOT use the `/assign @me` quick action — it is not processed by the GitLab API. If the user specifies a different assignee, use their username instead
- **Use only valid labels** from [../references/gitlab-labels.md](../references/gitlab-labels.md). Never invent labels — in particular, priorities are `priority::P1`, `priority::P2`, `priority::P3` (not `priority::high`, `priority::critical`, etc.)

## Domain adaptation

Adapt focus based on the domain detected from context:

- **Backend/API**: endpoints, models, validation, performance
- **Frontend/UI**: components, state, UX, accessibility
- **Infra/DevOps**: deployments, config, observability
- **Mobile**: sync, offline, permissions, performance
- **Tests**: coverage, edge cases, flakiness
- **Documentation**: clarity, examples, onboarding

## Self-check before output

Verify mentally:
- All provided files/context analyzed
- Exact names used (no invention)
- Steps are actionable without ambiguity
- Validation criteria are measurable
- Ticket is self-contained (actionable without further clarification)
- Markdown syntax is valid for GitLab rendering
- A board column label is present (Refinement, Ready, workflow::To Do, etc.)

## GitLab issue templates (dynamic)

The team's GitLab issue templates are loaded below. **Use the template matching the detected type (`bug`, `feature`, or `technical`) as the skeleton for the description.**

**CRITICAL — preserve template formatting exactly as-is:** keep all emojis, section headers, bullet markers, and structure from the template verbatim. Do NOT strip emojis, rename headers, reorder sections, or reformat. Only fill in the placeholder content within each section. The template is the source of truth for formatting.

!`for tpl in bug feature technical; do echo "=== Template: $tpl ==="; glab api "projects/pysae%2Fissue-templates/repository/files/.gitlab%2Fissue_templates%2F${tpl}.md/raw?ref=main" 2>/dev/null; echo -e "\n"; done 2>/dev/null || echo "Templates unavailable"`

## Parent epic

Before creating the issue, match it to the most relevant parent epic using the scoring script:

```bash
pysae-ai-tools glab epic-attach-issues match-one \
  --title "<ISSUE_TITLE>" \
  --label "<LABEL1>" --label "<LABEL2>" \
  --description "<ISSUE_DESCRIPTION_FIRST_500_CHARS>"
```

The script scores the issue against all open epics (enriched with their child issue titles) and returns the top matches with confidence levels.

1. If the top match has **high** confidence → suggest that epic
2. If only **medium** confidence → suggest it but mention uncertainty
3. If all matches are **low** or no match → suggest "aucune epic"
4. If the user explicitly requests a specific epic, use that one
5. When presenting the confirmation summary, show the suggested epic (or "aucune")

## Output format

After the user confirms the weight and labels, create the issue using `glab issue create`. **Always write the description to a temp file first** to avoid shell expansion issues and hangs. Use `mktemp` to generate a unique filename — never a fixed path like `/tmp/issue_desc.md`, which would collide if several skill runs execute in parallel on the same machine:

```bash
ISSUE_DESC=$(mktemp -t issue-desc-XXXXXX.md)
trap 'rm -f "$ISSUE_DESC"' EXIT

cat > "$ISSUE_DESC" <<'EOF'
[filled-in GitLab template for the detected type]

/label ~DOMAIN ~type::TYPE ~priority::PRIORITY
/weight WEIGHT
EOF

# Resolve current GitLab username
GL_USER=$(glab api user | jq -r '.username')

pysae-ai-tools glab retry issue create \
  --title "Issue title here" \
  --description "$(cat "$ISSUE_DESC")" \
  --assignee "${GL_USER}" \
  --no-editor \
  --yes
```

## Attach to epic

After creating the issue, attach it to the matched epic using `epic-attach` (**never** use `/parent_epic` quick action — it silently fails in some cases):

```bash
pysae-ai-tools glab epic-attach --epic ${EPIC_IID} --issue ${PROJECT_PATH}#${NEW_IID}
```

Skip this step if no epic was matched.

## Timeout & retry

The `pysae-ai-tools glab retry` wrapper handles timeout, retry (3 attempts), process cleanup, and API fallback automatically. Always use it for `glab issue create`.

$ARGUMENTS
