Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .github/prompts/issues-diagram.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
name: issues-diagram
description: Generate or refresh a self-contained HTML file with three interactive Mermaid dependency diagrams for the dgee2/Menu repo — epics only, child issues only, and a full combined view — with status-based colour coding and pan/zoom.
argument-hint: optional output path (defaults to docs/issues-diagram.html)
---

# Issues Dependency Diagram

Generate (or refresh) the interactive HTML dependency diagram for this repository.

## Skills to apply

Apply both of these skills in order:

1. **`github-issues-status`** — fetch all issues, parse epic task lists, and compute blocked / unblocked / in-progress / done status for every issue and epic.
2. **`mermaid-html-diagram`** — render the computed data as a self-contained HTML file.

## Runtime context

- Repository: `dgee2/Menu`
- Output path: `docs/issues-diagram.html` (override with the caller's argument if provided)
- Open the file after writing it

## Three diagrams to produce

### Diagram 1 — Epics only (`#epics-only`)

- `rankDir: TB`, height `72vh`
- One node per epic; apply the epic's computed status class
- Labelled arrows between epics showing the dependency reason
- Node label includes: epic number, title, status indicator, and a one-line blocker summary

### Diagram 2 — Child issues only (`#child-issues`)

- `rankDir: LR`, height `85vh`
- Task nodes grouped into epic subgraphs; subgraph background colour matches epic status
- Within-epic arrows follow the natural implementation order (DB entity → API → frontend)
- Cross-epic arrows connect specific tasks at the boundary between dependent epics
(see the cross-epic wiring table below)
- Node label includes: issue number, short title, ✅ if closed

### Diagram 3 — Full diagram (`#full-diagram`)

- `rankDir: TB`, height `85vh`
- Epics as subgraph containers (styled by status) containing all child tasks
- Epic-level dependency arrows between subgraphs

## Cross-epic task-level wiring (child issues diagram)

These are the established dependencies inferred from epic bodies and domain ordering rules.
Re-verify closed state on each refresh — a closed issue promotes its dependents from BLOCKED to UNBLOCKED.

| From | To | Reason |
|---|---|---|
| #1110 | #1111, #1112, #1113 | MenuUser.Id referenced by Recipe ownership |
| #1111, #1112, #1113 | #1114 | All DB changes before DTO expansion |
| #1114 | #1115, #1116, #1117 | DTOs before API endpoints |
| #1115 | #1118, #1123 | List endpoint before detail page / search index |
| #1116 | #1119, #1124, #1129 | Create/update before form, outbox, sharing |
| #1133 | #1134 | Public route group structural split required |
| #1117 | #1139 | Recipe CRUD complete before architectural restructure |
| #1110 | #1129, #1143, #1144, #1151, #1154 | User identity before all user-owned features |
| #1124 | #1148 | Outbox infra before metrics snapshot |
| #1125 | #1149 | RecipeViewed event before metrics consumer |
| #1143, #1145 | #1149 | Favourite/diary events feed metrics consumer |
| #1116 | #1143, #1151 | Recipe CRUD before favourite / collection features |

## Known epic structure

The table below is pre-populated from the 2026-05-28 snapshot. On each run, re-check issue states via `github-issues-status` and update statuses — do not use this table as a substitute for live data.

| Epic | Title | Children | Depends on |
|-------|--------------------------------------------|-----------------|-------------------|
| #1097 | Identity & User Provisioning (MenuUser) | #1109, #1110 | — |
| #1098 | Core Recipe Model (DB Schema) | #1111–#1113 | #1097 |
| #1099 | Recipe Authoring API Expansion | #1114–#1117 | #1098 |
| #1100 | Frontend: Recipe Editor & Detail Pages | #1118–#1122 | #1099 |
| #1101 | Recipe Search | #1123–#1128 | #1099 |
| #1102 | Access Control & Sharing | #1129–#1133 | #1097, #1099 |
| #1103 | Recipe Publication | #1134–#1138 | #1102 (via #1133) |
| #1104 | Architectural Project Restructure | #1139–#1142 | #1099 |
| #1105 | Favourites & Diary | #1143–#1147 | #1097, #1099 |
| #1106 | Metrics & Engagement | #1148–#1150 | #1101, #1105 |
| #1107 | Curated Recipe Collections | #1151–#1153 | #1099 |
| #1108 | Communication Preferences | #1154–#1156 | #1097 |

## Summary table

Append an **Epic Summary** HTML table below the diagrams with columns:
Epic #, Title, Child Issues, Status, Depends on.
105 changes: 105 additions & 0 deletions .github/skills/github-issues-status/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
name: github-issues-status
description: Fetch all issues for a GitHub repo, parse Epic task lists, and compute a blocked/unblocked/in-progress/done status for every issue and epic transitively.
user-invokable: true
context: inline
---

# GitHub Issues Status

## Purpose

Use this skill whenever you need a structured view of issue states and blocking relationships — as input to a diagram, a sprint report, or any other artefact. It produces a data model (not a visual output) that other skills or prompts can consume.

## Inputs

| Name | Required | Description |
|---|---|---|
| `repo` | yes | `OWNER/REPO` slug, e.g. `dgee2/Menu` |
| `epic-pattern` | no | Title prefix that identifies epic issues. Default: `[Epic]` |

## Step 1 — Fetch all issues

```bash
gh issue list --repo <repo> --state all --limit 200
```

Capture: `number`, `title`, `state` (OPEN / CLOSED), `labels`.

## Step 2 — Identify epics and fetch their bodies

Any issue whose title contains `[Epic]` (or the configured `epic-pattern`) is an **Epic**.

For each epic, fetch the full body:

```bash
gh issue view <number> --repo <repo> --json title,body
```

Parse the body for GitHub task-list syntax to extract child issue references:

```
- [x] #NNNN ← completed child task
- [ ] #NNNN ← open child task
```

Build a map: `epic → [child issue numbers]`.

## Step 3 — Infer cross-epic dependencies

Read each epic body for explicit dependency language:

> "depends on", "requires", "after", "once X exists", "built on top of", "comes first", "all subsequent"

Also apply these domain ordering rules:
- DB schema / entity changes must precede API endpoint changes
- API endpoint changes must precede frontend changes
- User identity / auth foundation (MenuUser) must precede all feature epics
- Outbox / event infrastructure must precede projection consumers that read from it
- A "public route group" structural split must precede any public endpoints that use it

Record each inferred dependency with a short reason label (used for arrow labels in diagrams).

For cross-epic task-level wiring in child-issue diagrams, connect the last key output task of a prerequisite epic to the first task of the dependent epic. If multiple tasks must complete, wire each one explicitly.

## Step 4 — Compute status for every issue

Apply this algorithm **transitively**, starting from issues with no dependencies:

```
status(issue):
if issue.state == CLOSED → DONE
if all direct dependencies are DONE → UNBLOCKED
otherwise → BLOCKED
```

For **Epics**, derive status from their children and epic-level dependencies:

```
epicStatus(epic):
if all children DONE and all epic deps DONE → DONE
if some children DONE and next open child is UNBLOCKED
and all epic deps DONE → IN_PROGRESS
otherwise → BLOCKED
```

## Step 5 — Output the data model

Produce a structured summary with these fields per issue:

```
{
number: 1097,
title: "[Epic] Identity & User Provisioning (MenuUser)",
state: "OPEN",
status: "IN_PROGRESS", // DONE | UNBLOCKED | IN_PROGRESS | BLOCKED
isEpic: true,
children: [1109, 1110], // epic only
closedChildren: [1109], // epic only
deps: [], // issue numbers this one depends on
depLabels: {}, // dep number → reason string
blockedBy: [], // first-level open deps
}
```

This output is consumed by `mermaid-html-diagram` or other reporting skills.
199 changes: 199 additions & 0 deletions .github/skills/mermaid-html-diagram/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
---
name: mermaid-html-diagram
description: Generate a self-contained HTML file containing one or more interactive Mermaid diagrams with dark GitHub-style theming, status-based colour coding, and mouse/button pan-and-zoom via svg-pan-zoom.
user-invokable: true
context: inline
---

# Mermaid HTML Diagram

## Purpose

Use this skill to render any Mermaid diagram (flowchart, sequence, ER, state, etc.) as a polished, self-contained HTML file that can be opened directly in a browser. It handles the common pitfalls of embedding Mermaid SVGs in fixed-height containers and wiring up pan-and-zoom correctly.

## Inputs

| Name | Required | Description |
|---|---|---|
| `diagrams` | yes | List of `{ id, title, mermaidSource, height }` objects |
| `outputPath` | yes | Absolute path for the `.html` file |
| `pageTitle` | no | Browser tab title |
| `legend` | no | List of `{ label, fillColour, strokeColour }` items |

## Colour palette — status-based nodes

Use these consistently whenever nodes represent work items with a blocking status:

| Status | Fill | Stroke | Text | Usage |
|-------------|---------|---------|---------|------------------------------------------|
| DONE | #2d1f6e | #8957e5 | #d2a8ff | Closed / completed issue |
| UNBLOCKED | #0d3020 | #3fb950 | #7ee787 | Open, all dependencies done — bold text |
| IN_PROGRESS | #3d2600 | #f0883e | #f0c674 | Partially done, next task ready — bold |
| BLOCKED | #2d1010 | #f85149 | #ffa198 | Open with at least one open dependency |

Subgraph container backgrounds use the same fill/stroke as the group's status but slightly darker.

Add status indicators to node labels:
- DONE: `✅` prefix or suffix
- IN_PROGRESS: `▶` prefix
- BLOCKED: `⛔` prefix

## HTML structure

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{pageTitle}</title>
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/svg-pan-zoom@3.6.1/dist/svg-pan-zoom.min.js"></script>
<style>
/* See Critical CSS section below */
</style>
</head>
<body>
<!-- top nav, legend, diagram sections, summary table -->
<script>
/* See Critical JS section below */
</script>
</body>
</html>
```

## Critical CSS

```css
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #0d1117; color: #c9d1d9; margin: 0; padding: 20px; }

.mermaid-box {
width: 100%; overflow: hidden;
background: #161b22; border: 1px solid #30363d; border-radius: 8px;
cursor: grab; user-select: none;
display: block; position: relative;
}
.mermaid-box:active { cursor: grabbing; }
/* Mermaid injects a wrapper div — both it and the SVG must fill the container */
.mermaid-box > .mermaid {
width: 100% !important; height: 100% !important; display: block !important;
}
.mermaid-box svg {
display: block !important; width: 100% !important;
height: 100% !important; max-width: none !important;
}

.diagram-wrap { position: relative; }
.diagram-controls {
position: absolute; top: 10px; right: 10px; z-index: 10; display: flex; gap: 6px;
}
.diagram-controls button {
background: rgba(33,38,45,0.92); border: 1px solid #30363d;
color: #c9d1d9; border-radius: 6px; padding: 5px 12px;
cursor: pointer; font-size: 0.82rem; backdrop-filter: blur(4px);
}
.diagram-controls button:hover { background: #30363d; border-color: #58a6ff; color: #58a6ff; }
```

## Critical JS — initialisation

Mermaid renders SVGs with **hardcoded pixel `width` and `height` attributes**. If you leave these in place, svg-pan-zoom will compute an incorrect viewport and the diagram will appear cut off or misaligned. The fix sequence is mandatory:

```javascript
mermaid.initialize({ startOnLoad: false, theme: "dark", securityLevel: "loose" });

const pz = {};

document.addEventListener("DOMContentLoaded", async () => {
await mermaid.run({ querySelector: ".mermaid" });

const setups = [
// { key, boxId, inId, outId, rstId } — one entry per diagram
];

setups.forEach(({ key, boxId, inId, outId, rstId }) => {
const box = document.getElementById(boxId);
const svg = box && box.querySelector("svg");
if (!svg) return;

// 1. Strip Mermaid's hardcoded pixel dimensions (keep viewBox)
svg.removeAttribute("width");
svg.removeAttribute("height");
svg.style.cssText = "display:block;width:100%;height:100%;max-width:none;";

// 2. Make the inner .mermaid wrapper div fill the container too
const inner = svg.closest(".mermaid");
if (inner) inner.style.cssText = "display:block;width:100%;height:100%;";

// 3. Initialise — do NOT pass fit/center:true here; call them explicitly after
pz[key] = svgPanZoom(svg, {
zoomEnabled: true, controlIconsEnabled: false,
fit: false, center: false,
minZoom: 0.04, maxZoom: 25, zoomScaleSensitivity: 0.3,
mouseWheelZoomEnabled: true, dblClickZoomEnabled: true,
preventMouseEventsDefault: true,
});

// 4. Resize to actual container, then fit and centre
pz[key].resize();
pz[key].fit();
pz[key].center();

// 5. Wire buttons
document.getElementById(inId) .addEventListener("click", () => pz[key].zoomIn());
document.getElementById(outId).addEventListener("click", () => pz[key].zoomOut());
document.getElementById(rstId).addEventListener("click", () => {
pz[key].resize(); pz[key].fit(); pz[key].center();
});
});

// 6. Re-fit on window resize
window.addEventListener("resize", () => {
Object.values(pz).forEach(p => { try { p.resize(); p.fit(); p.center(); } catch(e){} });
});
});
```

## Container height guidelines

| Diagram type | Recommended height |
|---|---|
| Simple (< 15 nodes) | `60vh` |
| Medium (15–30 nodes) | `72vh` |
| Large (30+ nodes) | `85vh` |

## Per-diagram section HTML pattern

```html
<div class="diagram-section">
<h2 id="{id}">{title}</h2>
<div class="diagram-wrap">
<div class="diagram-controls">
<button id="{id}-in">+</button>
<button id="{id}-out">-</button>
<button id="{id}-rst">⟲ Reset</button>
</div>
<div class="mermaid-box" id="box-{id}" style="height:{height}">
<div class="mermaid" id="mmd-{id}">
{mermaidSource}
</div>
</div>
</div>
</div>
```

## Mermaid init block per diagram

```
%%{init: {"theme": "dark", "flowchart": {"rankDir": "TB", "nodeSpacing": 55, "rankSpacing": 80}}}%%
```

Use `rankDir: TB` (top-to-bottom) for dependency trees and `rankDir: LR` (left-to-right) for wide graphs with many parallel tracks.

## After writing the file

Open it immediately so the result is visible:

```powershell
Start-Process "<outputPath>"
```
Loading