Generate Mermaid collaboration diagrams embedded in markdown, visualizing system interactions and workflows from domain concepts and requirements. Creates sequence diagrams, flowcharts, class diagrams, and interaction patterns with traceability links to source requirements. This skill is the single authoritative source for boundary validation rules VR-1 through VR-4 and their check algorithms; other skills (e.g., edps-compliance) delegate VR checking to this skill rather than reimplementing it.
Generate visual collaboration diagrams from domain analysis to illustrate system interactions, user workflows, entity relationships, and domain models using Mermaid syntax embedded in markdown.
Transform analyzed domain concepts and requirements into clear, actionable collaboration diagrams that visualize key system interactions, user journeys, cross-system workflows, and domain entity relationships. Focus on communicating complex relationships through standardized diagram patterns.
projects/[project-name]/artifacts/Analysis/domain-concepts.json (from domain-extractconcepts skill)projects/[project-name]/artifacts/Analysis/requirements.json (from requirements-ingest skill)orgModel/**/domain-model.md (existing domain models for class diagram generation)projects/[project-name]/artifacts/Analysis/goals.json (from goals-extract skill)Files Generated:
projects/[project-name]/artifacts/Analysis/collaboration-diagrams.md - Markdown with embedded Mermaid diagramsprojects/[project-name]/artifacts/Analysis/collaboration-diagrams.json - Structured diagram metadataorgModel/**/domain-model.md - Updated organizational domain models with embedded class diagrams (when domain-model integration is requested)collaboration-diagrams.md)# Collaboration Diagrams
**Project**: [project_id]
**Generated**: [timestamp]
**Source**: domain-concepts.json, requirements.json
## Domain Class Model
### Entity Relationship Overview *(Diagram D-001)*
**Source Requirements**: [R-001], [R-003]
**Domain Source**: orgModel/01-skill-dev/domain-model.md
```mermaid
classDiagram
class User:::core {
+user_id: String
+name: String
+email: String
+role: UserRole
+authenticate()
+updateProfile()
}
class UserRole:::core {
+role_id: String
+name: String
+permissions: String[]
+grantAccess()
}
class Session:::entity {
+session_id: String
+start_time: DateTime
+expiry_time: DateTime
+is_active: Boolean
+extend()
+terminate()
}
User "1" --> "1" UserRole : has
User "1" *-- "*" Session : creates
%% Styling Definitions
classDef core fill:#e1f5fe
classDef entity fill:#f3e5f5
classDef enum fill:#fff3e0
classDef ai fill:#e8f5e8
Source Requirements: [R-001], [R-003]
Entities Involved: User, AuthenticationService, Database
sequenceDiagram
participant U as User
participant AS as AuthenticationService
participant DB as Database
U->>AS: Login request (username, password)
AS->>DB: Validate credentials
DB-->>AS: User record
AS->>AS: Generate JWT token
AS-->>U: Authentication response (token)
Note over AS: Token valid for 24 hours
Note over U,DB: Secure HTTPS communication
Source Requirements: [R-005], [R-007]
Entities Involved: APIGateway, ExternalService, Cache
sequenceDiagram
participant AG as API Gateway
participant ES as External Service
participant C as Cache
AG->>C: Check cache for data
alt Cache Hit
C-->>AG: Return cached data
else Cache Miss
AG->>ES: Request external data
ES-->>AG: Return fresh data
AG->>C: Store in cache (TTL: 5min)
end
AG-->>Client: Return data response
Source Requirements: [R-010]
Decomposition: 01-ECommerce-Platform/collaboration.md
sequenceDiagram
%% Stereotypes: User=actor | ECommerce=control | Payment=control | Shipping=control
participant User as "User"
box "E-commerce Platform"
participant ECommerce as "E-commerce Platform"
end
box "Payment System"
participant Payment as "Payment System"
end
box "Shipping System"
participant Shipping as "Shipping System"
end
User->>ECommerce: Place Order
ECommerce->>Payment: Process Payment
ECommerce->>Shipping: Schedule Delivery
### JSON Structure (`collaboration-diagrams.json`)
```json
{
"project_id": "string",
"generation_metadata": {
"generated_at": "ISO8601",
"source_files": ["domain-concepts.json", "requirements.json"],
"total_diagrams": "number",
"diagram_types": ["class", "sequence", "flowchart", "stateDiagram"]
},
"diagrams": [
{
"id": "D-001",
"title": "Entity Relationship Overview",
"type": "class",
"category": "domain-model",
"description": "Core domain entities and their relationships",
"entities": ["User", "UserRole", "Session"],
"source_requirements": ["R-001", "R-003"],
"mermaid_code": "classDiagram...",
"complexity": "medium",
"maintenance_priority": "high"
},
{
"id": "D-002",
"title": "Authentication Flow",
"type": "sequence",
"category": "user-system",
"description": "User authentication and JWT token generation",
"entities": ["User", "AuthenticationService", "Database"],
"source_requirements": ["R-001", "R-003"],
"mermaid_code": "sequenceDiagram...",
"complexity": "medium",
"maintenance_priority": "high"
}
]
}
From domain-concepts.json:
From requirements.json:
For Hierarchical Diagrams (Optional):
<<Actor>>, <<System>>, <<UI>>, <<Entity>>) from domain conceptsDomain Class Models:
User-System Interactions:
System-System Interactions:
Business Process Workflows:
Hierarchical Diagrams:
box syntax to represent system boundaries<<System>> participants into Level 1+ diagramsClass Diagrams:
classDiagram
class [EntityName]:::[styleCategory] {
+attribute_name: Type
-private_attribute: Type
+operation_name()
-private_operation()
}
%% UML Relationship Notation (MANDATORY — do NOT use ER notation like ||--o{ )
%% Association: ClassA "1" --> "*" ClassB : label
%% Composition: Parent "1" *-- "*" Child : label
%% Aggregation: Whole "1" o-- "*" Part : label
%% Inheritance: Parent <|-- Child
%% Dependency: Client ..> Service : uses
%% Realization: Interface <|.. Implementation
%%
%% Multiplicity: "1", "*", "0..1", "1..*", "0..*"
%% FORBIDDEN: ||--o{ }o--|| }o--o{ ||--|| (these are ER notation, not UML)
[SourceEntity] "1" --> "*" [TargetEntity] : relationship_label
[ParentEntity] <|-- [ChildEntity]
[CompositeEntity] "1" *-- "*" [ComponentEntity] : contains
[AggregateEntity] "1" o-- "*" [PartEntity] : has
[Client] ..> [Service] : uses
%% Apply :::style directly on class body declarations
%% RIGHT: class User:::core { +name: String }
%% WRONG: class User { +name: String } then User:::core
%% Styling Definitions
classDef [styleCategory] fill:#[color]
classDef actor fill:#e1f5fe
classDef entity fill:#f3e5f5
classDef enum fill:#fff3e0
classDef ai fill:#e8f5e8
Naming Conventions for Class Diagrams:
--> (association), *-- (composition), o-- (aggregation), <|-- (inheritance), ..> (dependency)"1", "*", "0..1", etc. on both sides of the relationship||--o{, }o--||, }o--o{, ||--||) in class diagrams — those belong in erDiagram blocks only:::styleCategory directly on class body declarations: class Name:::style { } — this is the preferred formatSequence Diagrams:
participant [ShortName] as [Full Entity Name]
[Actor]->>+[Target]: [Action description]
[Target]-->>-[Actor]: [Response description]
Note over [Entity]: [Important information]
alt [Condition]
[Alternative flow]
else [Other condition]
[Alternative flow]
end
Naming Conventions:
Hierarchical Sequence Diagrams (with Boundaries):
sequenceDiagram
%% Stereotypes: [ActorAlias]=actor | [BoundaryAlias]=boundary, [ControlAlias]=control, [EntityAlias]=entity
participant [ActorName] as "[Full Actor Name]"
box "[BoundaryName]"
participant [BoundaryAlias] as "[Full Participant Name]"
participant [ControlAlias] as "[Full Participant Name]"
participant [EntityAlias] as "[Full Participant Name]"
end
[ActorName]->>[BoundaryAlias]: [Interaction]
Naming and Stereotype Conventions:
participant [Alias] as "[Label]" syntax for all participants%% Stereotypes: comment at the top of the diagram, using the format: Alias=type separated by commas within a boundary and | between boundariesactor, boundary, control, entitybox "Boundary Name" for maximum renderer compatibilityRequirement References:
[R-XXX] formatENT-XXX identifiers from domain conceptsorgModel/**/*domain-model.md paths for class diagramsDiagram Metadata:
D-001, D-002, etc.)For Hierarchical Diagrams:
decomposition field in diagram metadata to link to child diagramsEvery participant in a hierarchical collaboration diagram must be classified into exactly one of four stereotypes. Classification drives annotation generation, decomposition eligibility, and message routing validation.
| Stereotype | Comment value | Role | Decomposable? |
|---|---|---|---|
| Actor | actor | External entity that initiates interactions | No |
| Boundary | boundary | Interface mediator between actors and internal components | No |
| Control | control | Business logic / orchestration component | Yes |
| Entity | entity | Data store or passive resource | No |
When a participant does not have an explicit stereotype, the skill infers its type using the following ordered heuristic rules:
Actor inference — A participant is classified as actor when:
box boundaries<<Actor>> stereotype tag in domain conceptsBoundary inference — A participant is classified as boundary when:
box to receive a message from an external actor<<UI>> stereotype tag in domain conceptsEntity inference — A participant is classified as entity when:
<<Entity>> stereotype tag in domain conceptsControl inference (default) — A participant is classified as control when:
<<System>> stereotype tag in domain conceptscontrolExplicit type specification always takes precedence over inference. Types can be set via:
Input JSON:
{
"participants": [
{ "name": "OrderService", "stereotype": "control" },
{ "name": "AuditLog", "stereotype": "entity" },
{ "name": "AdminPortal", "stereotype": "boundary" }
]
}
Inline annotation (already in diagram):
%% Stereotypes: OrderService=control
participant OrderService as "Order Service"
When a manual override conflicts with inferred type, the override wins and a note is added to the diagram metadata:
{
"type_overrides": [
{ "participant": "AuditLog", "inferred": "control", "override": "entity", "reason": "manual" }
]
}
After classification, every participant definition in the Mermaid output must use the standard participant [Alias] as "[Label]" syntax, with stereotypes tracked in a %% Stereotypes: comment:
sequenceDiagram
%% Stereotypes: Customer=actor | API=boundary, OrderSvc=control, OrderDB=entity
participant Customer as "Customer"
box "Order Processing"
participant API as "Order API"
participant OrderSvc as "Order Service"
participant OrderDB as "Order Database"
end
Customer->>API: Place Order
API->>OrderSvc: Process Order
OrderSvc->>OrderDB: Store Order
Generation rules:
participant [Alias] as "[Label]" for every participant%% Stereotypes: comment listing all participants with their typesAlias=type pairs, separated by commas within a box and | between boxesbox blockbox block@{ "type": "...", "label": "..." } syntax — it is not supported by most Mermaid renderers (GitHub, Mermaid Live, VS Code preview)box "Name" not box NameBefore generating a decomposition (sub-process diagram) for any participant, the skill must validate decomposition eligibility:
"type": "control" may be decomposed into sub-process diagramsactor, boundary, or entity participant must produce a validation errorValidation output on violation:
{
"validation_errors": [
{
"rule": "control-only-decomposition",
"participant": "CustomerDB",
"type": "entity",
"message": "Cannot decompose participant 'CustomerDB' (type: entity). Only control-type participants can be decomposed into sub-processes.",
"suggestion": "If this participant requires internal detail, consider reclassifying it as 'control' or modeling its internals as a separate entity-focused diagram."
}
]
}
box boundary, the first message from an external actor must be received by a boundary-type participantcontrol or entity participant inside a box, a validation error is generatedValid pattern:
Customer (actor) ->> API (boundary) ->> Service (control) ->> DB (entity)
Invalid pattern (produces error):
Customer (actor) ->> Service (control) ❌ skips boundary
Validation output on violation:
{
"validation_errors": [
{
"rule": "boundary-first-reception",
"boundary": "Order Processing",
"actor": "Customer",
"received_by": "OrderService",
"received_by_type": "control",
"message": "Actor 'Customer' sends directly to 'OrderService' (type: control) inside boundary 'Order Processing'. Messages from actors must be received by a boundary-type participant first.",
"suggestion": "Add or designate a boundary-type participant (e.g., API Gateway) as the entry point for this boundary."
}
]
}
actor-type participants must never appear inside a box boundarybox blockentity-type participants should not be decomposedWhen a participant is decomposed from Level N to Level N+1:
boundary-type participant matching the parent's external interfacecontrol at Level N cannot appear as entity at Level N+1After classification, the skill generates a type summary in the diagram metadata:
{
"participant_type_summary": {
"total_participants": 8,
"by_type": {
"actor": { "count": 2, "participants": ["Customer", "Admin"] },
"boundary": { "count": 2, "participants": ["WebUI", "AdminPortal"] },
"control": { "count": 3, "participants": ["OrderService", "PaymentService", "NotificationService"] },
"entity": { "count": 1, "participants": ["OrderDB"] }
},
"decomposable": ["OrderService", "PaymentService", "NotificationService"],
"type_overrides": [],
"inference_confidence": {
"high": ["Customer", "WebUI", "OrderDB"],
"medium": ["OrderService", "PaymentService"],
"low": ["NotificationService"]
}
}
}
{
"stereotype_classification": true,
"auto_inference": true,
"manual_overrides": [
{ "participant": "AuditLog", "type": "entity" }
],
"enforce_decomposition_rules": true,
"enforce_boundary_first_reception": true,
"generate_type_summary": true
}
This section defines how the skill generates Mermaid box ... end syntax blocks for boundary grouping in hierarchical sequence diagrams. All rules in this section apply whenever hierarchical_decomposition: true or explicit boundaries are configured.
Every boundary is rendered as a box block. External actors are declared before all box blocks; participants inside a boundary appear inside the corresponding box ... end block:
sequenceDiagram
%% Stereotypes: [ActorName]=actor | [BoundaryParticipant]=boundary, [ControlParticipant1]=control, [ControlParticipant2]=control, [EntityParticipant1]=entity
%% External participants (actors) — outside all boundaries
participant [ActorName] as "[Human-readable Actor Label]"
%% Boundary: [BoundaryName]
box "[BoundaryName]"
participant [BoundaryParticipant] as "[Label]"
participant [ControlParticipant1] as "[Label]"
participant [ControlParticipant2] as "[Label]"
participant [EntityParticipant1] as "[Label]"
end
%% Interactions
[ActorName]->>[BoundaryParticipant]: [Action]
...
Generation rules:
actor-type participants are emitted before any box blockbox "[BoundaryName]" ... end block — always quote the label%% Boundary: comment for readability%% Stereotypes: comment listing every participant's typeparticipant [Alias] as "[Label]" syntax — NEVER use @{ ... } JSON metadatabox must follow strict ordering: boundary first, then control, then entity (see Participant Ordering Within a Box)box blocks; decomposition to sub-boundaries is expressed through separate diagrams linked by decomposition referencesParticipants inside each box block must follow a strict ordering to satisfy EDPS boundary rules and produce readable diagrams:
| Order | Stereotype | Rationale |
|---|---|---|
| 1st | boundary | First recipient of actor messages; entry point to boundary |
| 2nd–Nth | control | Business logic components; eligible for further decomposition |
| Last | entity | Data / resource stores; passive, no first-message routing needed |
Example of correct ordering:
box "Payment Service Boundary"
participant Gateway as "Payment Gateway"
participant Processor as "Transaction Processor"
participant Validator as "Payment Validator"
participant Ledger as "Transaction Ledger"
end
If a boundary contains no boundary-type participant, emit a validation warning and list all control participants first, followed by entity participants.
Multiple non-overlapping boundaries are supported in a single sequence diagram. Each gets its own box block, declared in order of first interaction:
sequenceDiagram
%% Stereotypes: Customer=actor | Web=boundary, Order=control, Inventory=control, CustomerDB=entity | PayAPI=boundary, TxProcessor=control, Ledger=entity | FulfillAPI=boundary, Warehouse=control, Shipment=entity
participant Customer as "Customer"
%% Boundary: E-commerce Platform
box "E-commerce Platform Boundary"
participant Web as "Web Frontend"
participant Order as "Order Service"
participant Inventory as "Inventory Service"
participant CustomerDB as "Customer Database"
end
%% Boundary: Payment System
box "Payment System Boundary"
participant PayAPI as "Payment API"
participant TxProcessor as "Transaction Processor"
participant Ledger as "Transaction Ledger"
end
%% Boundary: Fulfillment Center
box "Fulfillment Center Boundary"
participant FulfillAPI as "Fulfillment API"
participant Warehouse as "Warehouse Manager"
participant Shipment as "Shipment Record"
end
Customer->>Web: Place Order
Web->>Order: Create Order
Order->>PayAPI: Process Payment
Order->>FulfillAPI: Schedule Delivery
Multi-boundary constraints:
box blocks follows the sequence of first message receipt by each boundaryBoundary names are derived automatically from context using the following priority order:
| Priority | Source | Example Output |
|---|---|---|
| 1 | Manual name in input configuration | "Payment Gateway" → Payment Gateway |
| 2 | Domain concept name + " Boundary" suffix | concept OrderManagement → Order Management Boundary |
| 3 | Dominant participant name + type suffix | primary control CreditChecker → Credit Check Service Boundary |
| 4 | Functional role inference from participant names | names contain inventory, stock → Inventory Management Boundary |
| 5 | Generic fallback with ordinal | System Boundary 1, System Boundary 2 |
Naming formatting rules:
" Boundary" suffix to system/component names; omit suffix for naturally scoped phrases that are already descriptive (e.g., E-commerce Platform)... if exceededBoundaries support optional color customization. Colors are applied via Mermaid's box color parameter:
box rgb(235, 245, 255) "E-commerce Platform Boundary"
participant Web as "Web Frontend"
...
end
Default color palette (applied round-robin when auto_color: true):
| Boundary Index | Color | RGB Value | Semantic Meaning |
|---|---|---|---|
| 1st boundary | Light blue | rgb(235, 245, 255) | Primary system |
| 2nd boundary | Light green | rgb(235, 255, 240) | Secondary system |
| 3rd boundary | Light amber | rgb(255, 250, 235) | Supporting system |
| 4th boundary | Light lavender | rgb(245, 235, 255) | Integration layer |
| 5th+ boundary | Light grey | rgb(245, 245, 245) | Additional systems |
Styling configuration:
{
"boundary_styling": {
"auto_color": true,
"manual_colors": {
"Payment System Boundary": "rgb(255, 243, 224)",
"Security Boundary": "rgb(255, 235, 235)"
}
}
}
When auto_color: false (default) and no manual_colors are provided, the box keyword is used without a color parameter.
When generate_boundary_comments: true is set (recommended), the skill inserts structured comments into the Mermaid output to improve readability and navigation:
sequenceDiagram
%% ─────────────────────────────────────────────────────
%% BOUNDARY SUMMARY
%% ─────────────────────────────────────────────────────
%% [B-1] E-commerce Platform Boundary
%% Participants: Web Frontend (boundary), Order Service (control),
%% Inventory Service (control), Customer Database (entity)
%% Decomposable: Order Service, Inventory Service
%% External actor: Customer
%%
%% [B-2] Payment System Boundary
%% Participants: Payment API (boundary), Transaction Processor (control),
%% Transaction Ledger (entity)
%% Decomposable: Transaction Processor
%% External actor: none (called from E-commerce Platform)
%% ─────────────────────────────────────────────────────
participant Customer as "Customer"
%% [B-1] E-commerce Platform Boundary
box "E-commerce Platform Boundary"
...
end
%% [B-2] Payment System Boundary
box "Payment System Boundary"
...
end
| Edge Case | Detection | Handling |
|---|---|---|
| Single participant boundary | Only one participant inside a box block | Emit a warning in metadata; still generate the box; suggest merging with a related boundary |
| External participants between boxes | Participants not assigned to any boundary | Declare outside all box blocks; include in external_participants metadata list |
No boundary-type participant in box | Box contains only control/entity participants | Emit validation warning; list controls first, entities last; add %% WARNING: No boundary-type entry point comment inside the box |
| Empty boundary | Boundary configured with zero participants | Skip generation; emit error empty-boundary-skipped in metadata |
| Duplicate participant across boundaries | Same participant ID appears in two boxes | Emit validation error duplicate-participant; use first boundary assignment; suggest renaming |
| More than 5 boundaries | boundary_count > 5 | Emit readability warning; continue generation; recommend splitting into multiple diagrams |
{
"box_syntax": {
"enabled": true,
"participant_ordering": "boundary-control-entity",
"generate_boundary_comments": true,
"boundary_naming": {
"strategy": "domain-concept-first",
"suffix": "Boundary",
"title_case": true
},
"boundary_styling": {
"auto_color": false,
"manual_colors": {}
},
"validation": {
"enforce_participant_ordering": true,
"warn_single_participant_boundary": true,
"error_on_empty_boundary": true,
"warn_no_boundary_type_entry_point": true,
"error_on_duplicate_participant": true,
"warn_exceeds_boundary_count": 5
}
}
}
After box syntax generation the skill emits a box_syntax_metadata block in collaboration-diagrams.json:
{
"box_syntax_metadata": {
"total_boundaries": 3,
"boundaries": [
{
"id": "B-1",
"name": "E-commerce Platform Boundary",
"color": null,
"participants": {
"boundary": ["Web"],
"control": ["Order", "Inventory"],
"entity": ["CustomerDB"]
},
"decomposable_participants": ["Order", "Inventory"],
"external_actors": ["Customer"],
"warnings": []
},
{
"id": "B-2",
"name": "Payment System Boundary",
"color": null,
"participants": {
"boundary": ["PayAPI"],
"control": ["TxProcessor"],
"entity": ["Ledger"]
},
"decomposable_participants": ["TxProcessor"],
"external_actors": [],
"warnings": []
}
],
"external_participants": [],
"validation_errors": [],
"validation_warnings": []
}
}
This section defines the complete set of boundary validation rules, the two execution modes (strict vs advisory), and the machine-readable validation report format emitted by the skill. Boundary validation runs as a pre-render check after participant classification and box syntax generation, and before final Mermaid output is written.
All hierarchical collaboration diagrams produced by this skill are validated against four EDPS boundary rules. Each rule can independently raise an error (hard violation) or a warning (advisory issue) depending on the active mode.
| Rule ID | Rule Name | Default Severity |
|---|---|---|
| VR-1 | Single External Interface | Error |
| VR-2 | Boundary-First Reception | Error |
| VR-3 | Control-Only Decomposition | Error |
| VR-4 | Cohesive Responsibility | Warning |
Requirement: Each boundary must have exactly one external actor sending messages directly into it. Multiple external actors communicating directly with internal boundary participants violates EDPS encapsulation principles.
Valid:
Customer (actor) ->> API (boundary) [inside Order Boundary]
Invalid:
Customer (actor) ->> API [inside Order Boundary] ✅
Admin (actor) ->> Service [inside Order Boundary] ❌ second actor enters boundary directly
Detection logic:
actor-type and outside the boundarycount(distinct external actors sending into boundary) > 1 → violationValidation output on violation:
{
"rule": "VR-1",
"rule_name": "single-external-interface",
"severity": "error",
"boundary": "Order Processing Boundary",
"actors_found": ["Customer", "Admin"],
"message": "Boundary 'Order Processing Boundary' is accessed by 2 external actors (Customer, Admin). Only one external actor may interact directly with a boundary.",
"suggestion": "Split into two separate boundaries — one per external actor — or introduce a shared entry-point gateway that aggregates actor messages before forwarding into a single boundary."
}
Requirement: Within any box boundary, the first message sent from an external actor must be received by a boundary-type participant. Actors must not bypass the boundary-type entry point and send directly to control or entity participants.
Valid:
Customer (actor) ->> Gateway (boundary) ->> OrderService (control)
Invalid:
Customer (actor) ->> OrderService (control) ❌ skips boundary-type entry point
Detection logic:
boundary → violationValidation output on violation:
{
"rule": "VR-2",
"rule_name": "boundary-first-reception",
"severity": "error",
"boundary": "Order Processing Boundary",
"actor": "Customer",
"received_by": "OrderService",
"received_by_type": "control",
"message": "Actor 'Customer' sends directly to 'OrderService' (type: control) inside boundary 'Order Processing Boundary'. The first recipient inside a boundary must be a boundary-type participant.",
"suggestion": "Add or designate a boundary-type participant (e.g., 'Order API' or 'Order Portal') as the single entry point. Route the actor message through that participant first."
}
Requirement: Only participants with type: control may be decomposed into sub-process diagrams. Attempting to decompose an actor, boundary, or entity participant is a structural violation.
Valid: