feat: consolidate reviewed Diagram Design 2.6.0 release (#134)

* fix(commands): stop hardcoding the visual-type count

Integrates the final reviewed diff from PR #112.

* docs(high-level): correct effective width checklist

Integrates the final reviewed diff from PR #105.

* fix(commands): quote profile argument hint

Integrates the final reviewed diff from PR #126.

* test(sankey): gate conservation and ribbon geometry

Integrates the final reviewed diff from PR #103.

* feat(tooling): add doctor diagnostics gate

Integrates the final reviewed diff from PR #132.

* feat(scripts): lint diagrams as rendered

Integrates the final reviewed diff from PR #18.

* feat(types): add quantitative polar chart

Integrates the final reviewed diff from PR #101.

* chore(release): consolidate reviewed changes in 2.6.0

Documents every combined gate and synchronizes Claude, Codex, and Factory metadata for the 39-type release.

* fix(doctor): support installed-skill projects

---------

Co-authored-by: mysoniw <soniw1@gmail.com>
Co-authored-by: thang <76550342+thangldw@users.noreply.github.com>
Co-authored-by: YinShaokun <yinshaokun@didiglobal.com>
Co-authored-by: 0xDarkMatter <0xDarkMatter@users.noreply.github.com>
Co-authored-by: Rupam Pal <rupam.pal@euromonitor.com>
Co-authored-by: Yuvraj3905 <yuvraj202001@gmail.com>
This commit is contained in:
Cathryn Lavery
2026-08-20 12:21:43 -07:00
committed by GitHub
co-authored by mysoniw thang YinShaokun 0xDarkMatter Rupam Pal Yuvraj3905
parent 4b573616cb
commit b827385a17
42 changed files with 7090 additions and 130 deletions
+9 -5
View File
@@ -1,16 +1,16 @@
---
name: diagram-design
description: Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, Sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg or Mermaid .mmd sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.
description: Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, polar chart (polar/radial lollipop), loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, treemap, bar, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, DP security matrix, Sankey, fishbone, Wardley map, kanban, user journey, deployment, dependency graph, UML class, story map, or database schema diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg or Mermaid .mmd sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.
license: MIT
metadata:
version: "2.5"
version: "2.6"
---
# Diagram Design
Create visual diagrams as self-contained HTML files with inline SVG and CSS, following an opinionated editorial design system.
Thirty-eight visual types. Semantic patterns describe behavior independently; type references describe layout. Details load from `references/` only when selected.
Thirty-nine visual types. Semantic patterns describe behavior independently; type references describe layout. Details load from `references/` only when selected.
---
@@ -49,7 +49,7 @@ Applied to schematics:
## 2. When to Use
Use for any of the 38 visual types (§3) when a reader will learn more from a visual than from prose, a table, or a bulleted list.
Use for any of the 39 visual types (§3) when a reader will learn more from a visual than from prose, a table, or a bulleted list.
**Don't use for:**
@@ -78,7 +78,7 @@ When behavior, state, enforcement, or risk carries the meaning, first load [`ref
The pattern owns semantic primitives and its tighter budget; the type owns layout grammar. Use [`references/animation.md`](references/animation.md) only when motion is requested or materially clarifies ordered change; static remains the default.
### Visual-type guide (38)
### Visual-type guide (39)
| If you're showing… | Use | Reference |
|---|---|---|
@@ -92,6 +92,7 @@ The pattern owns semantic primitives and its tighter budget; the type owns layou
| Cross-functional process with handoffs | **Swimlane** | [type-swimlane.md](references/type-swimlane.md) |
| Two-axis positioning / prioritization | **Quadrant** | [type-quadrant.md](references/type-quadrant.md) |
| Multiple entities scored across 3–5 quantitative criteria | **Radar / Spider** | [type-radar.md](references/type-radar.md) |
| One quantitative series across cyclic categories; angle=category, radius=magnitude | **Polar chart** | [type-polar.md](references/type-polar.md) |
| Reinforcing cycle / flywheel where the last step feeds the first and a shared hub accumulates state | **Loop** | [type-loop.md](references/type-loop.md) |
| Hierarchy through containment / scope | **Nested** | [type-nested.md](references/type-nested.md) |
| Parent → children relationships | **Tree** | [type-tree.md](references/type-tree.md) |
@@ -383,6 +384,9 @@ Quick check: if a coordinate ends in 1, 2, 3, 5, 6, 7, 9 — fix it.
| Max radar axes | 5 |
| Max radar series | 5 |
| Max focal radar series | 1 |
| Max polar categories | 8 |
| Max polar series | 1 |
| Max focal polar categories | 1 |
| Max bars (bar chart) | 8 |
| Max cells (treemap) | 8 |
| Max series (line chart) | 5 |
@@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Request demand by UTC window · Polar chart</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
html, body, div, main, header, footer, section, article, p, h1, h2, h3, h4, h5, h6 { box-sizing:border-box; margin:0; padding:0; }
:root { --color-paper:#2d3142; --color-ink:#f5f5f5; --color-muted:#bfc0c0; --color-accent:#f08a59; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family:var(--font-sans); background:var(--color-paper); color:var(--color-ink); min-height:100vh; display:flex; align-items:center; justify-content:center; padding:3rem 2rem; }
.frame { max-width:1200px; width:100%; }
.eyebrow { font-family:var(--font-mono); font-size:0.66rem; font-weight:500; letter-spacing:0.18em; text-transform:uppercase; color:var(--color-muted); margin-bottom:0.5rem; }
h1 { font-family:var(--font-serif); font-size:clamp(1.5rem,2.4vw + 0.75rem,2rem); font-weight:400; letter-spacing:-0.02em; line-height:1.15; color:var(--color-ink); margin-bottom:1.5rem; }
svg { width:100%; min-width:900px; display:block; }
@media (max-height:700px) {
body { padding-top:0.75rem; padding-bottom:0.75rem; }
.frame { max-width:960px; }
.eyebrow { margin-bottom:0.25rem; }
h1 { margin-bottom:0.5rem; }
}
</style>
</head>
<body>
<div class="frame">
<p class="eyebrow">Polar · Diagram Design</p>
<h1>Request demand by UTC window</h1>
<svg viewBox="0 0 1000 520" xmlns="http://www.w3.org/2000/svg"
role="img" aria-labelledby="polar-dark-title polar-dark-desc"
data-polar-chart data-polar-cx="500" data-polar-cy="230"
data-polar-radius="160" data-polar-min="0" data-polar-max="100"
data-polar-start-angle="-90" data-polar-clockwise="true"
data-polar-radius-encoding="linear" data-polar-inner-radius="0">
<title id="polar-dark-title">Request demand by UTC window</title>
<desc id="polar-dark-desc">Polar chart on a 0–100% scale identifying 12–15 UTC as the 100% peak, with the other seven UTC windows proceeding clockwise.</desc>
<rect data-polar-background width="100%" height="100%" fill="#2d3142"/>
<text x="40" y="28" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">% OF DAILY PEAK · 0–100</text>
<circle data-polar-ring cx="500" cy="230" r="32" fill="none" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="64" fill="none" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="96" fill="none" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="128" fill="none" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="160" fill="none" stroke="rgba(245,245,245,0.20)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="0" x1="500" y1="230" x2="500" y2="70" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="1" x1="500" y1="230" x2="613.137" y2="116.863" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="2" x1="500" y1="230" x2="660" y2="230" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="3" x1="500" y1="230" x2="613.137" y2="343.137" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="4" x1="500" y1="230" x2="500" y2="390" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="5" x1="500" y1="230" x2="386.863" y2="343.137" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="6" x1="500" y1="230" x2="340" y2="230" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="7" x1="500" y1="230" x2="386.863" y2="116.863" stroke="rgba(245,245,245,0.16)" stroke-width="0.8"/>
<text x="492" y="201" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">20</text>
<text x="492" y="169" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">40</text>
<text x="492" y="137" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">60</text>
<text x="492" y="105" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">80</text>
<text x="492" y="73" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">100</text>
<text x="508" y="233" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace">0</text>
<g data-polar-category="00–03" data-polar-index="0" data-polar-value="32">
<line data-polar-ray x1="500" y1="230" x2="500" y2="178.8" stroke="#bfc0c0" stroke-width="2"/>
<circle data-polar-marker cx="500" cy="178.8" r="4" fill="#2d3142" stroke="#bfc0c0" stroke-width="1.2"/>
<text x="500" y="42" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">00–03</text>
<text data-polar-value-label x="500" y="26" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">32</text>
</g>
<g data-polar-category="03–06" data-polar-index="1" data-polar-value="18">
<line data-polar-ray x1="500" y1="230" x2="520.365" y2="209.635" stroke="#bfc0c0" stroke-width="2"/>
<circle data-polar-marker cx="520.365" cy="209.635" r="4" fill="#2d3142" stroke="#bfc0c0" stroke-width="1.2"/>
<text x="632.936" y="97.064" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">03–06</text>
<text data-polar-value-label x="644.25" y="85.75" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start">18</text>
</g>
<g data-polar-category="06–09" data-polar-index="2" data-polar-value="24">
<line data-polar-ray x1="500" y1="230" x2="538.4" y2="230" stroke="#bfc0c0" stroke-width="2"/>
<circle data-polar-marker cx="538.4" cy="230" r="4" fill="#2d3142" stroke="#bfc0c0" stroke-width="1.2"/>
<text x="688" y="230" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">06–09</text>
<text data-polar-value-label x="704" y="230" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start" dy="16">24</text>
</g>
<g data-polar-category="09–12" data-polar-index="3" data-polar-value="58">
<line data-polar-ray x1="500" y1="230" x2="565.62" y2="295.62" stroke="#bfc0c0" stroke-width="2"/>
<circle data-polar-marker cx="565.62" cy="295.62" r="4" fill="#2d3142" stroke="#bfc0c0" stroke-width="1.2"/>
<text x="632.936" y="362.936" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">09–12</text>
<text data-polar-value-label x="644.25" y="374.25" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start" dy="12">58</text>
</g>
<g data-polar-category="12–15" data-polar-index="4" data-polar-value="100" data-polar-focal="true">
<line data-polar-ray x1="500" y1="230" x2="500" y2="390" stroke="#f08a59" stroke-width="2.4"/>
<circle data-polar-marker cx="500" cy="390" r="5" fill="#2d3142" stroke="#f08a59" stroke-width="1.2"/>
<text x="500" y="418" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">12–15</text>
<text data-polar-value-label x="500" y="434" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">100</text>
</g>
<g data-polar-category="15–18" data-polar-index="5" data-polar-value="82">
<line data-polar-ray x1="500" y1="230" x2="407.227" y2="322.773" stroke="#bfc0c0" stroke-width="2"/>
<circle data-polar-marker cx="407.227" cy="322.773" r="4" fill="#2d3142" stroke="#bfc0c0" stroke-width="1.2"/>
<text x="367.064" y="362.936" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">15–18</text>
<text data-polar-value-label x="355.75" y="374.25" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" dy="12">82</text>
</g>
<g data-polar-category="18–21" data-polar-index="6" data-polar-value="76">
<line data-polar-ray x1="500" y1="230" x2="378.4" y2="230" stroke="#bfc0c0" stroke-width="2"/>
<circle data-polar-marker cx="378.4" cy="230" r="4" fill="#2d3142" stroke="#bfc0c0" stroke-width="1.2"/>
<text x="312" y="230" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">18–21</text>
<text data-polar-value-label x="296" y="230" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" dy="16">76</text>
</g>
<g data-polar-category="21–24" data-polar-index="7" data-polar-value="45">
<line data-polar-ray x1="500" y1="230" x2="449.088" y2="179.088" stroke="#bfc0c0" stroke-width="2"/>
<circle data-polar-marker cx="449.088" cy="179.088" r="4" fill="#2d3142" stroke="#bfc0c0" stroke-width="1.2"/>
<text x="367.064" y="97.064" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">21–24</text>
<text data-polar-value-label x="355.75" y="85.75" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">45</text>
</g>
<line data-polar-rule x1="40" y1="468" x2="960" y2="468" stroke="rgba(245,245,245,0.10)" stroke-width="0.8"/>
<text x="40" y="488" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.08em">Illustrative normalized workload profile</text>
</svg>
</div>
</body>
</html>
@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Request demand by UTC window · Polar chart</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
html, body, div, main, header, footer, section, article, p, h1, h2, h3, h4, h5, h6 { box-sizing:border-box; margin:0; padding:0; }
:root { --color-paper:#f5f5f5; --color-paper-2:#ececec; --color-ink:#2d3142; --color-muted:#4f5d75; --color-soft:#7a8399; --color-rule:rgba(45,49,66,0.12); --color-accent:#eb6c36; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family:var(--font-sans); background:var(--color-paper); color:var(--color-ink); min-height:100vh; padding:3rem 2rem; }
.container { max-width:1200px; margin:0 auto; }
.header { margin-bottom:2.5rem; }
.header-eyebrow { font-family:var(--font-mono); font-size:0.66rem; font-weight:500; letter-spacing:0.18em; text-transform:uppercase; color:var(--color-muted); margin-bottom:0.75rem; }
h1 { font-family:var(--font-serif); font-size:clamp(1.75rem,3vw + 1rem,2.5rem); font-weight:400; letter-spacing:-0.02em; line-height:1.1; color:var(--color-ink); margin-bottom:0.5rem; }
.subtitle { font-size:1rem; line-height:1.55; color:var(--color-muted); max-width:58ch; }
.diagram-container { background:var(--color-paper-2); border:1px solid var(--color-rule); border-radius:8px; padding:1.5rem; overflow-x:auto; }
svg { width:100%; min-width:900px; display:block; }
.cards { display:grid; grid-template-columns:1.1fr 1fr 0.9fr; gap:1rem; margin-top:1.5rem; }
@media (max-width:800px) { .cards { grid-template-columns:1fr; } }
.card { background:#ffffff; border:1px solid var(--color-rule); border-radius:6px; padding:1.25rem; }
.card-header { display:flex; align-items:center; gap:0.6rem; margin-bottom:0.75rem; padding-bottom:0.75rem; border-bottom:1px solid rgba(45,49,66,0.08); }
.card-dot { width:7px; height:7px; border-radius:50%; flex-shrink:0; background:var(--color-muted); }
.card-dot.coral { background:var(--color-accent); }
.card h3 { font-size:0.875rem; font-weight:600; color:var(--color-ink); }
.card p { color:var(--color-muted); font-size:0.8125rem; line-height:1.55; }
.footer { margin-top:2rem; padding-top:1.5rem; border-top:1px solid rgba(45,49,66,0.10); font-family:var(--font-mono); font-size:0.72rem; letter-spacing:0.06em; color:var(--color-soft); display:flex; justify-content:space-between; flex-wrap:wrap; gap:0.5rem; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<p class="header-eyebrow">Polar · Diagram Design</p>
<h1>Request demand by UTC window</h1>
<p class="subtitle">One normalized workload series across eight UTC windows, with radius showing percent of the daily peak.</p>
</div>
<div class="diagram-container">
<svg viewBox="0 0 1000 520" xmlns="http://www.w3.org/2000/svg"
role="img" aria-labelledby="polar-full-title polar-full-desc"
data-polar-chart data-polar-cx="500" data-polar-cy="230"
data-polar-radius="160" data-polar-min="0" data-polar-max="100"
data-polar-start-angle="-90" data-polar-clockwise="true"
data-polar-radius-encoding="linear" data-polar-inner-radius="0">
<title id="polar-full-title">Request demand by UTC window</title>
<desc id="polar-full-desc">Polar chart on a 0–100% scale identifying 12–15 UTC as the 100% peak, with the other seven UTC windows proceeding clockwise.</desc>
<rect data-polar-background width="100%" height="100%" fill="#f5f5f5"/>
<text x="40" y="28" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">% OF DAILY PEAK · 0–100</text>
<circle data-polar-ring cx="500" cy="230" r="32" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="64" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="96" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="128" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="160" fill="none" stroke="rgba(45,49,66,0.20)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="0" x1="500" y1="230" x2="500" y2="70" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="1" x1="500" y1="230" x2="613.137" y2="116.863" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="2" x1="500" y1="230" x2="660" y2="230" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="3" x1="500" y1="230" x2="613.137" y2="343.137" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="4" x1="500" y1="230" x2="500" y2="390" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="5" x1="500" y1="230" x2="386.863" y2="343.137" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="6" x1="500" y1="230" x2="340" y2="230" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="7" x1="500" y1="230" x2="386.863" y2="116.863" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<text x="492" y="201" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">20</text>
<text x="492" y="169" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">40</text>
<text x="492" y="137" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">60</text>
<text x="492" y="105" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">80</text>
<text x="492" y="73" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">100</text>
<text x="508" y="233" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace">0</text>
<g data-polar-category="00–03" data-polar-index="0" data-polar-value="32">
<line data-polar-ray x1="500" y1="230" x2="500" y2="178.8" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="500" cy="178.8" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="500" y="42" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">00–03</text>
<text data-polar-value-label x="500" y="26" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">32</text>
</g>
<g data-polar-category="03–06" data-polar-index="1" data-polar-value="18">
<line data-polar-ray x1="500" y1="230" x2="520.365" y2="209.635" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="520.365" cy="209.635" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="632.936" y="97.064" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">03–06</text>
<text data-polar-value-label x="644.25" y="85.75" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start">18</text>
</g>
<g data-polar-category="06–09" data-polar-index="2" data-polar-value="24">
<line data-polar-ray x1="500" y1="230" x2="538.4" y2="230" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="538.4" cy="230" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="688" y="230" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">06–09</text>
<text data-polar-value-label x="704" y="230" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start" dy="16">24</text>
</g>
<g data-polar-category="09–12" data-polar-index="3" data-polar-value="58">
<line data-polar-ray x1="500" y1="230" x2="565.62" y2="295.62" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="565.62" cy="295.62" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="632.936" y="362.936" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">09–12</text>
<text data-polar-value-label x="644.25" y="374.25" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start" dy="12">58</text>
</g>
<g data-polar-category="12–15" data-polar-index="4" data-polar-value="100" data-polar-focal="true">
<line data-polar-ray x1="500" y1="230" x2="500" y2="390" stroke="#eb6c36" stroke-width="2.4"/>
<circle data-polar-marker cx="500" cy="390" r="5" fill="#f5f5f5" stroke="#eb6c36" stroke-width="1.2"/>
<text x="500" y="418" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">12–15</text>
<text data-polar-value-label x="500" y="434" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">100</text>
</g>
<g data-polar-category="15–18" data-polar-index="5" data-polar-value="82">
<line data-polar-ray x1="500" y1="230" x2="407.227" y2="322.773" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="407.227" cy="322.773" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="367.064" y="362.936" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">15–18</text>
<text data-polar-value-label x="355.75" y="374.25" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" dy="12">82</text>
</g>
<g data-polar-category="18–21" data-polar-index="6" data-polar-value="76">
<line data-polar-ray x1="500" y1="230" x2="378.4" y2="230" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="378.4" cy="230" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="312" y="230" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">18–21</text>
<text data-polar-value-label x="296" y="230" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" dy="16">76</text>
</g>
<g data-polar-category="21–24" data-polar-index="7" data-polar-value="45">
<line data-polar-ray x1="500" y1="230" x2="449.088" y2="179.088" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="449.088" cy="179.088" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="367.064" y="97.064" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">21–24</text>
<text data-polar-value-label x="355.75" y="85.75" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">45</text>
</g>
<line data-polar-rule x1="40" y1="468" x2="960" y2="468" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="488" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.08em">Illustrative normalized workload profile</text>
</svg>
</div>
<div class="cards">
<article class="card">
<div class="card-header"><span class="card-dot coral"></span><h3>Peak · 12–15 UTC · 100%</h3></div>
<p>The focal ray reaches the shared 100% outer ring.</p>
</article>
<article class="card">
<div class="card-header"><span class="card-dot"></span><h3>Quietest · 03–06 UTC · 18%</h3></div>
<p>The shortest ray remains visibly proportional to the zero baseline.</p>
</article>
<article class="card">
<div class="card-header"><span class="card-dot"></span><h3>Evening tail · 18–21 UTC · 76%</h3></div>
<p>Demand stays elevated into the final quarter of the clockwise cycle.</p>
</article>
</div>
<div class="footer">
<span>Illustrative data · normalized to daily peak</span>
<span>Polar chart · static SVG</span>
</div>
</div>
</body>
</html>
@@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Request demand by UTC window · Polar chart</title>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
html, body, div, main, header, footer, section, article, p, h1, h2, h3, h4, h5, h6 { box-sizing:border-box; margin:0; padding:0; }
:root { --color-paper:#f5f5f5; --color-ink:#2d3142; --color-muted:#4f5d75; --color-accent:#eb6c36; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
body { font-family:var(--font-sans); background:var(--color-paper); color:var(--color-ink); min-height:100vh; display:flex; align-items:center; justify-content:center; padding:3rem 2rem; }
.frame { max-width:1200px; width:100%; }
.eyebrow { font-family:var(--font-mono); font-size:0.66rem; font-weight:500; letter-spacing:0.18em; text-transform:uppercase; color:var(--color-muted); margin-bottom:0.5rem; }
h1 { font-family:var(--font-serif); font-size:clamp(1.5rem,2.4vw + 0.75rem,2rem); font-weight:400; letter-spacing:-0.02em; line-height:1.15; color:var(--color-ink); margin-bottom:1.5rem; }
svg { width:100%; min-width:900px; display:block; }
@media (max-height:700px) {
body { padding-top:0.75rem; padding-bottom:0.75rem; }
.frame { max-width:960px; }
.eyebrow { margin-bottom:0.25rem; }
h1 { margin-bottom:0.5rem; }
}
</style>
</head>
<body>
<div class="frame">
<p class="eyebrow">Polar · Diagram Design</p>
<h1>Request demand by UTC window</h1>
<svg viewBox="0 0 1000 520" xmlns="http://www.w3.org/2000/svg"
role="img" aria-labelledby="polar-title polar-desc"
data-polar-chart data-polar-cx="500" data-polar-cy="230"
data-polar-radius="160" data-polar-min="0" data-polar-max="100"
data-polar-start-angle="-90" data-polar-clockwise="true"
data-polar-radius-encoding="linear" data-polar-inner-radius="0">
<title id="polar-title">Request demand by UTC window</title>
<desc id="polar-desc">Polar chart on a 0–100% scale identifying 12–15 UTC as the 100% peak, with the other seven UTC windows proceeding clockwise.</desc>
<rect data-polar-background width="100%" height="100%" fill="#f5f5f5"/>
<text x="40" y="28" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.14em">% OF DAILY PEAK · 0–100</text>
<circle data-polar-ring cx="500" cy="230" r="32" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="64" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="96" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="128" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<circle data-polar-ring cx="500" cy="230" r="160" fill="none" stroke="rgba(45,49,66,0.20)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="0" x1="500" y1="230" x2="500" y2="70" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="1" x1="500" y1="230" x2="613.137" y2="116.863" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="2" x1="500" y1="230" x2="660" y2="230" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="3" x1="500" y1="230" x2="613.137" y2="343.137" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="4" x1="500" y1="230" x2="500" y2="390" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="5" x1="500" y1="230" x2="386.863" y2="343.137" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="6" x1="500" y1="230" x2="340" y2="230" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<line data-polar-spoke data-polar-index="7" x1="500" y1="230" x2="386.863" y2="116.863" stroke="rgba(45,49,66,0.16)" stroke-width="0.8"/>
<text x="492" y="201" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">20</text>
<text x="492" y="169" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">40</text>
<text x="492" y="137" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">60</text>
<text x="492" y="105" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">80</text>
<text x="492" y="73" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">100</text>
<text x="508" y="233" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace">0</text>
<g data-polar-category="00–03" data-polar-index="0" data-polar-value="32">
<line data-polar-ray x1="500" y1="230" x2="500" y2="178.8" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="500" cy="178.8" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="500" y="42" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">00–03</text>
<text data-polar-value-label x="500" y="26" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">32</text>
</g>
<g data-polar-category="03–06" data-polar-index="1" data-polar-value="18">
<line data-polar-ray x1="500" y1="230" x2="520.365" y2="209.635" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="520.365" cy="209.635" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="632.936" y="97.064" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">03–06</text>
<text data-polar-value-label x="644.25" y="85.75" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start">18</text>
</g>
<g data-polar-category="06–09" data-polar-index="2" data-polar-value="24">
<line data-polar-ray x1="500" y1="230" x2="538.4" y2="230" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="538.4" cy="230" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="688" y="230" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">06–09</text>
<text data-polar-value-label x="704" y="230" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start" dy="16">24</text>
</g>
<g data-polar-category="09–12" data-polar-index="3" data-polar-value="58">
<line data-polar-ray x1="500" y1="230" x2="565.62" y2="295.62" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="565.62" cy="295.62" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="632.936" y="362.936" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">09–12</text>
<text data-polar-value-label x="644.25" y="374.25" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="start" dy="12">58</text>
</g>
<g data-polar-category="12–15" data-polar-index="4" data-polar-value="100" data-polar-focal="true">
<line data-polar-ray x1="500" y1="230" x2="500" y2="390" stroke="#eb6c36" stroke-width="2.4"/>
<circle data-polar-marker cx="500" cy="390" r="5" fill="#f5f5f5" stroke="#eb6c36" stroke-width="1.2"/>
<text x="500" y="418" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">12–15</text>
<text data-polar-value-label x="500" y="434" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">100</text>
</g>
<g data-polar-category="15–18" data-polar-index="5" data-polar-value="82">
<line data-polar-ray x1="500" y1="230" x2="407.227" y2="322.773" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="407.227" cy="322.773" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="367.064" y="362.936" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">15–18</text>
<text data-polar-value-label x="355.75" y="374.25" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" dy="12">82</text>
</g>
<g data-polar-category="18–21" data-polar-index="6" data-polar-value="76">
<line data-polar-ray x1="500" y1="230" x2="378.4" y2="230" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="378.4" cy="230" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="312" y="230" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">18–21</text>
<text data-polar-value-label x="296" y="230" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end" dy="16">76</text>
</g>
<g data-polar-category="21–24" data-polar-index="7" data-polar-value="45">
<line data-polar-ray x1="500" y1="230" x2="449.088" y2="179.088" stroke="#4f5d75" stroke-width="2"/>
<circle data-polar-marker cx="449.088" cy="179.088" r="4" fill="#f5f5f5" stroke="#4f5d75" stroke-width="1.2"/>
<text x="367.064" y="97.064" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">21–24</text>
<text data-polar-value-label x="355.75" y="85.75" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">45</text>
</g>
<line data-polar-rule x1="40" y1="468" x2="960" y2="468" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
<text x="40" y="488" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.08em">Illustrative normalized workload profile</text>
</svg>
</div>
</body>
</html>
+36 -33
View File
@@ -240,107 +240,110 @@
<button class="tab new" data-type="radar">
<span class="eyebrow">15</span>Radar
</button>
<button class="tab new" data-type="polar">
<span class="eyebrow">16</span>Polar
</button>
<button class="tab new" data-type="loop">
<span class="eyebrow">16</span>Loop
<span class="eyebrow">17</span>Loop
</button>
<button class="tab new" data-type="datalake">
<span class="eyebrow">17</span>Data lake
<span class="eyebrow">18</span>Data lake
</button>
<button class="tab new" data-type="bar">
<span class="eyebrow">18</span>Bar
<span class="eyebrow">19</span>Bar
</button>
<button class="tab new" data-type="line">
<span class="eyebrow">19</span>Line
<span class="eyebrow">20</span>Line
</button>
<button class="tab new" data-type="gantt">
<span class="eyebrow">20</span>Gantt
<span class="eyebrow">21</span>Gantt
</button>
<button class="tab new" data-type="scatter">
<span class="eyebrow">21</span>Scatter
<span class="eyebrow">22</span>Scatter
</button>
<button class="tab new" data-type="medallion">
<span class="eyebrow">22</span>Medallion
<span class="eyebrow">23</span>Medallion
</button>
<button class="tab new" data-type="high-level">
<span class="eyebrow">23</span>High-Level
<span class="eyebrow">24</span>High-Level
</button>
<button class="tab new" data-type="process">
<span class="eyebrow">24</span>Process
<span class="eyebrow">25</span>Process
</button>
<button class="tab new" data-type="data-flow">
<span class="eyebrow">26</span>Data flow
<span class="eyebrow">27</span>Data flow
</button>
<button class="tab new" data-type="dp-integration">
<span class="eyebrow">27</span>DP integration
<span class="eyebrow">28</span>DP integration
</button>
<button class="tab new" data-type="high-level-vertical">
<span class="eyebrow">28</span>High-Level / Parametric
<span class="eyebrow">29</span>High-Level / Parametric
</button>
<button class="tab new" data-type="treemap">
<span class="eyebrow">29</span>Treemap
<span class="eyebrow">30</span>Treemap
</button>
<button class="tab new" data-type="slopegraph">
<span class="eyebrow">30</span>Line · slopegraph
</button>
<button class="tab new" data-type="dp-security-matrix">
<span class="eyebrow">32</span>DP security matrix
<span class="eyebrow">33</span>DP security matrix
</button>
<button class="tab new" data-type="it-state">
<span class="eyebrow">33</span>IT current-state
<span class="eyebrow">34</span>IT current-state
</button>
<button class="tab new" data-type="sankey">
<span class="eyebrow">34</span>Sankey
<span class="eyebrow">35</span>Sankey
</button>
<button class="tab new" data-type="fishbone">
<span class="eyebrow">35</span>Fishbone
<span class="eyebrow">36</span>Fishbone
</button>
<button class="tab new" data-type="wardley">
<span class="eyebrow">36</span>Wardley map
<span class="eyebrow">37</span>Wardley map
</button>
<button class="tab new" data-type="kanban">
<span class="eyebrow">37</span>Kanban
<span class="eyebrow">38</span>Kanban
</button>
<button class="tab new" data-type="journey">
<span class="eyebrow">38</span>User journey
<span class="eyebrow">39</span>User journey
</button>
<button class="tab new" data-type="deployment">
<span class="eyebrow">39</span>Deployment
<span class="eyebrow">40</span>Deployment
</button>
<button class="tab new" data-type="dependency">
<span class="eyebrow">40</span>Dependency graph
<span class="eyebrow">41</span>Dependency graph
</button>
<button class="tab new" data-type="uml-class">
<span class="eyebrow">41</span>UML class
<span class="eyebrow">42</span>UML class
</button>
<button class="tab new" data-type="story-map">
<span class="eyebrow">42</span>Story map
<span class="eyebrow">43</span>Story map
</button>
<button class="tab new" data-type="db-schema">
<span class="eyebrow">43</span>Database schema
<span class="eyebrow">44</span>Database schema
</button>
<button class="tab new" data-type="sequence-oauth">
<span class="eyebrow">44</span>Sequence · OAuth
<span class="eyebrow">45</span>Sequence · OAuth
</button>
<button class="tab new" data-type="import-drawio" data-single>
<span class="eyebrow">45</span>Import · draw.io
<span class="eyebrow">46</span>Import · draw.io
</button>
<button class="tab new" data-type="import-mermaid" data-single>
<span class="eyebrow">46</span>Import · Mermaid
<span class="eyebrow">47</span>Import · Mermaid
</button>
<button class="tab new" data-type="quadrant-consultant" data-single>
<span class="eyebrow">47</span>Quadrant · consultant
<span class="eyebrow">48</span>Quadrant · consultant
</button>
<button class="tab new" data-type="loop-terminal" data-single>
<span class="eyebrow">48</span>Loop · terminal
<span class="eyebrow">49</span>Loop · terminal
</button>
<button class="tab new" data-type="policy-trace-animated" data-single>
<span class="eyebrow">49</span>Policy trace · animated
<span class="eyebrow">50</span>Policy trace · animated
</button>
<button class="tab new" data-type="queue-animated" data-single>
<span class="eyebrow">50</span>Fan-in queue · animated
<span class="eyebrow">51</span>Fan-in queue · animated
</button>
<button class="tab new" data-type="paved-road-animated" data-single>
<span class="eyebrow">51</span>Secure paved road · animated
<span class="eyebrow">52</span>Secure paved road · animated
</button>
</div>
@@ -176,7 +176,7 @@
<!-- Main Diagram -->
<div class="diagram-container">
<!-- Replace [diagram-slug] with a unique slug for this diagram before export. -->
<svg viewBox="0 0 1000 700" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="[diagram-slug]-title [diagram-slug]-desc">
<svg viewBox="0 0 1000 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="[diagram-slug]-title [diagram-slug]-desc">
<title id="[diagram-slug]-title">[Diagram title]</title>
<desc id="[diagram-slug]-desc">[One sentence describing what the diagram shows]</desc>
<defs>
+119
View File
@@ -0,0 +1,119 @@
# Environment doctor
Load this file when the user asks to run diagnostics, health checks, or first-run troubleshooting, or when they invoke `/diagram-design:doctor` or `/doctor`.
The goal is a one-shot report that checks local readiness for Diagram Design import/export and command routing, without mutating user files or installing dependencies.
Resolve the Diagram Design installation from this loaded reference, not from the
user's current working directory. A normal project directory is the expected
place to invoke the doctor and must not be treated as a repository-path error.
Use two diagnostic modes:
- **Installed-skill mode** (default): check the runtime and the resolved skill
installation. Do not require maintainer-only repository files.
- **Maintainer-checkout mode**: use this only when the resolved installation
root contains `CONTRIBUTING.md`, `.github/workflows/ci.yml`, and
`scripts/verify-plugin-package.py`. Add the repository integrity checks below.
## Inputs
Optional flags:
- `--strict` — treat warnings as failures in the final summary.
- `--json` — print a machine-readable JSON report in addition to human summary.
If no flags are provided, run in standard mode.
## Required checks
Run all checks in this order and report each as `pass`, `warn`, or `fail`.
1. Python runtime
- Resolve `python3` first, then `python`.
- Require version >= 3.10.
- `fail` if no Python interpreter is found.
- `fail` if version is below 3.10.
2. Playwright availability for PNG export
- Check whether Playwright import works in the active Python interpreter (`import playwright`).
- Check whether Chromium is installed for Playwright (`playwright install --help` availability is sufficient for command presence; prefer also checking browser cache when practical).
- If missing, mark `warn` and print exact setup hint:
- `pip install playwright && playwright install chromium`
- Never auto-install dependencies.
3. Expected script presence (maintainer-checkout mode only)
- Verify these repository scripts exist:
- `scripts/verify-drawio-import.py`
- `scripts/verify-mermaid-import.py`
- `scripts/verify-motion.py`
- `scripts/lint-skin.py`
- `scripts/verify-docs-sync.py`
- Missing scripts are `fail` in maintainer-checkout mode.
- In installed-skill mode, report that maintainer scripts are not applicable;
their absence is not a warning or failure.
4. Plugin wiring surfaces (maintainer-checkout mode only)
- Verify Claude command files exist and point to their references:
- `commands/export-diagram.md` -> `references/export.md`
- `commands/import-drawio.md` -> `references/import-drawio.md`
- `commands/import-mermaid.md` -> `references/import-mermaid.md`
- `commands/profile.md` -> `references/profiles.md`
- `commands/doctor.md` -> `references/doctor.md`
- Verify Pi prompt files exist and point to their references:
- `prompts/export-diagram.md` -> `references/export.md`
- `prompts/import-mermaid.md` -> `references/import-mermaid.md`
- `prompts/profile.md` -> `references/profiles.md`
- `prompts/doctor.md` -> `references/doctor.md`
- Missing files are `fail`.
- Mismatched reference routing is `fail`.
- In installed-skill mode, report that maintainer command/prompt wiring is not
applicable; partial or absent repository routing trees are not failures.
5. Common path mistakes
- Verify `SKILL.md` beneath the resolved installation root. Do not search for it
relative to the user's current project and do not instruct users to enter the
maintainer repository.
- Detect Windows path quoting risk when paths contain spaces and the provided command examples omit quotes.
- Detect references to local installed skill paths that do not exist (if command output includes one).
- Mark these as `warn` with a precise fix suggestion.
- A missing resolved `SKILL.md` should suggest reinstalling or updating Diagram
Design, not changing into a repository checkout.
## Output contract
Always print:
1. A compact summary line:
- `Doctor summary: <PASS|WARN|FAIL> (<pass_count> pass, <warn_count> warn, <fail_count> fail)`
2. A checklist with one line per check:
- `[PASS] Python 3.11.9 found at ...`
- `[WARN] Playwright not installed ...`
- `[FAIL] Missing scripts/verify-docs-sync.py`
3. A `Next actions` section only when warn/fail exists.
4. If `--json` is present, append JSON object with:
- `status`, `counts`, `checks[]` (`name`, `status`, `message`, `fix` optional), `timestamp`.
## Safety and behavior rules
- Read-only diagnostics only: do not modify files, do not install packages, do not run destructive git commands.
- If any command fails unexpectedly, capture stderr and continue remaining checks.
- Never claim a check passed unless verified directly in this run.
- Prefer explicit, copy-pastable remediation commands.
## Example result
```text
Doctor summary: WARN (6 pass, 2 warn, 0 fail)
[PASS] Python 3.11.9 found at /usr/bin/python3
[WARN] Playwright package not found in active interpreter
[PASS] scripts/verify-drawio-import.py present
...
Next actions
- Install PNG export dependencies: pip install playwright && playwright install chromium
- Re-run: /diagram-design:doctor --strict
```
@@ -159,7 +159,7 @@ Write the new tokens to `style-guide.md`. Suggest running the `/regenerate-examp
After onboarding, the user should:
1. Open `assets/index.html` (gallery) and confirm the new palette feels coherent across all 38 types.
1. Open `assets/index.html` (gallery) and confirm the new palette feels coherent across all 39 types.
2. If any type looks off, they usually need to tune `muted` (often too dark or too light against the new `paper`).
---
@@ -1,6 +1,6 @@
# Semantic patterns
Semantic patterns describe **what a system does**; the 38 visual types describe **how information is arranged**. Choose a pattern first when behavior, state, enforcement, or risk is load-bearing, then use its nearest visual type as the layout grammar. If no pattern matches, choose a visual type directly.
Semantic patterns describe **what a system does**; the 39 visual types describe **how information is arranged**. Choose a pattern first when behavior, state, enforcement, or risk is load-bearing, then use its nearest visual type as the layout grammar. If no pattern matches, choose a visual type directly.
Use one primary pattern per figure. A second pattern may supply at most one supporting primitive; if both need full treatment, split overview and detail. Labels and outcomes must remain complete in a static frame.
@@ -420,7 +420,7 @@ Before emitting SVG, verify **every** item. If any fails, fix it — don't ship.
1. Every cluster `node.cx` equals its chevron's `cx` (§2.2 + §2.7). This is what makes the chevron banner a real legend.
2. Every chevron `width` is a multiple of 4 and ≥ 120.
3. The reserved right strip (28 px) exists **iff** any vertical chevron is declared. If yes, `effective_w = 972`; if no, `effective_w = 1000`.
3. The reserved right strip (28 px) exists **iff** any vertical chevron is declared. If yes, `effective_w = 964`; if no, `effective_w = 1000`.
4. Exactly **one** `focal` node. If `focal` is unset in inputs, default to the first `kind: node` under chevron "Storage".
5. Every edge whose endpoint is the focal node uses `style: primary` (accent stroke + `arrow-accent` marker).
6. Every edge originating from a `kind: bar` component uses `style: trigger` (dashed + `arrow-sm`).
@@ -430,7 +430,7 @@ Before emitting SVG, verify **every** item. If any fails, fix it — don't ship.
10. Each vertical chevron pairs **1:1** with exactly one `bar` or `cross-cutting` component (§5 pairing rule). `len(verticals) == len(bars) + len(crosscuts)`.
11. `viewBox_h = max(540, strip_y_bot + 112)` — grow the canvas when multiple crosscuts are declared so the legend still fits.
12. Custom component colors (§3.4) apply only to container + icon + name; connectors stay topology-driven. Cap at 2 custom-colored components in addition to the focal.
11. The diagram passes SKILL.md §9 (4-px grid; ≤ 2 accent elements; mono only for technical content; hairlines; no shadows; no `rounded-2xl`).
13. The diagram passes SKILL.md §9 (4-px grid; ≤ 2 accent elements; mono only for technical content; hairlines; no shadows; no `rounded-2xl`).
---
@@ -0,0 +1,136 @@
# Polar Chart
**Best for:** one quantitative series across 4–8 categories whose clockwise order is meaningful.
## Input contract
```yaml
title: "Request demand by UTC window"
unit: "% of daily peak"
scale:
min: 0
max: 100
categories:
- { label: "00–03", value: 32 }
- { label: "03–06", value: 18 }
- { label: "06–09", value: 24 }
- { label: "09–12", value: 58 }
- { label: "12–15", value: 100, focal: true }
- { label: "15–18", value: 82 }
- { label: "18–21", value: 76 }
- { label: "21–24", value: 45 }
start_angle: -90
clockwise: true
source_note: "Illustrative normalized workload profile"
```
Validation rules:
1. `scale.min` is exactly `0`; truncated radial scales are invalid.
2. `scale.max` is finite and greater than `0`.
3. Every value is finite and satisfies `0 <= value <= scale.max`.
4. Category labels are unique after trimming and category count is 4–8.
5. At most one category is focal.
6. Categories retain input order; sorting by value would destroy circular meaning.
Missing values are out of scope for the first version. The agent must stop and ask whether to omit the category or supply a value; it must not coerce missing data to zero.
## Quantitative encoding
For category `i` of `N`, value `v`, center `(cx, cy)`, and outer radius `R`:
```text
theta_i = start_angle + clockwise_sign * 2π * i / N
radius_i = R * v / scale.max
x_i = cx + radius_i * cos(theta_i)
y_i = cy + radius_i * sin(theta_i)
```
Angles are expressed in radians for calculation; `start_angle` is supplied in degrees and defaults to `-90`, placing the first category at twelve o'clock. `clockwise_sign` is `+1` for the default clockwise order and `-1` otherwise.
The value ray is the line segment from `(cx, cy)` to `(x_i, y_i)`. Its visible length is exactly proportional to `v`. Endpoint circles have constant radius and encode no additional quantity. No filled sector may sit behind or beneath a value ray, because its area would compete with the declared radius encoding.
The element carrying `data-polar-chart` must be the chart's root `<svg>`. Its descendants are limited to `<g>`, `<line>`, `<circle>`, `<rect>`, `<text>`, `<title>`, and `<desc>`; nested SVGs, paths, polygons, external references, images, and every other element are rejected. Duplicate attributes, mismatched markup, URL-valued SVG references, transforms, CSS loading through `@import`/`url()`, and geometry-affecting CSS are forbidden. Chart elements carry neither `class` nor inline `style`; document styles may not use selectors capable of matching the chart, except the canonical root `svg` layout rule. The only external stylesheet allowed is Google Fonts. Every line carries exactly one of `data-polar-spoke`, `data-polar-ray`, or `data-polar-rule` and uses the role's declared stroke width; spoke and ray geometry is verified within `min(0.75 px, 5% of R)`. The five grid circles carry `data-polar-ring`, use `fill="none"`, a 0.8 px stroke, the chart center, and the 20% through 100% radius intervals exactly once. Every endpoint circle carries `data-polar-marker` and uses the declared 4 px radius, or 5 px for the focal category, with a 1.2 px stroke. The optional full-canvas background is the only rectangle and carries `data-polar-background`. This fail-closed allowlist prevents contributors from bypassing the radius-only encoding with an unannotated or falsely annotated filled shape.
### Zero
For `v = 0`, `radius_i = 0`. Render no value ray and no endpoint marker. Keep the faint full-radius category spoke, and render the category's numeric label as `0`. A single scale label at the center also marks the shared zero baseline. Do not add a minimum hub, minimum ray length, displaced marker, or other visible magnitude.
## Layout conventions
Version 1 supports:
- one quantitative series;
- 4–8 equally spaced categories in a meaningful clockwise order;
- a shared linear scale with `min = 0` and `max > 0`;
- five circular grid rings at 20%, 40%, 60%, 80%, and 100%;
- one optional focal category rendered with the accent token;
- minimal light, minimal dark, and full-editorial examples;
- horizontal, upright category labels outside the outer ring;
- one numeric value label per category.
Version 1 excludes:
- DISC, personality, competency, and role-profile wheels whose sectors are qualitative;
- arbitrary point placement within sectors;
- filled quantitative wedges, gradient bands, or donut hubs;
- multiple series, negative values, logarithmic scales, unequal sector angles, and more than eight categories;
- animation or interaction.
Use Radar for multiple entities scored across common criteria, Line for more than eight ordered time buckets, and Bar when circular order adds no meaning.
## Geometry
All three examples use `viewBox="0 0 1000 520"`, center `(500, 230)`, and `R = 160`.
- Grid rings: `r = 32, 64, 96, 128, 160`.
- Category spokes: center to `R`, 0.8 px rule stroke, no arrowhead.
- Non-focal value rays: 2 px muted stroke; endpoint marker radius 4.
- Focal value ray: 2.4 px accent stroke; endpoint marker radius 5.
- Ring labels: `0.2 × max` through `1.0 × max` on the first axis only, Geist Mono 8 px; the example therefore shows `20, 40, 60, 80, 100`.
- Category labels: at `R + 28`, Geist Sans 11 px semibold, horizontal and upright.
- Numeric labels: at `R + 44`, Geist Mono 8 px, including the unit in the chart subtitle rather than repeating it eight times.
- Label anchor: `middle` within 15 degrees of vertical, `start` on the right half, and `end` on the left half.
- Drawing order: background, rings, spokes, scale labels, non-focal rays, focal ray, endpoint markers, category labels, numeric labels, legend/source note.
The minimal examples use the full 1000×520 canvas. The full-editorial example places the same chart in the existing editorial frame and adds summary cards without changing chart geometry.
## Visual treatment
- One accent category maximum. All other value rays use the muted token.
- Circular rings and spokes are structural grid marks, never category colors.
- Endpoint markers are constant-size lollipop heads, not bubbles.
- Category labels remain horizontal; tangent rotation is intentionally excluded because it lowers scanability and belongs to the rejected qualitative wheel direction.
- The chart must remain understandable in grayscale: position and numeric labels carry the data; accent only directs attention.
- The SVG accessible description names the peak category, the scale, and the clockwise category order without narrating geometry.
## Complexity budget
- 4–8 categories.
- Exactly one quantitative series.
- At most one focal category.
- Five grid rings and one numeric value label per category.
- Static output only; split or change type rather than adding interaction or another encoding.
## When not to use
- Multiple series → use Radar.
- Non-cyclic categories → use Bar.
- More than eight ordered time buckets → use Line.
- Qualitative profiles, arbitrary sector placement, negative values, or logarithmic scales → choose a truthful non-polar representation.
## Anti-patterns
- Donut hubs or any non-zero inner baseline.
- Filled wedges, sectors, or gradient bands that imply area encodes magnitude.
- Tangent or rotated category labels.
- Multiple series on the same polar chart.
- Truncated scales whose minimum is not zero.
- Categories sorted by value instead of retaining their meaningful circular order.
- Treating a missing value as zero.
## Examples
- `assets/example-polar.html` — minimal light.
- `assets/example-polar-dark.html` — minimal dark with the same dataset and geometry.
- `assets/example-polar-full.html` — full editorial with three unequal summary cards and unchanged chart geometry.