跳到正文
cccskills
免费在 GitHub 公开

ticket-diagram

Attach a self-contained Excalidraw status diagram to a GitHub epic — read the epic + its sub-issue tree, render boxes-coloured-by-status with dependency arrows to a committed PNG that (a) renders on the GitHub mobile app and (b) has the editable Excalidraw scene embedded inside it, post it as a sticky comment, and round-trip human edits back in from a comment. Use when asked to "diagram an epic", "draw the ticket tree", "show the epic on mobile", "add a status graph to

中文简介正在准备中。当前显示原文说明。

集成工具GitHub
查看安装方法

包含的文件(1)

  • SKILL.md10.2 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Ticket diagram — an editable, mobile-legible status graph per epic

Turn a GitHub epic's sub-issue tree into a picture: boxes coloured by status, dependency arrows bound to the boxes, committed as a single PNG that renders in the issue/PR body on mobile and carries the editable Excalidraw scene embedded inside it — open that PNG in Excalidraw and you get the live scene to rearrange and hand back.

This is workstream #2 of the human-readable-tickets epic (#479) made concrete, tracked under epic #483. It reuses the sign-off / revision loop of #310 (the same loop ui-proposal and schema-review use): generate → post on the PR → iterate on feedback → approve.

Why Excalidraw + a PNG? Mermaid is disqualified: on the GitHub mobile app a ```mermaid block shows raw code + a perpetual "Loading" spinner (confirmed on #479). A committed PNG renders everywhere, including mobile, with no stall. The scene is embedded in the PNG (Excalidraw's own "Embed scene" format), so the image is also the editable source — no separate verbose .excalidraw file in the repo.

Artifacts (what gets committed)

Per diagram, in writeups/diagrams/:

  • <slug>.graph.json — the small, diffable semantic source (nodes + status + edges). This is the human-auditable record; git blame/diffs of what the epic is live here.
  • <slug>.png — the render + embedded editable scene in one file. Shows in the issue body on mobile; open it in Excalidraw to edit.

The loose <slug>.excalidraw is not committed (it's gitignored) — the scene rides inside the PNG. Pass --excalidraw to the generator only if you want a loose copy locally.

The pipeline (two halves)

  YOU (over the GitHub MCP)            the GENERATOR (deterministic, offline)
  ────────────────────────            ──────────────────────────────────────
  read epic + get_sub_issues   ──▶    scripts/ticket-excalidraw.mjs <graph.json>
  build the graph JSON                  → writeups/diagrams/<slug>.graph.json   (semantic source)
                                        → writeups/diagrams/<slug>.png          (render + scene embedded)

The split matters: the agent does the GitHub I/O; the script does the graph→artifacts step (no network at render time, byte-stable output → minimal diffs).

1 · Read the epic → build the graph JSON

For epic #NN: issue_read (get) the epic, then issue_read (get_sub_issues). For each child read its title, state (open/closed), labels (status:*), and any Blocked-by: #x, #y line in the body. Then build:

{
  "epic": 479,
  "slug": "make-tickets-human-readable",
  "title": "Make tickets human-readable",
  "feedbackUrl": "https://github.com/FriendlyInternet/nuxt-crouton/pull/487",
  "nodes": [{ "id": 454, "title": "Schemas + config", "status": "done" }],
  "edges": [{ "from": 454, "to": 455 }],
  "goal": { "label": "library-catalog.pmcp.dev" }
}
  • status per node — closed → done · label status:in-progress → in_progress · status:blocked → blocked · otherwise pending.
  • edges — Blocked-by: #x on child C ⇒ edge { "from": x, "to": C } (arrow points from blocker to dependent; the generator lays blockers above dependents).
  • goal (optional) — add it when the epic's acceptance is a concrete artifact (e.g. a preview URL). Every terminal node wires into it; it's coloured violet.
  • ref (optional, per node) — top-line label override (e.g. "W2") for nodes that aren't real issues, like an epic's workstreams before it's decomposed. Defaults to #<id>.
  • feedbackUrl (optional) — makes the diagram's footer a clickable "💬 Comment or send edits" link; pass the PR URL. Defaults to the epic issue URL.
  • slug — kebab-case; drives the filenames. Reuse the same slug every regeneration so the diff stays small and the sticky keeps pointing at the same files.

2 · Generate

node scripts/ticket-excalidraw.mjs /tmp/<slug>.graph.json --out-dir writeups/diagrams

Writes <slug>.graph.json + <slug>.png (PNG via the shared renderer .claude/skills/ui-proposal/render.mjs, headless Chromium — same as schema-review; the scene is then embedded into the PNG). Then commit both with /commit, referencing (#NN).

3 · Post the sticky comment & iterate (the #310 loop)

Post the PNG as a single sticky comment on the epic's PR, marked with an HTML anchor, and make the image a link that opens the scene in Excalidraw:

<!-- ticket-diagram:make-tickets-human-readable -->
### 🗺️ Epic diagram — Make tickets human-readable
![epic diagram](https://raw.githubusercontent.com/FriendlyInternet/nuxt-crouton/<branch>/writeups/diagrams/make-tickets-human-readable.png)

**✏️ To edit:** download this PNG and **open it in Excalidraw** — the scene is embedded, so it
opens live; drag boxes (arrows follow), then **export it (Embed scene ON) and attach the PNG to a
comment here**. I'll pull your edits back in.

_Revisions:_
- r1: initial

Reference the PNG by its raw.githubusercontent.com URL on the branch so it renders on mobile. The human reviews on the diff: they inline-comment, or they edit the scene and attach the exported PNG to a comment. Both are change requests. Ignore bot/self comments (user.type === 'Bot').

Approval = a comment containing approve/lgtm. (A 👍 reaction or a label does not resume the pipeline — only issue_comment triggers resume-on-comment.yml, #572.) On approval, mark the PR ready / merge per the epic flow.

4 · Round-trip a human edit back IN

When a human attaches an edited, scene-embedded PNG (or a .excalidraw) to a comment, grab its URL and run the importer — it decodes the scene, re-renders the PNG from that scene (so boxes they moved stay moved), re-embeds the scene, and writes the committed PNG:

node scripts/ticket-excalidraw-import.mjs <attachment-url-or-path> --slug <slug> --out-dir writeups/diagrams

Commit the PNG and refresh the sticky (append - rN: <what changed>). Pair this with subscribe_pr_activity: a comment with an attached PNG → run the importer → commit → done.

5 · Keep it current (it's a live view, not a one-shot)

When the epic's children change — a new sub-issue, a child closes, a Blocked-by edge changes — rebuild the graph JSON and regenerate. Same slug ⇒ the PNG updates in place and graph.json's diff shows exactly what moved semantically. (Regenerating from graph.json re-lays-out the boxes; if a human has hand-arranged the scene, prefer the importer in §4 to preserve their layout.)

Status palette

statuscolourmeaning
done🟩 greenchild issue closed
in_progress🟦 bluestatus:in-progress label
blocked🟥 redstatus:blocked label
pending🟨 yellowopen, not started
goal🟪 violetthe epic's concrete acceptance artifact

Files

  • scripts/ticket-excalidraw.mjs — CLI: graph JSON → .graph.json + scene-embedded .png.
  • scripts/ticket-excalidraw-import.mjs — CLI: an edited (scene-embedded) PNG / .excalidraw → re-rendered, re-embedded .png (the round-trip IN).
  • scripts/lib/excalidraw.mjs — pure emitters: layout() (layered DAG), toExcalidraw() (bound arrows + bound text + chrome), toSvg()/toHtml() (graph render), sceneToSvg()/sceneToHtml() (faithful render of an edited scene). No dependencies.
  • scripts/lib/excalidraw-png.mjs — dependency-free PNG metadata codec: extractScene() / embedScene() (Excalidraw's "Embed scene" tEXt format; Node zlib + manual chunk parsing).

Gotchas

  • The PNG is both the render and the editable source (scene embedded). Never put a client-rendered diagram (Mermaid/widget) in a GitHub body — it must be a committed image so it shows on mobile.
  • Editing = open the PNG in Excalidraw, not a #url= deep link — that needed a hosted .excalidraw, which we no longer commit. (If you want one-tap deep-link editing back, run the generator with --excalidraw, commit the loose file, and link https://excalidraw.com/#url=<raw url>.)
  • One-tap mobile editing = the hosted ticket-editor Worker (workers/ticket-editor, epic #483). Link …/?slug=<slug>&branch=<branch>&issue=<NN> — pass &issue=<NN> so each Save posts a new comment on issue NN with that edit's diagram (a timeline of versions, not just silent nuxt-harness[bot] commits). Requires the loose <slug>.excalidraw committed (generate with --excalidraw), since the editor reads it.
  • Pin a diagram image you want to stay put to its commit, not the branch. A raw.githubusercontent.com/<repo>/<branch>/…png URL re-renders whenever the file is later edited (so a "proposal" comment's picture drifts); …/<commit-sha>/…png is immutable and frozen. Post the proposal/sticky image pinned to the commit that produced it so the timeline reads correctly (the editor's per-save comments already do this).
  • Round-trip needs "Embed scene" ON in Excalidraw's export, or the importer can't find the scene (it errors clearly).
  • Reuse the slug across regenerations, or you'll orphan the old PNG and the sticky image link.
  • If the epic has no sub-issues yet, diagram its workstreams as ref-labelled nodes (e.g. W1…W5).

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

a11y

免费

Accessibility review for Vue surfaces — the code-cleaning analog of /code-review and /simplify, pointed at WCAG/ARIA. Reviews just your diff (or a package/file), rates findings by severity, and either comments inline on the PR (--comment) or applies the safe fixes for you (--fix). Steers the depth-aware `a11y` subagent. Use when asked to "check accessibility", "a11y this", "audit ARIA/keyboard", or run /a11y.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

ask-human

免费

Emit a blocking question the owner can read in ~10 seconds and answer in one reply — the scannable, recommendation-first handoff every agent posts when it hits a fork it can't own. Leads with the one decision + a recommendation, carries the 🤖 provenance header, doubles as the

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

audit

免费

Audit packages for documentation completeness, detect drift between code and docs, and maintain documentation quality across the monorepo. Use when checking package docs, running audits, or reviewing documentation health.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

Author a placeable layout block that looks right at ANY pane size. The one hard rule — size to the PANE with container queries (@container), never the viewport — plus list/form playbooks and the sizing contract (minWidth etc.) the viability metric reads. Use when adding/converting a croutonLayoutBlocks block, or when a block overflows/breaks in a narrow pane.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

When a bug or regression is reported, the FIRST step — before fixing — is to research how and when it was introduced (git archaeology), then record that finding on the tracking issue/PR. Use the moment a bug, error, broken build, or "this used to work" is reported, before writing a fix. Produces a first-bad-commit (or "not a code regression") note you paste onto the issue.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

commit

免费

Smart, granular git commits following monorepo conventions. Analyzes changes, filters to session-relevant files, groups by intent, and uses conventional commit format. Use when committing code changes.

中文简介正在准备中。当前显示原文说明。

FriendlyInternet/nuxt-crouton102026年10月21日 更新

查看 FriendlyInternet 的全部技能

报告此技能的问题