
Diagram Quality
- 164 installs
- 191 repo stars
- Updated July 24, 2026
- pproenca/dot-skills
diagram-quality: A skill for development. This provides functionality for development workflows.
Key points
- diagram-quality
Diagram Quality by the numbers
- 164 all-time installs (skills.sh)
- +7 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #2,315 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pproenca/dot-skills --skill diagram-qualityAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 164 |
|---|---|
| repo stars | ★ 191 |
| Last updated | July 24, 2026 |
| Repository | pproenca/dot-skills ↗ |
How do I use diagram-quality for development tasks?
Use diagram-quality for development tasks
Who is it for?
Best when you're working on backend & apis and need structured help with diagram-quality.
Skip if: Teams with no backend & apis needs, or anyone wanting a generic chat assistant without this specific workflow.
When should I use this skill?
When you need to use diagram-quality for development tasks, or when diagram-quality: a skill for development. this provides functionality for development workflows.
What you get
Structured output aligned to diagram-quality: diagram-quality.
Files
agent-uml Diagram Quality Best Practices
Make the human-Claude design conversation converge faster on the agent-uml canvas.
When to Apply
- Before every
diagram_upsertcall — check syntax safety rules and apply the correct skinparam preset - After every
design_feedbackresponse — consult the versioning decision table to choose the right next action - When starting a new design session — follow the progressive detail layers for diagram ordering
- Before calling
design_export— run the export-readiness checklist - When a diagram renders blank or elements aren't clickable — consult rendering safety rules
Rule Categories by Priority
| Priority | Section | Impact | Reference |
|---|---|---|---|
| 1 | Rendering Safety | CRITICAL | syn-safety.md, _presets.md |
| 2 | Conversation Mechanics | HIGH | _conversation.md |
| 3 | Design Effectiveness | MEDIUM | _design.md |
Quick Reference
1. Rendering Safety (CRITICAL)
18 rules that prevent blank canvas and ensure interactive SVG. Read syn-safety.md before writing any PlantUML source.
Key rules:
- Every element gets `as Alias` — without it, element is not clickable on canvas
- `skinparam backgroundColor transparent` — white default clashes with #f4f1ec canvas
- Copy the correct preset from [_presets.md](references/_presets.md) — one block per diagram type, matched to canvas CSS variables
2. Conversation Mechanics (HIGH)
5 decision tables for the feedback-response loop. Read _conversation.md when deciding what tool to call next.
Key tables:
- Table 4: Signal → Action — maps annotation, chat, silence, and timeout to the correct tool call
- Table 5: Message content — what to write in the
messageparameter (explain change + ask focusing question)
3. Design Effectiveness (MEDIUM)
4 heuristics with concrete thresholds. Read _design.md when planning diagram sequences or preparing for export.
Key heuristics:
- Progressive detail layers — L1 context → L2 container → L3 class → L4 behavior → L5 state
- Cross-reference traceability — every sequence participant must map to a component; every interface belongs to exactly one component boundary
- Decomposition thresholds — component >12, class >15, sequence >10 participants or >20 messages → split
How to Use
1. Starting a session: Read _conversation.md Table 3 (diagram type scope) to decide which diagram to create first 2. Writing PlantUML: Apply the skinparam preset from _presets.md, then check syn-safety.md for the rules relevant to your diagram type 3. After feedback: Consult _conversation.md Table 4 (signal → action) to decide whether to push a new version or reply with a question 4. Before export: Run the checklist in _design.md Heuristic 4
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Section definitions and ordering |
| references/syn-safety.md | 18 rendering safety rules (Incorrect/Correct) |
| references/_presets.md | 5 copy-paste skinparam presets per diagram type |
| references/_conversation.md | 5 decision tables for conversation loop |
| references/_design.md | 4 heuristics with thresholds |
| assets/templates/_template.md | Template for adding new rules |
| metadata.json | Version and reference information |
agent-uml
Version 0.1.0 pproenca April 2026
Note:
This document is mainly for agents and LLMs to follow when maintaining,
generating, or refactoring codebases. Humans may also find it useful,
but guidance here is optimized for automation and consistency by AI-assisted workflows.
---
Abstract
Quality guidelines for PlantUML diagrams rendered on the agent-uml collaborative canvas. Contains 18 rendering safety rules, 5 conversation decision tables, and 4 design effectiveness heuristics — all grounded in agent-uml's SVG element selection, canvas theme, version timeline, and chat panel behavior.
---
Table of Contents
1. Rendering Safety — CRITICAL
- 1.1 Rendering Safety — CRITICAL (Prevents HTTP 400 blank canvas and ensures interactive SVG elements)
2. Conversation Mechanics — HIGH 3. Design Effectiveness — MEDIUM
---
References
1. https://plantuml.com/ 2. [https://github.com/pproenca/agent-uml (private)](https://github.com/pproenca/agent-uml (private))
---
Source Files
This document was compiled from individual reference files. For detailed editing or extension:
| File | Description |
|---|---|
| references/_sections.md | Category definitions and impact ordering |
| assets/templates/_template.md | Template for creating new rules |
| SKILL.md | Quick reference entry point |
| metadata.json | Version and reference URLs |
{Rule Title}
{1-3 sentences explaining WHY this matters for the agent-uml canvas.}
Incorrect ({what's wrong}):
{Bad PlantUML code — production-realistic, not strawman}
{' Comments explaining the cost}Correct ({what's right}):
{Good PlantUML code — minimal diff from incorrect}
{' Comments explaining the benefit}When NOT to use this pattern:
- {Exception 1}
- {Exception 2}
{
"version": "1.0.3",
"organization": "pproenca",
"technology": "agent-uml",
"discipline": "distillation",
"type": "code-quality",
"date": "April 2026",
"abstract": "Quality guidelines for PlantUML diagrams rendered on the agent-uml collaborative canvas. Contains 18 rendering safety rules, 5 conversation decision tables, and 4 design effectiveness heuristics — all grounded in agent-uml's SVG element selection, canvas theme, version timeline, and chat panel behavior.",
"references": [
"https://plantuml.com/",
"https://github.com/pproenca/agent-uml (private)"
]
}
Conversation Mechanics
The agent-uml canvas is a conversation medium. Every diagram_upsert call pushes a new version to the timeline and optionally posts a message to the chat panel. Every design_feedback call reads what the human said (chat messages) or pointed at (element annotations). Wrong decisions here — pushing a version when you should have asked a question, or posting an empty message when you should have explained a structural change — waste the human's attention and stall convergence.
These 5 decision tables map situations to the right tool call with the right parameters.
---
Table 1: Alias Discipline Per Element Type
Every element must have an explicit as Alias to be clickable on the canvas. This table shows the exact syntax for each diagram type.
| Diagram Type | Element | Syntax | Example |
|---|---|---|---|
| component | Component | [Display Name] as Alias | [API Gateway] as APIGateway |
| component | Actor | actor "Display Name" as Alias | actor "End User" as EndUser |
| component | Interface | interface "Display Name" as Alias | interface "REST API" as RestAPI |
| component | Database | database "Display Name" as Alias | database "User DB" as UserDB |
| component | Boundary | package "Display Name" as Alias {} | package "Backend" as Backend {} |
| class | Class | class "Display Name" as Alias | class "User Service" as UserService |
| class | Interface | interface "Display Name" as Alias | interface "Repository" as Repository |
| class | Enum | enum "Display Name" as Alias | enum "OrderStatus" as OrderStatus |
| class | Abstract | abstract class "Display Name" as Alias | abstract class "Base Handler" as BaseHandler |
| sequence | Participant | participant "Display Name" as Alias | participant "Auth Service" as AuthService |
| sequence | Actor | actor "Display Name" as Alias | actor "Client" as Client |
| sequence | Boundary | boundary "Display Name" as Alias | boundary "API Layer" as APILayer |
| sequence | Control | control "Display Name" as Alias | control "Orchestrator" as Orchestrator |
| sequence | Entity | entity "Display Name" as Alias | entity "Order" as Order |
| activity | Partition | partition "Display Name" as Alias {} | partition "Validation" as Validation {} |
| state | State | state "Display Name" as Alias | state "Processing" as Processing |
Rule: If the display name is a single word identical to the alias, you still write the alias explicitly: class UserService as UserService. Relying on implicit naming is fragile across PlantUML versions.
---
Table 2: Cross-Diagram Naming Consistency
When the same concept appears in multiple diagrams, the alias must be identical or systematically derived. This enables the human to trace an annotation on one diagram to its counterpart in another.
| Situation | Alias Rule | Example |
|---|---|---|
| Same component in component + sequence diagrams | Identical alias | AuthService in both |
| Class that implements a component's interface | Component alias + suffix | Component: PaymentService, Class: PaymentServiceImpl |
| Sequence participant that represents a class | Identical alias to the class | Class: OrderService, Participant: OrderService |
| Boundary/package containing multiple classes | Shared prefix | Package: UserDomain, Classes: UserService, UserRepo |
| External system referenced across diagrams | Identical alias everywhere | StripeAPI in component, sequence, and activity |
| Database referenced in component + sequence | Identical alias | OrderDB in both |
| Actor in component + sequence | Identical alias | EndUser in both |
Anti-pattern: Using PaySvc in the component diagram and PaymentService in the sequence diagram. When the human annotates PaySvc, Claude must know it maps to PaymentService — but why make either party do that translation? Use one alias.
---
Table 3: What Each Diagram Type Shows and Excludes
Each diagram type in the diagram_upsert type enum has a specific scope. Including out-of-scope detail clutters the canvas and dilutes feedback.
| Type | Shows | Excludes | Typical Design Phase |
|---|---|---|---|
component | System boundaries, containers/services, external dependencies, communication protocols, data stores | Internal class structure, method signatures, field types | First: establish system-level architecture |
class | Domain model for ONE bounded context, relationships (inheritance, composition, dependency), key methods/fields, interfaces | Infrastructure concerns, other bounded contexts, deployment details | After component: detail one container's internals |
sequence | Interaction flow for ONE use case, message order, async boundaries, return values, alt/opt/loop fragments | Classes/methods not involved in this flow, error handling for unrelated paths | After class: animate a specific scenario |
activity | Business process flow, decision points, parallel forks/joins, swimlanes/partitions | Technical implementation, class structure, API details | When modeling workflows or business rules |
state | Lifecycle of ONE entity, transitions with guards, entry/exit actions, nested states | Other entities, infrastructure, the code that implements transitions | When modeling entity lifecycle |
Rule: If you catch yourself adding an element that belongs to a different diagram type, stop. Create a separate diagram instead of overloading the current one.
---
Table 4: When to Push a New Version vs. Ask a Question
This table maps feedback signals from design_feedback to the correct next tool call. The signal type determines whether you call diagram_upsert (push a visual change) or design_feedback with reply only (respond without changing the diagram).
| Signal | Tool Call | Action | Message Content |
|---|---|---|---|
| Annotation on specific element | diagram_upsert | Targeted fix to the annotated element | "Fixed [Element]: [what changed]. Does the relationship to [adjacent element] still hold?" |
| Chat: "X should be Y" (rename/move) | diagram_upsert | Structural change — rename, move, or reconnect | "Renamed/moved [X] → [Y]. This also affects [downstream dependency] — I updated that too." |
| Chat: "what about X?" (question) | design_feedback with reply | Probe before drawing — clarify scope/intent | "Good question. X could live in [A] or [B] depending on [tradeoff]. Which fits your architecture better?" |
| Chat: "this doesn't feel right" (vague) | design_feedback with reply | Ask which element or boundary feels wrong | "Can you click on the element or area that feels off? Or is it the overall decomposition that needs rethinking?" |
| Chat: "looks good" / "continue" | diagram_upsert (new type) | Advance to next methodology step | "Moving to [next diagram type] to detail [specific aspect]. Starting with [scope]." |
| Annotation + chat together | diagram_upsert | Address annotation first, acknowledge broader point | "Fixed [annotated element]. Regarding your chat point about [topic] — [brief response or question]." |
| 120s timeout (no feedback) | design_feedback with reply | Announce you're advancing; don't proceed silently | "No feedback received — I'll move forward with [next step]. Let me know if you'd like to revisit the current diagram." |
Key principle: Every diagram_upsert call gets a message that (a) explains what changed and (b) asks a focusing question about the next decision. Never describe what's already visible — the human can see the diagram. Never post an empty explanation.
---
Table 5: Message Parameter Content
The message parameter on diagram_upsert appears in the canvas chat panel as a Claude message. It's the primary conversational tool. These patterns maximize signal per message.
| Context | Good Message Pattern | Bad Message Pattern | Why |
|---|---|---|---|
| First diagram in session | "Starting with the component view. I've placed [N] services based on [rationale]. Is [boundary decision] right, or should [alternative]?" | "Here's the component diagram." | The human can see it's a component diagram. Ask about a decision they need to make. |
| After structural change | "Moved the auth check from Gateway to a dedicated AuthService. This means [consequence]. Does [downstream service] still call Gateway directly?" | "I updated the diagram based on your feedback." | Name what changed, state the consequence, ask about the ripple effect. |
| After annotation fix | "Changed [Element] from [old] to [new] as you annotated. This affects [related element] — I kept it as-is for now. Should it change too?" | "Fixed the annotation." | Connect the fix to its dependencies. |
| Advancing to new diagram type | "Here's the sequence for [use case]. I assumed [specific assumption] — is that right?" | "Here's the sequence diagram." | State your assumptions so the human can correct them before you build on them. |
| When design has competing options | "[Option A] keeps services independent but adds a message queue. [Option B] is simpler but couples [X] to [Y]. I drew Option A — switch to B?" | "I chose this approach." | Present the tradeoff. Let the human pick. |
Design Effectiveness
Once diagrams render correctly (Section 1) and the conversation loop works (Section 2), design quality determines whether the exported specification is something a developer can implement. These heuristics set concrete thresholds — not "keep it simple" but "split when a component diagram exceeds 12 elements."
---
Heuristic 1: Feedback Interpretation
The canvas provides three feedback channels. Each has different semantics and demands a different response posture.
| Signal | What It Means | Response Posture | Common Mistake |
|---|---|---|---|
| Element annotation | "Change THIS specific thing." The human clicked an element and typed. | Fix the annotated element in the next version. Mention the fix in the message. | Treating an annotation as a suggestion to "consider" — it's a directive. |
| Chat message | Broader concern or direction. Not tied to a single element. | May require structural rethinking. Ask a clarifying question if the scope is unclear before pushing a new version. | Immediately redrawing without understanding scope — you might change the wrong thing. |
| Silence (120s timeout) | Either carefully reviewing, satisfied, or stepped away. | Post a message via design_feedback with reply asking a specific question or announcing you're advancing. Never proceed silently. | Assuming silence means approval and pushing three more versions without checking. |
| "Looks good" / "continue" | Current diagram is approved. Ready for the next level of detail. | Advance to the next diagram type or deeper view. State what you're doing next in the message. | Staying on the same diagram and adding more detail to something already approved. |
| Multiple annotations on the same area | That area is wrong or confusing. Individual fixes won't resolve it. | Redesign that subsystem. Explain the new approach in the message before pushing the version. | Fixing annotations one by one without stepping back to see the pattern. |
| Contradictory feedback (annotation says X, chat says not-X) | The human is exploring the design space, not giving final direction. | Call out the contradiction explicitly via design_feedback reply. Ask which direction to take. | Picking one and ignoring the other. |
---
Heuristic 2: Progressive Detail Layers
Each layer of detail uses specific diagram types and references the previous layer. The element counts are upper bounds — exceeding them is a signal to split, not a hard failure.
| Layer | Diagram Type(s) | What This Layer Adds | Max Elements | References |
|---|---|---|---|---|
| L1: System Context | component | Actors, external systems, main system boundary | 7±2 boxes | Starting point — no prior layer |
| L2: Container | component (detailed) | Internal services, data stores, communication protocols | 10±3 boxes | Every box in L2 must appear inside the L1 system boundary |
| L3: Internal Structure | class | Domain model, interfaces, relationships for ONE container | 12±3 classes | Each class diagram covers exactly one L2 container |
| L4: Behavior | sequence, activity | Interaction flows, business processes | 8±2 participants, 15 messages | Every participant must map to an L2 container or L3 class |
| L5: State | state | Entity lifecycle, transitions, guards | 6±2 states | Each state diagram covers exactly one L3 entity |
Cross-Reference Traceability Rules
Element counts prevent visual overload, but traceability is what makes the exported spec implementable. These rules are mandatory:
| Rule | What It Means | Violation Signal |
|---|---|---|
| Every L4 sequence participant maps to an L2 component or L3 class | If a participant appears in a sequence diagram, it must exist as a named element (same alias) in a component or class diagram. | A participant alias that doesn't match any component/class alias = orphan. Either add the missing component/class or remove the participant. |
| Every L3 interface belongs to exactly one L2 component boundary | An interface in a class diagram must be inside a package/boundary that maps to a single L2 container. | An interface floating outside any boundary, or inside multiple boundaries = ambiguous ownership. |
| Every L2 communication arrow has a corresponding L4 sequence | If two containers communicate (arrow in component diagram), at least one sequence diagram must show the interaction. | A component-to-component arrow with no sequence = underspecified behavior. Either add the sequence or remove the arrow if it's aspirational. |
| L5 state transitions reference L4 triggers | A state transition guard or trigger should reference a message from a sequence diagram. | A transition with no identifiable trigger = magic state change. Name the triggering interaction. |
How to check: Before calling design_export, review each diagram layer and verify aliases match across layers. Flag any orphan aliases in the export message.
---
Heuristic 3: Decomposition — When to Split a Diagram
When a diagram exceeds these thresholds, split it. Don't add a note saying "simplified" — create a second diagram that covers the overflow.
| Diagram Type | Split Threshold | Split Strategy | New Diagram Scope |
|---|---|---|---|
component | >12 components | Split by bounded context or deployment boundary | Each new diagram covers one context with its external dependencies shown as simplified boxes |
class | >15 classes | Split by package or aggregate root | Each new diagram covers one package with external dependencies shown as interfaces only |
sequence | >10 participants OR >20 messages | Split by scenario or phase | Each new diagram covers one scenario; shared participants keep the same aliases |
activity | >15 activities | Split by subprocess or phase boundary | Each new diagram covers one phase; handoff points shown as start/end events |
state | >8 states | Split by state group (e.g., happy path vs. error states) | Each new diagram covers one group; transitions between groups shown as notes |
After splitting: Post a message explaining the split and how the diagrams relate: "Split the checkout sequence into two: happy path (this one) and error handling (next). Both share the same participant aliases."
---
Heuristic 4: Export-Readiness Checklist
Before calling design_export, verify every item. A failed item should be fixed in a final diagram_upsert pass, not left as a note.
| # | Check | How to Verify | Fix |
|---|---|---|---|
| 1 | All aliases are meaningful | No single-letter aliases (A, B) or generic names (Service1) | Rename to domain terms: PaymentService, OrderDB |
| 2 | Skinparams consistent across diagrams | Every diagram uses the same preset from _presets.md | Re-apply the correct preset block |
| 3 | No TODO/placeholder notes | Search for TODO, TBD, placeholder, ??? in puml_source | Either resolve the TODO or remove the element |
| 4 | Every diagram has a title | Each puml_source contains a title line | Add title [System] - [View Type] |
| 5 | Cross-diagram aliases match | Same concept uses identical alias string everywhere (see Heuristic 2 traceability rules) | Standardize on one alias per concept |
| 6 | No orphan elements | Every element has at least one relationship (arrow, containment, or note) | Remove or connect the orphan |
| 7 | Notes explain WHY, not WHAT | Notes describe design rationale, constraints, or tradeoffs — not restating what the diagram already shows visually | Rewrite: "Uses async because order processing takes 2-5s" not "This is the order service" |
Canvas Skinparam Presets
Copy-paste the appropriate preset block at the top of every diagram, immediately after @startuml. These presets match the agent-uml canvas theme:
| Canvas Variable | Hex | Usage |
|---|---|---|
--bg | #f4f1ec | Canvas background (warm beige) |
--bg-raised | #ffffff | Element fill (white, visible on beige) |
--bg-inset | #eae6df | Subtle inset / header backgrounds |
--border | #78716c | Default borders and arrows |
--border-strong | #b8b0a2 | Emphasis borders |
--text | #1c1917 | Primary text |
--text-muted | #78716c | Secondary text |
--accent | #b45309 | Warm orange accent (highlights, note borders) |
--accent-bg | #fef3c7 | Light orange (note backgrounds) |
---
Component Diagram Preset
skinparam backgroundColor transparent
skinparam defaultFontColor #1c1917
skinparam defaultFontSize 13
skinparam componentBackgroundColor #ffffff
skinparam componentBorderColor #78716c
skinparam componentFontColor #1c1917
skinparam interfaceBackgroundColor #fef3c7
skinparam interfaceBorderColor #b45309
skinparam packageBackgroundColor #f4f1ec
skinparam packageBorderColor #b8b0a2
skinparam arrowColor #78716c
skinparam arrowFontColor #78716c
skinparam noteBackgroundColor #fef3c7
skinparam noteBorderColor #b45309
skinparam noteFontColor #1c1917Class Diagram Preset
skinparam backgroundColor transparent
skinparam defaultFontColor #1c1917
skinparam defaultFontSize 13
skinparam classBackgroundColor #ffffff
skinparam classBorderColor #78716c
skinparam classFontColor #1c1917
skinparam classHeaderBackgroundColor #eae6df
skinparam classAttributeFontColor #1c1917
skinparam classStereotypeFontColor #78716c
skinparam abstractClassBackgroundColor #ffffff
skinparam abstractClassBorderColor #b8b0a2
skinparam interfaceBackgroundColor #fef3c7
skinparam interfaceBorderColor #b45309
skinparam enumBackgroundColor #ffffff
skinparam enumBorderColor #78716c
skinparam packageBackgroundColor #f4f1ec
skinparam packageBorderColor #b8b0a2
skinparam arrowColor #78716c
skinparam arrowFontColor #78716c
skinparam noteBackgroundColor #fef3c7
skinparam noteBorderColor #b45309
skinparam noteFontColor #1c1917Sequence Diagram Preset
skinparam backgroundColor transparent
skinparam defaultFontColor #1c1917
skinparam defaultFontSize 13
skinparam participantBackgroundColor #ffffff
skinparam participantBorderColor #78716c
skinparam participantFontColor #1c1917
skinparam actorBorderColor #78716c
skinparam actorBackgroundColor #ffffff
skinparam sequenceArrowColor #78716c
skinparam sequenceArrowFontColor #78716c
skinparam sequenceLifeLineBorderColor #d4cfc6
skinparam sequenceLifeLineBackgroundColor #eae6df
skinparam sequenceGroupBackgroundColor #f4f1ec
skinparam sequenceGroupBorderColor #b8b0a2
skinparam sequenceGroupFontColor #1c1917
skinparam sequenceDividerBackgroundColor #eae6df
skinparam sequenceDividerBorderColor #b8b0a2
skinparam noteBackgroundColor #fef3c7
skinparam noteBorderColor #b45309
skinparam noteFontColor #1c1917Activity Diagram Preset
skinparam backgroundColor transparent
skinparam defaultFontColor #1c1917
skinparam defaultFontSize 13
skinparam activityBackgroundColor #ffffff
skinparam activityBorderColor #78716c
skinparam activityFontColor #1c1917
skinparam activityDiamondBackgroundColor #fef3c7
skinparam activityDiamondBorderColor #b45309
skinparam activityDiamondFontColor #1c1917
skinparam activityBarColor #78716c
skinparam partitionBackgroundColor #f4f1ec
skinparam partitionBorderColor #b8b0a2
skinparam arrowColor #78716c
skinparam arrowFontColor #78716c
skinparam noteBackgroundColor #fef3c7
skinparam noteBorderColor #b45309
skinparam noteFontColor #1c1917State Diagram Preset
skinparam backgroundColor transparent
skinparam defaultFontColor #1c1917
skinparam defaultFontSize 13
skinparam stateBackgroundColor #ffffff
skinparam stateBorderColor #78716c
skinparam stateFontColor #1c1917
skinparam stateAttributeFontColor #78716c
skinparam stateStartColor #1c1917
skinparam stateEndColor #1c1917
skinparam arrowColor #78716c
skinparam arrowFontColor #78716c
skinparam noteBackgroundColor #fef3c7
skinparam noteBorderColor #b45309
skinparam noteFontColor #1c1917Sections
This file defines all sections, their ordering, impact levels, and descriptions. The section ID (in parentheses) is the filename prefix used to group reference files.
---
1. Rendering Safety (syn)
Impact: CRITICAL Description: PlantUML syntax errors return HTTP 400 from the rendering server, producing a blank canvas that kills the design conversation. These rules prevent rendering failures and ensure SVG output is interactive on the agent-uml canvas.
Reference files:
- syn-safety.md — 18 rules in Incorrect/Correct format
- _presets.md — 5 copy-paste skinparam blocks matched to canvas theme
2. Conversation Mechanics (conv)
Impact: HIGH Description: The agent-uml canvas is a conversation medium, not just a renderer. Wrong versioning decisions, missing aliases, or empty chat messages waste human attention and stall convergence. These decision tables map feedback signals to tool calls.
Reference file:
- _conversation.md — 5 decision tables covering alias discipline, naming consistency, diagram scope, versioning signals, and message content
3. Design Effectiveness (design)
Impact: MEDIUM Description: Once diagrams render correctly and the conversation loop works, design quality determines whether the exported spec is implementable. These heuristics set complexity thresholds and enforce traceability between diagram layers.
Reference file:
- _design.md — 4 heuristics with concrete thresholds for feedback interpretation, progressive detail, decomposition, and export readiness
Rendering Safety
PlantUML source goes through plantuml-encoder → HTTP fetch to the PlantUML server → SVG string → canvas render. A syntax error at any stage means a blank canvas and a dead conversation. The canvas then selects svg g[id] elements to make them clickable for annotations — elements without IDs are invisible to the feedback loop.
These 18 rules are ordered by blast radius: server errors first, then annotation-breaking issues, then layout problems.
---
1. Always wrap in @startuml / @enduml
The PlantUML server returns HTTP 400 for source missing the boundary markers. The diagram_upsert tool sends puml_source directly — there is no auto-wrapping.
Incorrect (missing boundary):
class UserService {
+getUser(id): User
}Correct (explicit boundaries):
@startuml
class UserService {
+getUser(id): User
}
@enduml2. Every element gets an explicit as Alias
The canvas makes SVG elements clickable by selecting svg g[id]. PlantUML only emits an id attribute on the <g> group when the element has an explicit as alias. Without it, the human cannot annotate the element — cutting off the primary feedback channel.
Incorrect (no alias — element not clickable):
@startuml
actor User
[Payment Service]
[Auth Service]
User --> [Payment Service]
[Payment Service] --> [Auth Service]
@endumlCorrect (every element aliased — all clickable):
@startuml
actor "User" as User
[Payment Service] as PaymentService
[Auth Service] as AuthService
User --> PaymentService
PaymentService --> AuthService
@enduml3. Aliases must be single-word identifiers
SVG id attributes cannot contain spaces. PlantUML silently truncates or mangles multi-word aliases, breaking the canvas g[id] selector match. Use PascalCase for compound names.
Incorrect (spaces in alias):
@startuml
[API Gateway] as API Gateway
@endumlCorrect (PascalCase alias):
@startuml
[API Gateway] as APIGateway
@enduml4. Quote display names, not aliases
Multi-word display labels need quotes. The alias (after as) must remain an unquoted identifier. Quoting the alias makes it a display-name override, not an SVG id.
Incorrect (alias quoted — SVG id becomes the literal with quotes):
@startuml
class "User Service" as "UserService"
@endumlCorrect (quotes on label only):
@startuml
class "User Service" as UserService
@enduml5. Declare sequence participants before use
Undeclared participants get auto-created by PlantUML when first referenced in a message. Auto-created participants often lack proper id attributes in the SVG, making them un-annotatable. Declaring them upfront also controls left-to-right order.
Incorrect (participants declared implicitly):
@startuml
Client -> AuthService: authenticate
AuthService -> Database: query user
@endumlCorrect (explicit declaration with aliases):
@startuml
participant "Client" as Client
participant "Auth Service" as AuthService
participant "Database" as Database
Client -> AuthService: authenticate
AuthService -> Database: query user
@enduml6. Set backgroundColor transparent
The canvas background is #f4f1ec with a dot grid. PlantUML's default white background creates a visible white rectangle that clashes with the warm canvas. Setting transparent lets the diagram float on the canvas naturally.
Incorrect (default white background):
@startuml
class UserService as UserService
@endumlCorrect (transparent background):
@startuml
skinparam backgroundColor transparent
class UserService as UserService
@enduml7. Use canvas-matched colors for element styling
The canvas CSS palette is warm and muted. PlantUML defaults (bright blue headers, primary-color arrows) create jarring contrast on #f4f1ec. Match element colors to the canvas variables — see _presets.md for copy-paste blocks per diagram type.
Incorrect (PlantUML defaults — bright blue on warm canvas):
@startuml
skinparam backgroundColor transparent
class UserService as UserService {
+getUser()
}
@endumlCorrect (canvas-matched palette):
@startuml
skinparam backgroundColor transparent
skinparam classBackgroundColor #ffffff
skinparam classBorderColor #78716c
skinparam classFontColor #1c1917
skinparam classHeaderBackgroundColor #eae6df
skinparam classArrowColor #78716c
class UserService as UserService {
+getUser()
}
@endumlSee _presets.md for complete preset blocks per diagram type — do not hand-roll skinparams.
8. Component bracket syntax preserves SVG IDs
For component diagrams, the bracket syntax [Name] as Alias produces more reliable SVG id attributes than the long-form component "Name" as Alias. The bracket form is also more concise.
Incorrect (long-form — inconsistent SVG IDs across PlantUML versions):
@startuml
component "Payment Service" as PaymentService
component "Auth Service" as AuthService
@endumlCorrect (bracket syntax — reliable IDs):
@startuml
[Payment Service] as PaymentService
[Auth Service] as AuthService
@enduml9. Escape angle brackets with tilde syntax
< and > in labels (e.g., Java/TypeScript generics) break SVG XML parsing. PlantUML uses ~ as the escape for generic type parameters.
Incorrect (raw angle brackets — SVG parse error):
@startuml
class "Repository<User>" as UserRepo
@endumlCorrect (tilde escape in quoted display name):
@startuml
class "Repository~User~" as UserRepo
@endumlAlternative (standard generics syntax — preferred when label matches alias):
@startuml
class Repository<User> as UserRepo
@endumlWhen NOT to use tilde escaping: When the class uses PlantUML's native generics syntax (class Repository<User>), angle brackets are handled correctly and produce valid SVG. Only use tilde escaping when generics appear inside a quoted display name that differs from the alias.
10. Avoid reserved words as aliases
class, interface, abstract, component, actor, participant, as, note, package, namespace are PlantUML keywords. Using them as aliases causes parse errors or silent misinterpretation.
Incorrect (alias is a keyword):
@startuml
class "Interface Layer" as interface
@endumlCorrect (descriptive alias):
@startuml
class "Interface Layer" as InterfaceLayer
@enduml11. Use modern activity diagram syntax
The legacy (*) syntax produces SVG without useful element IDs. The modern :Activity; syntax produces named elements that can receive aliases via partition blocks.
Incorrect (legacy syntax — no element IDs):
@startuml
(*) --> "Validate Input"
"Validate Input" --> "Process Order"
"Process Order" --> (*)
@endumlCorrect (modern syntax):
@startuml
start
:Validate Input;
:Process Order;
stop
@enduml12. State diagram initial and final states
Use [*] for initial and final pseudostates. Custom start/end node names create orphan elements that confuse the layout engine.
Incorrect (custom start node):
@startuml
state "Start" as Start
Start --> Pending
@enduml*Correct ([] pseudostate):**
@startuml
[*] --> Pending
Pending: Order received
@enduml13. Limit nesting to 3 levels
PlantUML's layout engine degrades beyond 3 levels of package, namespace, or rectangle nesting. Elements get crushed, labels overlap, and the SVG becomes unreadable on the canvas.
Incorrect (4 levels — layout explosion):
@startuml
package "System" {
package "Domain" {
package "User" {
package "Internal" {
class UserRepo as UserRepo
}
}
}
}
@endumlCorrect (3 levels max — flat inner layer):
@startuml
package "System" {
package "Domain" {
package "User" {
class UserRepo as UserRepo
class UserService as UserService
}
}
}
@enduml14. Use together for layout grouping
Manual direction hints (-right->, -down->) are brittle — they break when elements are added or removed. The together keyword reliably groups elements that should be visually adjacent.
Incorrect (direction hints that break on change):
@startuml
[Auth Service] as AuthService
[User Service] as UserService
[Payment Service] as PaymentService
AuthService -right-> UserService
UserService -right-> PaymentService
@endumlCorrect (together grouping):
@startuml
together {
[Auth Service] as AuthService
[User Service] as UserService
[Payment Service] as PaymentService
}
AuthService --> UserService
UserService --> PaymentService
@endumlWhen direction hints ARE appropriate: When you need a specific element on a specific side (e.g., an external system to the right of a boundary). Use sparingly — one or two hints per diagram, not on every arrow.
15. Long labels go in notes, not on arrows
Arrow labels longer than ~30 characters cause layout distortion — PlantUML tries to fit the text inline, pushing elements apart or overlapping them. Use note on link for detailed descriptions.
Incorrect (long inline label — layout distortion):
@startuml
[API Gateway] as APIGateway
[Auth Service] as AuthService
APIGateway --> AuthService : validates JWT token and checks role-based permissions
@endumlCorrect (short label + note):
@startuml
[API Gateway] as APIGateway
[Auth Service] as AuthService
APIGateway --> AuthService : authenticate
note on link
Validates JWT token and
checks role-based permissions
end note
@enduml16. Use #hex colors, not named colors
Named colors (red, orange, blue) render inconsistently across PlantUML server versions. Hex colors produce identical output on any server. Always use the canvas palette values from _presets.md.
Incorrect (named color — unpredictable rendering):
@startuml
skinparam classBorderColor grey
@endumlCorrect (hex color — deterministic):
@startuml
skinparam classBorderColor #78716c
@enduml17. Arrow direction controls layout flow
PlantUML's default arrow --> points downward. Use explicit direction suffixes to control layout: -down-> (default), -right->, -left->, -up->. This is the primary tool for controlling the overall diagram flow direction.
Incorrect (all default direction — vertical stack when horizontal is clearer):
@startuml
[Client] as Client
[Gateway] as Gateway
[Service] as Service
Client --> Gateway
Gateway --> Service
@endumlCorrect (explicit horizontal flow):
@startuml
left to right direction
[Client] as Client
[Gateway] as Gateway
[Service] as Service
Client --> Gateway
Gateway --> Service
@endumlAlternative: Use left to right direction at the top of the diagram to flip the entire layout axis. Prefer this over per-arrow direction suffixes when the whole diagram flows horizontally.
18. Every diagram gets a title
The version timeline shows dots for each version. Without titles, the human can't distinguish between versions when reviewing the timeline. The title also anchors exported diagrams.
Incorrect (no title — anonymous in timeline):
@startuml
[Payment Service] as PaymentService
@endumlCorrect (titled — identifiable in timeline):
@startuml
title Payment System - Component View
[Payment Service] as PaymentService
@endumlRelated skills
FAQ
What does diagram-quality do?
diagram-quality: A skill for development. This provides functionality for development workflows.
When should I use diagram-quality?
When you need to use diagram-quality for development tasks, or when diagram-quality: a skill for development. this provides functionality for development workflows.
What are the main capabilities?
diagram-quality.