Files
diagrams-drawio/references/rules-style.md
oleg-lukasonokandClaude Code 6584df0666 Fix review findings: importer DoS, sync data loss, views/profile rendering, docs
Source importers: lstat before open so FIFOs no longer hang the directory
walk; replace the quadratic Rust macro regex with a linear scan.
Three-way sync: report page add/add and delete-vs-modify as conflicts
instead of silently overwriting or resurrecting; canonical comparison so
key order is not a change; the sync action withholds output and fails on
conflicts unless --force. Story publishing escapes <, >, & and U+2028/9
inside the embedded JSON.
Views: drop parentId of unselected containers, re-layout instead of
manual geometry, validate before serialising; flatten() merges identical
nodes repeated across pages so C4 output works with every analysis
action. Dark theme edge labels get a background; tube-map corridors sit
above the stations; C4 containers keep the swimlane style and orphan
relationships land on the matching page; router keeps container header
bands as obstacles; sequence self-messages loop on one side.
Docs: SKILL.md lists all 23 CLI actions and how each capability family
is invoked, task wrappers for query/test/what-if/doctor, capability
tables and --page scope corrected, maintenance snippet uses the real
synchronous action signature, duplicated rule bullets moved to the rule
references, coverage matrix wording made verifiable.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-06 17:01:50 +03:00

81 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# diagrams-drawio — Style Rules
Visual appearance and sizing rules for draw.io diagrams generated by this skill.
These rules are **MANDATORY** — apply them when generating any diagram.
---
## General style rules — MANDATORY
- **All child shapes within the same swimlane must have the same height** — never mix different heights within one swimlane layer/row
- **Rectangles must never use rounding** — always set `rounded=0` on rectangle shapes
- Prefer dimensions divisible by 40; wrap non-divisible vendor icons in a grid-aligned container
- **The space between sibling shapes of the same level (same swimlane, same row) must be divisible by 40px** — use 40px as the minimum gap. If a swimlane row has shapes of width W and gap G, the step between shape origins = W + G where G ≥ 40 and G mod 40 = 0.
- **Swimlane `startSize` (header height) must be divisible by 40** — use `startSize=40`
- **Swimlane body height (total − startSize) must be divisible by 40** — so total height = 40 + N×40 = a multiple of 40
- Example: `startSize=40`, body=80 → total=120 ✓; body=160 → total=200 ✓
- Use ≤ 3 primary color families; create hierarchy with shades
- Keep connector colors simple and consistent; use dashed connectors only for semantically distinct flows (async, backup, admin, private)
- Avoid borders on shapes unless needed for visual separation or canonical styling
- Shape size is driven by **content**, not routing — typically 80–160px tall per label line
### Text fit and cards
- Avoid long text inside narrow shapes; use wider cards or wrap the label in a dedicated text area inside the card
- Service names must fit within the visual card width and never extend beyond card boundaries
- For service-card diagrams use one consistent card pattern: icon on the left, service label on the right, enough padding around both
- When using canonical vendor icons, **preserve the original icon styling**; adjust the surrounding card/container layout instead of modifying the icon style
---
## Connector routing rules — MANDATORY
- **All outgoing connectors from the same shape must share a single exit point** — never let multiple connectors leave a shape at different X/Y coordinates. Pick one exit side (top/bottom/left/right) and one coordinate on that side; all outgoing connectors use it as their first waypoint.
- **All incoming connectors to the same shape must share a single entry point** — never let multiple connectors enter a shape at different X/Y coordinates. Pick one entry side and one coordinate; all incoming connectors use it as their last waypoint before the shape.
- **Connectors must never attach at a shape corner** — the exit/entry point must lie on the middle of a side: top-center, bottom-center, left-center, or right-center. A point that is simultaneously on both an X-edge (left or right) AND a Y-edge (top or bottom) of the shape bounding box is a corner and is forbidden. Use the midpoint of the chosen side: `x_mid = (x1+x2)/2` for top/bottom sides, `y_mid = (y1+y2)/2` for left/right sides.
- These rules ensure a clean "bus-bar" fan-out/fan-in pattern and prevent connectors from diverging at their source or converging at their target at different positions, which creates visual clutter and increases crossing risk.
- Exception: shapes with only a single outgoing or single incoming connector — the single-port rule trivially holds. The corner rule still applies.
- **Arrowheads stay outside shape interiors** — connectors touch the shape/card edge and never pass through the body.
- When computing waypoints: use `page-negative-space-summary` to find free X corridors per row, then pick an exit/entry coordinate that lies within a free corridor at the next traversed level. This minimises connector-shape overlaps and connector crossings.
- **Waypoints must never be closer than 20px to any shape** — the first waypoint after a shape exit must be at least 20px away from the shape's edge in the direction of travel (e.g., if exiting bottom at y=520, first waypoint y ≥ 540; if exiting right at x=1040, first waypoint x ≥ 1060). The last waypoint before a shape entry must likewise be at least 20px away from the shape's edge. This 20px clearance also applies to any waypoint relative to same-level sibling shapes the connector passes by — the waypoint must not come within 20px of any sibling shape's bounding box side it is adjacent to.
---
## Text-width estimation — negative space calculation
When computing negative space manually (e.g. for a negative-space diagram), **shape bounding boxes alone overestimate occupied space**. Text labels only occupy a sub-region within the shape bbox. Use the following formula to estimate the text rendering width:
```
charWidth = fontSize × 0.6 // avg glyph width for proportional fonts
rawWidth = longestLineChrCount × charWidth
padding = fontSize × 1.0 // horizontal padding (~0.5em each side)
textWidth = rawWidth + padding
fontStyle modifiers (draw.io flags):
bit 0 (value 1) = bold → charWidth × 1.10
bit 1 (value 2) = italic → charWidth × 1.05
textXMin = clamp(shapeCenterX − textWidth/2, shape.xMin, shape.xMax)
textXMax = clamp(shapeCenterX + textWidth/2, shape.xMin, shape.xMax)
```
**When to apply:**
- Swimlane headers (`startSize=40` band): the header text is centered in the full zone width. Use text region for occupied X, flanks are free negative space.
- Large container shapes whose children don't fill the full width.
- Any shape where `textWidth < shapeWidth` — the flanks inside the bbox are free.
**Example — zone headers at fontSize=12 bold (fontStyle=1), center x=660, zone x=80..1240:**
| Label | chars | charWidth | rawWidth | padding | textWidth | textXMin | textXMax | flank each side |
|---|---|---|---|---|---|---|---|---|
| "Client Layer" | 12 | 7.9 | 95 | 12 | 107 | 607 | 713 | ~527pt |
| "API Gateway / Edge Layer" | 24 | 7.9 | 190 | 12 | 202 | 559 | 761 | ~479pt |
| "Core Microservices" | 18 | 7.9 | 143 | 12 | 155 | 583 | 737 | ~503pt |
| "Messaging / Event Bus" | 21 | 7.9 | 166 | 12 | 178 | 571 | 749 | ~491pt |
| "Data Layer" | 10 | 7.9 | 79 | 12 | 91 | 615 | 705 | ~535pt |
**The `page-negative-space-summary` action now outputs these fields per shape:**
- `textXMin`, `textXMax`, `textWidth` — estimated text rendering region
- `textFlankLeft`, `textFlankRight` — free space flanking text inside bbox
- `rows[].textAwareFreeCorridors` — free corridors computed using text regions (wider than bbox-based corridors)