---
description: Render a Mermaid diagram (flowchart, sequence, ERD, state, gantt) via launch-deck. For ERDs, auto-derives tables and relations from launch-chart's db layer so the diagram matches the real schema. Files a chart-gap feedback comment to LS if the db layer is missing or empty.
when_to_use: |
  Auto-fire when the user wants a RENDERED Mermaid diagram visible in the browser — flowchart, sequence, ERD, state machine, or gantt. Trigger phrases: "diagram X", "draw the flowchart for Y", "sequence diagram of W", "ERD for the schema / for X module", "state diagram for V's lifecycle", "gantt of the rollout", "show me visually how X flows", "render this as a diagram", "give me a chart of the user table relations". Deck is required because Mermaid must be rendered to be useful — DSL text in the terminal cannot substitute. Do NOT auto-fire for: plain-text process explanations the user can read in the terminal ("walk me through how X works" — that's /kit:analyse or a direct terminal answer), ASCII flowcharts inline in chat, requests that already include Mermaid the user wrote, or schema questions where the answer is a few sentences rather than a diagram.
allowed-tools:
  - mcp__launch-deck__server_status
  - mcp__launch-deck__start_server
  - mcp__launch-deck__deck
  - mcp__launch-deck__await_feedback
  - mcp__launch-chart__chart_server_status
  - mcp__launch-chart__detect_project_stack
  - mcp__launch-chart__read_graph
  - mcp__launch-chart__inspect_node
  - mcp__launch-secure__kit_feedback_submit
  - Bash
---

# /kit:diagram

Push a Mermaid diagram to launch-deck. Five flavors:

- **flowchart** — boxes-and-arrows for any process
- **sequence** — request/response timing between actors
- **erd** — entity-relationship diagram. Auto-pulled from chart `db` layer unless the user provides their own DSL.
- **state** — state machine
- **gantt** — timeline

Parse `$ARGUMENTS`:
- **kind** (required) — `flowchart` | `sequence` | `erd` | `state` | `gantt`. If absent, ask.
- **subject** (required for non-erd) — what to diagram, e.g. "user login flow" or "OAuth handshake".
- **--scope=<filter>** — for ERDs, limit to one module or table set (e.g. `--scope=auth` or `--scope=User,Org,Membership`). Default: all tables.
- **--session=<id>** — deck session name. Default `diagram-<kind>-<subject-slug>`.
- **--dsl=<raw-mermaid>** — bypass auto-generation; push the user's DSL verbatim.
- **--no-feedback** — skip feedback round-trip (rare; only when the caller has already validated the DSL).

Examples:
- `/kit:diagram flowchart user login flow`
- `/kit:diagram sequence OAuth handshake between client, gateway, idp`
- `/kit:diagram erd --scope=work-items`
- `/kit:diagram erd` → full project ERD
- `/kit:diagram state work-item lifecycle: backlog → todo → in-progress → done`

## Preflight

1. Confirm `mcp__launch-deck__server_status` is running; start if not.
2. For `erd`: confirm `mcp__launch-chart__chart_server_status` is up, then call `mcp__launch-chart__detect_project_stack` and check `db` is in the layers list.

## Build the DSL

### flowchart / sequence / state / gantt

Translate the subject into Mermaid DSL based on what the user described. For sequence, infer actors from the subject (client/server/db are common defaults). Add concise labels — don't overload with prose.

Example flowchart skeleton:

```mermaid
flowchart TD
  Start([User opens app]) --> Auth{Session valid?}
  Auth -- yes --> Home[Home]
  Auth -- no --> Login[Login form]
  Login -- success --> Home
```

If the user passed `--dsl=…`, skip generation — use their DSL.

### erd

Query the db layer to derive entities and edges:

1. `mcp__launch-chart__read_graph(layer: "db", type: "table"[, module: <scope>])` — gets every table node.
2. For each table, `mcp__launch-chart__inspect_node(node_id: <id>, fields: ["columns", "relations"])` to get fields and FK relations.
3. Render Mermaid `erDiagram` DSL:

```mermaid
erDiagram
  USER ||--o{ WORK_ITEM : owns
  USER {
    string id PK
    string email
    datetime createdAt
  }
  WORK_ITEM {
    string id PK
    string userId FK
    string title
    enum type
  }
```

Rules:
- Use `||--o{` for 1:N FK relations, `}o--o{` for many-to-many join tables.
- Include PK + FK markers; include enum/scalar type for the first ~8 columns per table; truncate the rest with a `… (N more)` comment.
- Cap at 25 tables to keep the diagram readable. If the project has more than 25 in scope, ask the user to narrow with `--scope=`.

**Chart-gap detection** — file a feedback comment per the protocol below before stopping if:
- the db layer is missing from `detect_project_stack`
- `read_graph(layer: "db")` returns 0 nodes
- the chart shows tables but `inspect_node` returns no `columns` (parser misconfiguration)

## Push to deck — feedback mode is the default

**Always use `mode: "feedback"` for diagrams.** Mermaid DSL frequently fails on the first attempt (syntax pitfalls below), and the deck server's auto-error poll is racy (1500ms timeout in `deck-mcp.ts`). Feedback mode gives you two backstops: a synchronous render-error capture *and* explicit user confirmation. Skip only when `--no-feedback` was passed.

Call `mcp__launch-deck__deck` with:
- `session: <session>`
- `mode: "feedback"`
- `prompt: "Diagram render OK? Reply 'ok' to accept, or paste the error / describe what's wrong."` (ERDs: append "Does this match the schema you expected?")
- `blocks: [{ type: "mermaid", label: <kind>-<subject>, content: <mermaid-dsl> }]`

### Render-error retry loop

The deck MCP catches mermaid parse/render errors via the browser's `onMermaidError` → `/api/render-errors` channel and surfaces them on the `deck` tool response. Handle both signal paths:

1. **Synchronous render error** — if the `deck` response is `{ok: false, mermaid_error, failed_source, ...}`, inspect `failed_source` first:
   - If `failed_source` matches the DSL you just pushed → real error. Fix the DSL based on `mermaid_error` and re-push immediately (same session — the tab is already open). Cap at 2 auto-retries before surfacing to the user.
   - If `failed_source` does NOT match what you just pushed → **stale error**. The deck server's `lastRenderError` is a module-level pop register (`consumeRenderError` in `deck-serve.ts`) populated via WebSocket from the browser; if the previous push's render error arrived AFTER its 1500ms MCP poll, it leaks into this push's response. Ignore it and proceed to `await_feedback`.
2. **User feedback** — if `deck` returned `ok: true`, call `mcp__launch-deck__await_feedback({ session })`. If the reply is positive ("ok", "looks good", thumbs up), you're done. Otherwise treat the reply as a correction (syntax error pasted, "missing X", "wrong direction") and regenerate. Cap at 2 user-feedback retries before stopping and asking for a clearer instruction.

### Common Mermaid pitfalls (avoid on first attempt)

- **No `<br/>` in participant aliases.** `participant Pod as LaunchPod CLI<br/>(agent)` breaks the parser in many Mermaid builds. Use one-line names or a trailing parenthetical.
- **Multi-line notes are fragile.** `Note over X: line1<br/>line2` is risky inside `rect` blocks. Keep notes one-line, or chain two `Note` statements.
- **Multiple `else` branches.** `alt … else … else … else … end` works in current Mermaid but failure modes are noisy; prefer 2-branch alts or split into separate alt blocks.
- **`rect rgb(...)`** uses **space-separated** values, not commas: `rect rgb(230 240 255)` — not `rect rgb(230,240,255)`. Comma form errors silently in some builds.
- **Special chars in labels** — wrap in double quotes when using `:`, `(`, `,`, or unicode arrows: `A->>B: "step (1): start"`.
- **Reserved keywords as actor names** — avoid `end`, `note`, `loop`, `alt`, `opt` as participant ids.
- **ERD column types** must be one word: `string`, `int`, `datetime`, `enum`. No spaces, no parens.

## Open in browser

After the final successful push (and after `await_feedback` returns positive), open the per-session URL so the user lands directly on this diagram:

```
open "<deck-url>/#<session>"          # macOS
xdg-open "<deck-url>/#<session>"      # Linux
```

`<deck-url>` is the `url` returned by `mcp__launch-deck__server_status` (typically `http://localhost:52829`). The `#<session>` hash deep-links to this exact session.

## Output

```
diagram pushed — deck session "<session>" — <deck-url>/#<session>
kind: <kind>
nodes: <N>  edges: <M>
```

For ERDs add `tables: <N>  relations: <M>  scope: <scope or "all">`.

## Chart-gap protocol (shared)

When the chart MCP returns less data than expected (db layer missing, 0 tables, empty columns), file ONE report via `mcp__launch-secure__kit_feedback_submit` (the kit-self feedback channel — NOT `communication_write`, which would land in the user's own project Comm Hub instead of the launch-kit project) before stopping:

```
title: "launch-chart gap: <one-line>"
source: "kit:diagram"
body: |
  Skill: /kit:diagram
  Tool:  read_graph(layer="db", …) / inspect_node(...)
  Returned: <tables_count> tables, <relations_count> relations
  Expected: db layer present per detect_project_stack
  Project stack: <one-line summary>
```

Then fall back: render a `flowchart` placeholder explaining "DB layer not available — re-run `npx launch-chart generate_graph` then retry" instead of the ERD.

## Constraints

- **MCP-first for ERDs.** Never grep `prisma/schema.prisma` to build the DSL — the chart has the parsed model.
- **Cap entities at 25.** Past that, Mermaid wraps unreadably; ask the user to narrow scope.
- **Mermaid only.** This skill does not draw raster images — Mermaid DSL is the deliverable.
- **One block per push.**
- **Feedback mode by default.** Never push a diagram with `mode: "show"` unless `--no-feedback` was explicitly passed. Diagrams are validated artifacts, not fire-and-forget output.
- **Retry caps.** 2 auto-retries on synchronous render error + 2 user-feedback retries. Beyond that, hand the broken DSL back to the user with the last error message and stop.
