Skip to content

feat: add architecture diagram skill#103

Open
mayakost wants to merge 11 commits intomainfrom
feat/diagram-skill
Open

feat: add architecture diagram skill#103
mayakost wants to merge 11 commits intomainfrom
feat/diagram-skill

Conversation

@mayakost
Copy link
Contributor

Summary

  • Adds a new aws-architecture-diagram skill to the deploy-on-aws plugin that generates validated AWS architecture diagrams as draw.io XML using official AWS4 icon libraries
  • Includes PostToolUse hook for automatic draw.io validation on Edit/Write, Python post-processing scripts (icon color fixes, nesting fixes, step badge rendering), and extensive reference material (style guide, XML templates, 6 annotated example diagrams)
  • Bumps deploy-on-aws plugin version from 1.1.0 to 1.2.0 and updates marketplace/plugin manifests with new keywords and description

Test plan

  • Install the plugin locally with claude --plugin-dir ./plugins/deploy-on-aws and trigger the skill by asking to generate an AWS architecture diagram
  • Verify the generated .drawio file opens correctly in draw.io desktop and renders with proper AWS4 icons, step badges, and category containers
  • Confirm the PostToolUse validation hook fires when writing/editing .drawio files and catches malformed XML
  • Run mise run lint:manifests to validate updated marketplace.json and plugin.json
  • Run mise run lint:cross-refs to validate cross-references between manifests
  • Test both modes: codebase analysis ("analyze my infrastructure") and interactive brainstorm ("design a serverless API")

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.

mayakost and others added 3 commits March 20, 2026 19:59
…arkdown lint

Replace xml.etree.ElementTree with defusedxml.ElementTree in all Python
scripts to address Bandit B314/B405 and Semgrep XXE findings. Add nosec
suppression to subprocess import in drawio_url.py (browser URL opener only).
Fix 106 markdownlint errors (MD022/MD031/MD032 blank lines, MD001 heading
levels) across 7 reference files and SKILL.md. Trim SKILL.md from 515 to
495 lines to satisfy the 500-line SKILL001 limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mayakost mayakost requested review from a team as code owners March 23, 2026 16:18
@mayakost mayakost changed the title Add architecture diagram skill feat: add architecture diagram skill Mar 23, 2026
mayakost and others added 7 commits March 23, 2026 12:43
Move detailed XML generation rules and layout guidelines from SKILL.md
(494 lines) into references/xml-generation-rules.md and
references/layout-guidelines.md. SKILL.md is now 219 lines, well under
the 300-line warning threshold enforced by SKILL001.
Run dprint fmt on 7 files (JSON and Markdown) that were not
conforming to the project's formatting rules.
…sues

- Replace defusedxml with stdlib xml.etree.ElementTree in all 5 Python
  scripts and validate-drawio.sh (XML is self-generated, no XXE risk)
- Remove pip3 auto-install from PostToolUse hook
- Remove unused import sys in fix_step_badges.py
- Remove unused style variable in post_process_drawio.py fix_legend_size
- Add explanatory comment to except block in post_process_drawio.py
…ples

Delete 5 files (-2039 lines):
- example-diagrams.md (803 lines): outdated XML examples conflicting with .drawio refs
- aws-diagram-guidelines.md (536 lines): internal wiki copy, all rules in style-guide.md
- xml-structure.md (209 lines): merged unique parts into group-styles.md + layout-guidelines.md
- xml-generation-rules.md (186 lines): trimmed and renamed to xml-rules.md (89 lines)
- aws4-shapes.md (231 lines): split into aws4-shapes-services.md (69) + aws4-shapes-resources.md (100)

All reference files now under 100-line DESIGN_GUIDELINES limit.
All shape names preserved in the split files (zero shape deletions).
All cross-references updated to point to new file names.
- Remove eager "Study" paragraph that loaded ~135k tokens upfront
- Move reference loading into Step 3 where references are actually needed
- Add example selection table: agent picks 1-2 most relevant .drawio
  examples per diagram type (reduces ~95k to ~10-18k tokens)
- Update cross-references to renamed files (xml-rules.md,
  aws4-shapes-services.md)
- SKILL.md: 226 lines (under 300 limit)
…s for dark mode

- Remove background="#FFFFFF" from mxGraphModel XML template in SKILL.md
- Change rule from "ALWAYS set background=#FFFFFF" to "NEVER set background"
- Change edge label rule from labelBackgroundColor=#ffffff to
  labelBackgroundColor=none in layout-guidelines.md and xml-rules.md
- Both white backgrounds break dark mode adaptive contrast
- New references/general-icons.md: maps 40+ non-AWS technologies
  (PostgreSQL, Docker, Kubernetes, CoreML, HuggingFace, GitHub, etc.)
  to draw.io shapes with category-appropriate tint colors
- Mode A codebase analysis now detects non-AWS tech when no AWS
  infrastructure files are found (Dockerfiles, DB configs, ML frameworks)
- Mixed architectures supported: AWS icons for AWS services, general
  icons for non-AWS, same layout rules for both
- Step 3 loads general-icons.md only when non-AWS services are present
@scoropeza
Copy link
Contributor

scoropeza commented Mar 24, 2026

PR Review Findings

I reviewed this PR and found 8 issues + 1 additional dark mode bug. All have been addressed in 5 new commits on this branch.

Findings Addressed

# Finding Fix
1 example-diagrams.md teaches outdated style (803 lines) Deleted — 7 .drawio files are authoritative
2 SKILL.md eager-loads ~135k tokens Restructured for progressive disclosure — refs load in Step 3
3 All 7 examples loaded (~95k tokens) Added example selection table — agent picks 1-2 per type
4 4 reference files exceed 100-line limit Consolidated: deleted 5 files (-2039 lines), split/trimmed rest
5 pip3 install defusedxml on every hook Switched to stdlib xml.etree.ElementTree (self-generated XML, no XXE risk)
6 Hook matches all Edit/Write Documented in post-processing.md (correct behavior, <10ms exit for non-.drawio)
7 Code quality (unused imports, variables) Fixed in fix_step_badges.py and post_process_drawio.py
8 No dependency declaration Moot — defusedxml removed entirely

Additional Fix

  • Dark mode: Removed background="#FFFFFF" from mxGraphModel template and labelBackgroundColor=#ffffff from edge labels — both broke dark mode adaptive contrast

New Feature

  • Non-AWS architecture support: Added general-icons.md reference mapping 40+ non-AWS technologies (PostgreSQL, Docker, CoreML, HuggingFace, etc.) to draw.io shapes with category tinting. The skill now handles pure non-AWS, mixed, and pure AWS architectures.

Commits

  1. d92c414 fix: remove defusedxml dependency, fix code quality
  2. 68caa21 refactor: consolidate references, delete outdated examples
  3. 1d1a401 refactor: restructure SKILL.md for progressive disclosure
  4. 35fc174 fix: remove white backgrounds for dark mode
  5. 41ae138 feat: support non-AWS architecture diagrams

Keep all new plugins from main (amazon-location-service, aws-amplify,
aws-serverless, databases-on-aws, migration-to-aws) and apply our
diagram skill additions to deploy-on-aws (description, keywords, tags,
version bump to 1.2.0).
parser.add_argument("--verbose", "-v", action="store_true")
args = parser.parse_args()

tree = ET.parse(args.file)

Check warning

Code scanning / Bandit

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called Warning

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called
parser.add_argument("--verbose", "-v", action="store_true")
args = parser.parse_args()

tree = ET.parse(args.file)

Check warning

Code scanning / Bandit

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called Warning

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called
)
args = parser.parse_args()

tree = ET.parse(args.file)

Check warning

Code scanning / Bandit

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called Warning

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called
sys.exit(0)

try:
tree = ET.parse(file_path)

Check warning

Code scanning / Bandit

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called Warning

Using xml.etree.ElementTree.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.parse with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called

# Parse XML
try:
root = ET.fromstring(xml_text)

Check warning

Code scanning / Bandit

Using xml.etree.ElementTree.fromstring to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.fromstring with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called Warning

Using xml.etree.ElementTree.fromstring to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree.fromstring with its defusedxml equivalent function or make sure defusedxml.defuse_stdlib() is called
"""

import argparse
import xml.etree.ElementTree as ET

Check notice

Code scanning / Bandit

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called. Note

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called.
"""

import argparse
import xml.etree.ElementTree as ET

Check notice

Code scanning / Bandit

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called. Note

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called.
import argparse
import math
import re
import xml.etree.ElementTree as ET

Check notice

Code scanning / Bandit

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called. Note

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called.
import argparse
import json
import sys
import xml.etree.ElementTree as ET

Check notice

Code scanning / Bandit

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called. Note

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called.
import json
import re
import sys
import xml.etree.ElementTree as ET

Check notice

Code scanning / Bandit

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called. Note

Using xml.etree.ElementTree to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.etree.ElementTree with the equivalent defusedxml package, or make sure defusedxml.defuse_stdlib() is called.
Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep OSS found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants