---
name: jira-tickets
description: Generate detailed, actionable Jira ticket files for an epic based on a high-level description. Explores the codebase to fill in real technical details before writing.
---

Generate two files per Jira ticket for the epic described by the user:
- A **`.md` file** — human-readable source of truth, kept for editing and version control
- An **`.html` file** — used for pasting into Jira: open in any browser, press `Cmd+A` then `Cmd+C`, and paste into the Jira description field with `Cmd+V`

Follow these steps in order.

## 1. Parse the input

Extract from the user's description:
- The **goal** of the epic (what problem is being solved)
- Any **high-level requirements** or constraints mentioned
- Any **specific repos, tables, endpoints, or files** referenced
- Any **design ideas or preferences** the user has already expressed (treat these as requirements, not suggestions)

If the description is vague about a key technical decision, make a reasonable assumption and note it in the ticket rather than asking.

## 2. Explore the codebase

Before writing any ticket, use the Explore agent to gather real technical context from the relevant repos. Do NOT invent schema, endpoint names, or class names — read the actual code.

Specifically, look for:
- **Existing DB tables** related to the epic (schema, column names, types, FK constraints, indexes)
- **Migration framework** in use (Liquibase, Flyway, Alembic, plain SQL, etc.) and file naming conventions
- **Existing endpoints** that are referenced or that will need to be modified
- **Models/ORM classes** that correspond to the affected tables
- **How user identity flows** through the relevant service (JWT, headers, session, etc.)
- **Changelog or audit tables** if the epic involves tracking changes
- **Frontend API clients** that call the affected endpoints
- **Test patterns** used in the relevant service

Only explore repos that are directly relevant. Do not exhaustively survey the whole codebase.

## 3. Decompose into tickets

Break the epic into the smallest set of independently deliverable tickets. Each ticket should be completable by one developer in one sprint without depending on in-progress work from another ticket (except for explicit hard dependencies, which should be stated).

Typical breakdown for a data/backend epic:
- **DB migration ticket** — schema changes only, no application logic
- **Backend logic ticket(s)** — service/handler changes that use the new schema
- **Frontend ticket** (if needed) — UI or API client changes
- **Data/backfill ticket** — one-time script to populate historical data
- **Analytics ticket** — Sigma/dashboard changes that depend on the new data

Do not create tickets for things that are already done or that are clearly out of scope.

## 4. Write the ticket files

Create a subdirectory named after the epic (short, kebab-case). Ask the user where to save if the working directory is ambiguous.

For each ticket, write **two files** with the same base name:
- `TICKET-N-short-description.md`
- `TICKET-N-short-description.html`

### 4a. Markdown file (`.md`)

Standard markdown. This is the editable source. Structure:

```markdown
# [TICKET-N] <Title>

## Type
<Backend / Frontend / Database / Analytics / Data>

## Summary
<1-2 sentences>

## Background
<Context and motivation>

## Changes Required

### <Section per major change>
<Details with real names from the codebase>

```sql
-- actual SQL
```

## Acceptance Criteria
- [ ] <Verifiable outcome>
```

### 4b. HTML file (`.html`)

Convert the same content to a self-contained HTML file with embedded CSS. This is the file the user opens in a browser to copy-paste into Jira.

Use this exact CSS block in every HTML file — do not vary it:

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; max-width: 900px; margin: 40px auto; padding: 0 20px; color: #172B4D; line-height: 1.6; }
  h1 { font-size: 24px; border-bottom: 2px solid #DFE1E6; padding-bottom: 8px; }
  h2 { font-size: 18px; color: #344563; margin-top: 28px; }
  h3 { font-size: 15px; color: #344563; }
  code { background: #F4F5F7; padding: 2px 5px; border-radius: 3px; font-family: monospace; font-size: 13px; }
  pre { background: #F4F5F7; padding: 16px; border-radius: 4px; overflow-x: auto; }
  pre code { background: none; padding: 0; }
  table { border-collapse: collapse; width: 100%; margin: 12px 0; }
  th { background: #F4F5F7; border: 1px solid #DFE1E6; padding: 8px 12px; text-align: left; }
  td { border: 1px solid #DFE1E6; padding: 8px 12px; }
  ul { padding-left: 20px; }
  li { margin: 4px 0; }
  .checklist { list-style: none; padding-left: 0; }
  .checklist li::before { content: "☐  "; }
  .tip { border-left: 4px solid #0052CC; margin: 0 0 24px 0; padding: 8px 16px; background: #DEEBFF; border-radius: 0 4px 4px 0; font-size: 14px; }
</style>
</head>
<body>
<p class="tip"><strong>How to paste into Jira:</strong> press Cmd+A to select all, Cmd+C to copy, then Cmd+V into the Jira description field.</p>
<!-- ticket content here -->
</body>
</html>
```

Conversion rules from Markdown to HTML:
- `# Title` → `<h1>`, `## Title` → `<h2>`, `### Title` → `<h3>`
- `` `code` `` → `<code>code</code>`
- ` ```lang ... ``` ` → `<pre><code>...</code></pre>` (escape `<`, `>`, `&` inside pre blocks)
- `**bold**` → `<strong>bold</strong>`
- `- item` → `<ul><li>item</li></ul>`
- `- [ ] item` → `<ul class="checklist"><li>item</li></ul>`
- Tables → `<table>` with `<th>` for header row, `<td>` for data rows
- Inline `>` blockquotes → `<p class="tip">...</p>`

Rules for ticket content (applies to both files):
- Use the **actual table/column names, endpoint paths, class names, header names** from the codebase — never invent them
- Include **real SQL DDL** for DB tickets, not pseudocode
- Include pseudo-code or pattern-level code for backend tickets (enough to make implementation unambiguous)
- State **hard dependencies** between tickets explicitly
- Call out **rollback procedures** for any destructive or one-time operation
- Acceptance criteria must be **verifiable** — not "works correctly" but "SELECT COUNT(*) returns N rows after backfill"

## 5. Output

After writing all files, print a summary table:

| File | Ticket | Scope |
|---|---|---|
| `TICKET-1-...md` | Title | One-line scope description |

Then briefly note any design decisions you made that the user should review before creating the tickets in Jira.
