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>
5.1 KiB
Semantic lifecycle workflows
drawio-tools keeps editable Draw.io XML and semantic Diagram IR v2 synchronized without requiring Draw.io Desktop, a browser, network access, Python, Graphviz, or ELK.
All examples run from scripts/ after pnpm install --frozen-lockfile and task build. Results are YAML on standard output. Commands that write files require an explicit --output and use an atomic temporary-file rename. Input files cannot be used as output aliases.
Import and round trip
node dist/cli/commands.js --action import \
--file architecture.drawio \
--output architecture.yaml
node dist/cli/commands.js --action build \
--file architecture.yaml \
--output rebuilt.drawio
Import accepts bare mxGraphModel documents and multi-page mxfile wrappers. It preserves stable cell IDs, labels (including deliberately empty labels), parent relationships, styles, geometry, waypoints, semantic metadata, wrapper/page/model attributes, and unknown XML children in $drawio preservation envelopes. Dangling endpoints and ambiguous identities fail closed. Import output must use .yaml, .yml, or .json.
Transactional editing
node dist/cli/commands.js --action edit \
--file architecture.yaml \
--spec ../examples/edit-batch.yaml \
--dry-run
node dist/cli/commands.js --action edit \
--file architecture.yaml \
--spec ../examples/edit-batch.yaml \
--output edited.drawio
A batch targets one page and supports typed add, update, move, delete, and connect operations. Supported preconditions are exists, not-exists, and property-equals, each expressed with a type and id; property-equals additionally requires property (the property name) and value (the exact expected value). The shipped examples/edit-batch.yaml is tied to examples/platform-v2.yaml (page system, node api) — build or import that model first, or adapt the IDs before applying the batch to another model. Unknown precondition or operation types, update payloads that attempt to change id, duplicate identifiers, invalid parents/endpoints, and non-cascading deletion of referenced elements fail closed and abort the entire batch. Dry runs return a preview and write nothing.
Linked audience views
node dist/cli/commands.js --action views \
--file architecture.yaml \
--views executive,system,deployment,dataflow,security \
--output linked-views.drawio
Views preserve source model identifiers and provenance. A sparse view records an explicit fallback reason and modeling hint rather than pretending complete coverage. Unknown view names fail closed.
Query and paths
node dist/cli/commands.js --action query --file architecture.yaml --kind service
node dist/cli/commands.js --action query --file architecture.yaml \
--property owner=platform --property 'production=true'
node dist/cli/commands.js --action query --file architecture.yaml \
--from client --to database
Queries filter by semantic kind and exact properties. --from plus --to returns a deterministic shortest directed path. Semantic operations require globally unambiguous node IDs across pages.
Architecture policy tests
node dist/cli/commands.js --action test --file architecture.yaml
node dist/cli/commands.js --action test --file architecture.yaml \
--spec ../examples/policy-rules.yaml --strict
Built-in policy identifiers:
no-direct-internet-to-databaseno-cyclesno-orphansevery-service-has-ownerproduction-has-observabilityexternal-dependencies-have-timeoutstrust-boundaries-use-protocol
Errors always fail. With --strict, warnings also fail. Unknown policy identifiers fail closed.
Failure what-if analysis
node dist/cli/commands.js --action what-if \
--file architecture.yaml --fail api
The simulation follows outgoing dependencies and stops propagation at an edge with properties.isolates_failure: true. It never mutates the source model.
Three-way synchronization
node dist/cli/commands.js --action sync \
--base generated-before.yaml \
--file manually-edited.yaml \
--spec generated-after.yaml \
--output synchronized.drawio
The base is the previous generated model, --file is the manually edited model, and --spec is the newly generated model. Synchronization preserves manual geometry/style, adds incoming identities, and reports semantic conflicts. Removed elements and pages are retained with lifecycle metadata by default; use --prune to remove them explicitly. Add --dry-run to return a preview without writing.
Offline story
node dist/cli/commands.js --action story \
--file architecture.yaml \
--fail api \
--output architecture-story.html
The output is one self-contained HTML file with a restrictive Content Security Policy, escaped labels, keyboard navigation, a complete text alternative, provenance, and an optional what-if overlay. It makes no external requests and uses square corners.
Doctor
node dist/cli/commands.js --action doctor
Doctor reports availability of optional local backends without launching them and confirms that the native core does not require network access.