Files
diagram-design/CONTRIBUTING.md
T
Cathryn Lavery dbc4abd965 feat(skill): pre-draw checkpoint, docs-sync gate, packaged self-check, ADRs
- SKILL.md: confirm type/pattern/size/cuts with the user before rendering;
  checklist hooks for the checkpoint and the packaged self-check
- scripts/verify-docs-sync.py: CI now fails when the frontmatter description
  loses a type's lexical hook, the gallery can't reach a shipped example, or
  the README tree names a missing file
- skills/diagram-design/scripts/self_check.py: distilled output checker that
  ships with the skill so installed agents can verify their own diagrams;
  adversarial suite in scripts/test-self-check.py
- assets/index.html: six new tabs (OAuth sequence + five single-variant
  examples with a data-single variant lock) so every shipped example is
  browsable
- docs/adr/0001-0004: settled policies recorded (pinned controller, taxonomy
  freeze, reveal-only autoplay, byte cap + trigger-rich description)
- README: It's-working-if section, new gates documented; CONTRIBUTING: gate
  table, ADR guidance, type-addition invariants; CI: two new steps
2026-08-12 17:00:08 -07:00

10 KiB

Contributing to Diagram Design

Thanks for wanting to contribute — this project only gets better with more eyes on it.

Please read CODE_OF_CONDUCT.md first. All contributions are expected to keep the community welcoming.


What this project is

Diagram Design is an agent skill (Claude Code, Codex, Pi) that produces editorial-quality diagrams as self-contained HTML files. The repo is documentation-first: skills/diagram-design/SKILL.md is the index, each of the 27 visual types has its own reference file, and the extractor scripts in skills/diagram-design/scripts/ turn draw.io and Mermaid sources into a structured IR.

See README.md for the full picture, including the design system and the import/export flows.


Before you start

  • Create an issue first for anything non-trivial (new type, behavior change, import grammar work). Small fixes and docs can go straight to a PR.
  • Work on a branch — never commit directly to main.
  • Keep the scope tight. One PR = one concern. Mixing a new diagram type with a docs rewrite makes review slow.
  • Python 3.10+ is required for the development scripts (CI runs 3.11 and 3.12 across Linux, Windows, and macOS).

Validation gates

Every validation gate below must pass before a PR is ready. They also run automatically as GitHub Actions CI (.github/workflows/ci.yml).

What it checks Command
Accessible SVG contract (unit tests for the a11y linter) python3 scripts/test-lint-a11y.py
Semantic-pattern routing python3 scripts/verify-semantic-motion.py --markdown-only
Animated-example structure and accessibility python3 scripts/verify-semantic-motion.py --example-only
Skin conformance of every example and template (colors, fonts, a11y, assets, scripts) python3 scripts/lint-skin.py --all --baseline
A single file, e.g. a new example python3 scripts/lint-skin.py skills/diagram-design/assets/example-my-type.html
Sequence-doc consistency (ATL fragments, budgets) python3 scripts/verify-sequence-oauth.py
draw.io import path (real extractor vs fixtures + docs sync) python3 scripts/verify-drawio-import.py
Mermaid import path (grammars, adversarial input, caps, docs sync) python3 scripts/verify-mermaid-import.py
Optional motion contract (fallbacks, controls, budgets, determinism) python3 scripts/test-verify-motion.py
Every shipped motion template/example python3 scripts/verify-motion.py --shipped
Docs/routing sync (description hooks, gallery reachability, README tree) python3 scripts/verify-docs-sync.py
Packaged output self-check behaves (pass + adversarial cases) python3 scripts/test-self-check.py
Generated icon assets are up to date (icons.html, primitive-icons.md) python3 scripts/build-icons.py then git diff --exit-code on the two generated files

The semantic-pattern gate also caps skills/diagram-design/SKILL.md at 40,000 bytes so the installed skill remains practical to load. If that gate fails, reduce duplication or move detail into a routed reference; do not remove routing vocabulary from frontmatter.

Run them all at once before pushing:

python3 scripts/test-lint-a11y.py \
  && python3 scripts/verify-semantic-motion.py --markdown-only \
  && python3 scripts/verify-semantic-motion.py --example-only \
  && python3 scripts/verify-motion.py --shipped \
  && python3 scripts/lint-skin.py --all --baseline \
  && python3 scripts/verify-sequence-oauth.py \
  && python3 scripts/verify-drawio-import.py \
  && python3 scripts/verify-mermaid-import.py \
  && python3 scripts/test-verify-motion.py \
  && python3 scripts/verify-docs-sync.py \
  && python3 scripts/test-self-check.py

If a gate fails

  • lint-skin.py: the failure message names the file, line, and category (color, font-family, a11y, external-asset, pure-black, script). Colors must come from the palette in skills/diagram-design/references/style-guide.md; fonts from the allowed list; diagrams must satisfy the accessible SVG contract (see below). The linter also requires the SHA-pinned controller from template-motion.html verbatim and rejects remote resources, CSS @import, non-fragment CSS url(), event handlers, srcdoc, executable URLs, and extra scripts.
  • verify-*.py: the extractor's real behavior no longer matches its fixture or the documentation, or the reference/command/prompt wiring drifted. Fix the source of truth — do not widen a test to avoid a failure.
  • Icon assets: you changed scripts/vendor/icons/ or scripts/build-icons.py and the generated files went stale. Rerun python3 scripts/build-icons.py and commit the regenerated files.

Do not add a file to scripts/lint-skin-baseline.txt to get your example through. The baseline exists only for legacy pre-2.0 examples that legitimately predate the current skin, and it still receives a11y checks.


The accessible SVG contract (a11y)

Every diagram <svg> must satisfy the contract enforced by the linter:

  1. role="img" and aria-labelledby naming the <title> and <desc>.
  2. <title> is the first child of <svg> (before <defs>).
  3. IDs are prefixed per diagram and variant: <slug>-title / <slug>-desc — for example-loop-dark.html the slug is loop-dark, so the IDs are loop-dark-title / loop-dark-desc. Bare title/desc IDs and duplicate IDs are rejected.
  4. <title> is the short subject name (≈ the <h1>, ≤ 60 chars); <desc> is one sentence describing the content, not the geometry.
  5. Purely decorative SVGs (aria-hidden="true") are exempt.

The contract lives in scripts/lint-skin.py (lint_accessible_svgs) and is unit-tested by scripts/test-lint-a11y.py. When in doubt, pattern-match an existing example.


Working on examples (diagrams)

Every diagram type ships three variants: minimal light (example-<type>.html), minimal dark (example-<type>-dark.html), and full editorial (example-<type>-full.html).

  1. Copy the closest template (skills/diagram-design/assets/template.html, template-dark.html, or template-full.html).
  2. Load the matching references/type-<name>.md and follow its layout conventions.
  3. Replace the eyebrow, h1, and SVG body; replace the [diagram-slug] placeholders with your file's slug and keep the <title>/<desc> slots filled.
  4. Run the taste gate in SKILL.md §9, then the linter:
python3 scripts/lint-skin.py skills/diagram-design/assets/example-my-type.html

New examples should be added to the gallery (assets/index.html) so they stay browsable.

Motion is opt-in. Start from skills/diagram-design/assets/template-motion.html, follow references/animation.md, and run python3 scripts/verify-motion.py <file> plus python3 scripts/test-verify-motion.py. A motion file must preserve complete no-JavaScript, reduced-motion, print, screenshot, and export states. Keep the controller byte-for-byte identical to the template; changes require updating the canonical template, example, documentation, and adversarial tests together.

Design decisions (ADRs)

Settled policies live as short records in docs/adr/ — one pinned motion controller, semantic patterns never expanding the 27-type taxonomy, the reveal-only autoplay rule, and the SKILL.md byte cap with its trigger-rich description requirement. Read the relevant ADR before proposing a change that touches one; when a PR settles a new policy, add an ADR in the same PR.

Adding a new diagram type

  1. Write skills/diagram-design/references/type-<name>.md — layout conventions, anti-patterns, and a worked pattern for that type. Mirror an existing reference's structure.
  2. Add the row to the selection table in skills/diagram-design/SKILL.md §3 and the type's name to the frontmatter description — verify-docs-sync.py fails if the description loses or lacks a type's lexical hook.
  3. Add the three example variants (see above) and register them in the gallery (assets/index.html) — verify-docs-sync.py fails on any shipped example the gallery can't reach.
  4. Run the full gate suite — new examples are linted automatically by --all.

Changing the icon set

Icons are generated, never hand-edited:

  1. Add or replace the source SVG in scripts/vendor/icons/<source>/ (tabler/, simple/, …). Keep license provenance in THIRD_PARTY_LICENSES.md accurate.
  2. Regenerate and verify:
python3 scripts/build-icons.py
git diff --exit-code -- skills/diagram-design/assets/icons.html skills/diagram-design/references/primitive-icons.md

Touching the import paths

  • draw.io: skills/diagram-design/scripts/drawio_extract.py — must pass scripts/verify-drawio-import.py, which drives the extractor against scripts/fixtures/sample-architecture.drawio in all four container formats (raw XML, deflate+base64, PNG-embedded, SVG-embedded).
  • Mermaid: skills/diagram-design/scripts/mermaid_extract.py — must pass scripts/verify-mermaid-import.py, which covers every supported grammar, multi-block Markdown, adversarial labels, trust-boundary behavior, resource caps, and named failures.

Both scripts treat their input as untrusted data — they never render, fetch, or execute source content. Keep it that way. If you add a grammar or a new security boundary, extend the corresponding verifier with a fixture before merging.

Documentation and wiring must stay in sync: the import references, SKILL.md §11, the slash commands in commands/, and the Pi prompt templates in prompts/ each describe the same flows. The verifiers check this — keep both sides updated in one PR.

Documentation

Most of this repo is documentation. When behavior changes, update the affected reference files and the README in the same PR. Loose ends here are what the verifiers and reviewers will catch.


Commit and PR conventions

Commit messages follow Conventional Commits: type(scope): summary, e.g. fix(import): support current Mermaid syntax, ci: verify Mermaid imports, docs(onboarding): clarify the URL flow. Keep summaries short and imperative.

A good PR:

  • has a clear title and a description that says what changed and why;
  • mentions how you tested it (which gates you ran);
  • keeps generated and source files consistent (extractor + verifier + reference + command in one change);
  • is rebased on main and green on CI.

Questions?

Open a discussion or comment on the relevant issue. If it's about security, use the private reporting path in SECURITY.md.