{"version":3,"sources":["../src/layout/elk-layouter.ts","../src/layout/size-calculator.ts","../src/layout/post-processing/boundary-event/collector.ts","../src/layout/post-processing/boundary-event/mover.ts","../src/utils/debug.ts","../src/layout/post-processing/boundary-event/edge-recalculator.ts","../src/layout/post-processing/boundary-event/index.ts","../src/layout/edge-routing/geometry-utils.ts","../src/types/bpmn-constants.ts","../src/utils/node-map-builder.ts","../src/layout/post-processing/artifact-positioner.ts","../src/layout/post-processing/group-positioner.ts","../src/layout/post-processing/lane-arranger.ts","../src/layout/constraint/constraint-solver.ts","../src/layout/post-processing/pool-arranger.ts","../src/layout/post-processing/compactor.ts","../src/layout/edge-routing/pathfinding-router.ts","../src/layout/edge-routing/edge-fixer.ts","../src/layout/edge-routing/gateway-endpoint-adjuster.ts","../src/layout/default-options.ts","../src/layout/preparation/elk-graph-preparer.ts","../src/layout/preparation/result-merger.ts","../src/transform/reference-resolver.ts","../src/transform/lane-resolver.ts","../src/transform/diagram-builder.ts","../src/transform/model-builder.ts","../src/generators/bpmn-xml-generator.ts","../src/converter.ts","../src/prompt-generator.ts"],"sourcesContent":["/**\n * ELK Layout Engine Wrapper\n * Orchestrates the BPMN layout pipeline using specialized handlers.\n *\n * Lightweight post-processing: Only repositions boundary event targets below main flow.\n * ELK handles all edge routing.\n */\n\nimport ELK from 'elkjs';\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph, ElkLayoutOptions } from '../types';\nimport type { LayoutedGraph } from '../types/elk-output';\nimport { SizeCalculator } from './size-calculator';\nimport { BoundaryEventHandler } from './post-processing/boundary-event';\nimport { ArtifactPositioner } from './post-processing/artifact-positioner';\nimport { GroupPositioner } from './post-processing/group-positioner';\nimport { LaneArranger } from './post-processing/lane-arranger';\nimport { PoolArranger } from './post-processing/pool-arranger';\nimport { Compactor } from './post-processing/compactor';\nimport { EdgeFixer } from './edge-routing';\nimport { ElkGraphPreparer } from './preparation/elk-graph-preparer';\nimport { ResultMerger } from './preparation/result-merger';\nimport { isDebugEnabled } from '../utils/debug';\n\nexport interface ElkLayouterOptions {\n  elkOptions?: ElkLayoutOptions;\n  /** Enable layout compaction to reduce whitespace (default: true) */\n  enableCompaction?: boolean;\n}\n\nexport class ElkLayouter {\n  private elk: InstanceType<typeof ELK>;\n  private userOptions: ElkLayoutOptions;\n  private enableCompaction: boolean;\n  private sizeCalculator: SizeCalculator;\n  private boundaryEventHandler: BoundaryEventHandler;\n  private artifactPositioner: ArtifactPositioner;\n  private groupPositioner: GroupPositioner;\n  private laneArranger: LaneArranger;\n  private poolArranger: PoolArranger;\n  private compactor: Compactor;\n  private edgeFixer: EdgeFixer;\n  private graphPreparer: ElkGraphPreparer;\n  private resultMerger: ResultMerger;\n\n  constructor(options?: ElkLayouterOptions) {\n    this.elk = new ELK();\n    this.userOptions = options?.elkOptions ?? {};\n    this.enableCompaction = options?.enableCompaction ?? true;\n    this.sizeCalculator = new SizeCalculator();\n    this.boundaryEventHandler = new BoundaryEventHandler();\n    this.artifactPositioner = new ArtifactPositioner();\n    this.groupPositioner = new GroupPositioner();\n    this.laneArranger = new LaneArranger();\n    this.poolArranger = new PoolArranger();\n    this.compactor = new Compactor();\n    this.edgeFixer = new EdgeFixer();\n    this.graphPreparer = new ElkGraphPreparer();\n    this.resultMerger = new ResultMerger();\n  }\n\n  /**\n   * Run ELK layout on the graph\n   */\n  async layout(graph: ElkBpmnGraph): Promise<LayoutedGraph> {\n    // Deep clone to avoid mutating the original\n    const graphCopy = JSON.parse(JSON.stringify(graph)) as ElkBpmnGraph;\n\n    // Apply default sizes to all nodes\n    const sizedGraph = this.sizeCalculator.applyDefaultSizes(graphCopy);\n\n    // Collect boundary event info - used to set ELK constraints for target nodes\n    const boundaryEventInfo = this.boundaryEventHandler.collectInfo(sizedGraph);\n\n    // Collect boundary event target IDs for ELK constraint assignment\n    const boundaryEventTargetIds = this.graphPreparer.collectBoundaryEventTargetIds(boundaryEventInfo);\n\n    // Collect artifact association info for post-processing\n    const artifactInfo = this.artifactPositioner.collectInfo(sizedGraph);\n\n    // Collect Group info for post-processing (Groups will be repositioned after layout)\n    const groupInfo = this.groupPositioner.collectInfo(sizedGraph);\n\n    // Prepare graph for ELK (convert to ELK format)\n    // Pass boundaryEventTargetIds so ELK can apply position constraints\n    const elkGraph = this.graphPreparer.prepare(sizedGraph, this.userOptions, boundaryEventTargetIds);\n\n    // Run ELK layout\n    const layoutedElkGraph = await this.elk.layout(elkGraph);\n\n    // Lightweight post-processing: Move boundary event targets below their attached tasks\n    // This is BPMN-specific positioning that ELK cannot handle via constraints\n    const movedNodes = this.boundaryEventHandler.identifyNodesToMove(\n      layoutedElkGraph, boundaryEventInfo, sizedGraph, isDebugEnabled()\n    );\n\n    if (movedNodes.size > 0) {\n      // Move nodes\n      this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, movedNodes);\n      // Recalculate edges for moved nodes\n      this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo);\n    }\n\n    // Reposition artifacts (data objects, data stores, annotations) to be near their associated tasks\n    this.artifactPositioner.reposition(layoutedElkGraph, artifactInfo);\n\n    // Rearrange lanes to stack vertically within pools (ELK's partitioning doesn't do this correctly)\n    this.laneArranger.rearrange(layoutedElkGraph, sizedGraph);\n\n    // Rearrange pools to stack vertically within collaborations\n    this.poolArranger.rearrange(layoutedElkGraph, sizedGraph);\n\n    // Reposition Groups to surround their grouped elements\n    this.groupPositioner.reposition(layoutedElkGraph, groupInfo, sizedGraph);\n\n    // Recalculate artifact edges with obstacle avoidance\n    this.artifactPositioner.recalculateWithObstacleAvoidance(layoutedElkGraph, artifactInfo);\n\n    // Apply layout compaction to reduce whitespace (if enabled)\n    if (this.enableCompaction) {\n      this.compactor.compact(layoutedElkGraph);\n    }\n\n    // Pull content up to the top so canvas doesn't lead with empty space\n    // (ELK sometimes reserves vertical bands that post-processing leaves empty)\n    this.normalizeOrigin(layoutedElkGraph);\n\n    // Update container bounds to include all moved children\n    this.updateContainerBounds(layoutedElkGraph);\n\n    // Final edge correction pass — must run AFTER updateContainerBounds so\n    // edge endpoints snap to the post-shrink container borders. Otherwise\n    // edges anchored to a wider pre-shrink subprocess float past its new edge.\n    this.edgeFixer.fix(layoutedElkGraph);\n\n    // Merge layout results back with BPMN metadata\n    return this.resultMerger.merge(sizedGraph, layoutedElkGraph);\n  }\n\n  // Shift each top-level container so its leftmost/topmost node sits near\n  // the origin: ELK reserves bands for nodes that post-processing later\n  // relocates (e.g. boundary-event targets), and we want the canvas to lead\n  // with content, not empty space.\n  private normalizeOrigin(graph: ElkNode): void {\n    if (!graph.children) return;\n    const margin = 12;\n\n    for (const top of graph.children) {\n      // Find min x/y across direct children of this top-level container.\n      // We only care about positions inside `top`, since `top` itself sits\n      // at (0,0) in the root canvas after ELK.\n      if (!top.children || top.children.length === 0) continue;\n\n      // Boundary events are repositioned onto their parent task by the\n      // diagram builder, so their ELK-assigned y is phantom and must be\n      // ignored when finding the topmost visible content.\n      const isPhantom = (child: ElkNode): boolean => {\n        const bpmn = (child as ElkNode & { bpmn?: { type?: string } }).bpmn;\n        return bpmn?.type === 'boundaryEvent';\n      };\n\n      let minX = Infinity;\n      let minY = Infinity;\n      for (const child of top.children) {\n        if (isPhantom(child)) continue;\n        const x = child.x ?? 0;\n        const y = child.y ?? 0;\n        if (x < minX) minX = x;\n        if (y < minY) minY = y;\n      }\n      if (!isFinite(minX) || !isFinite(minY)) continue;\n\n      const shiftX = margin - minX;\n      const shiftY = margin - minY;\n      if (shiftX === 0 && shiftY === 0) continue;\n\n      for (const child of top.children) {\n        child.x = (child.x ?? 0) + shiftX;\n        child.y = (child.y ?? 0) + shiftY;\n      }\n      // Shift edge waypoints attached at this container level too.\n      if (top.edges) {\n        for (const edge of top.edges) {\n          if (!edge.sections) continue;\n          for (const section of edge.sections) {\n            section.startPoint.x += shiftX;\n            section.startPoint.y += shiftY;\n            section.endPoint.x += shiftX;\n            section.endPoint.y += shiftY;\n            if (section.bendPoints) {\n              for (const bp of section.bendPoints) {\n                bp.x += shiftX;\n                bp.y += shiftY;\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  private updateContainerBounds(graph: ElkNode): void {\n    type Bpmned = ElkNode & { bpmn?: { type?: string } };\n\n    const isLane = (n: Bpmned): boolean => n.bpmn?.type === 'lane';\n    const hasLaneChildren = (n: ElkNode): boolean =>\n      !!n.children?.some(c => isLane(c as Bpmned));\n\n    const fit = (node: ElkNode): void => {\n      if (!node.children || node.children.length === 0) return;\n\n      for (const child of node.children) fit(child);\n\n      // Authoritative sizing: don't touch lanes or pools-with-lanes.\n      if (isLane(node as Bpmned)) return;\n      if (hasLaneChildren(node)) return;\n\n      const padding = 12;\n      let requiredWidth = 0;\n      let requiredHeight = 0;\n      for (const child of node.children) {\n        requiredWidth = Math.max(requiredWidth, (child.x ?? 0) + (child.width ?? 0) + padding);\n        requiredHeight = Math.max(requiredHeight, (child.y ?? 0) + (child.height ?? 0) + padding);\n      }\n      node.width = requiredWidth;\n      node.height = requiredHeight;\n    };\n\n    fit(graph);\n  }\n}\n","/**\n * Size Calculator\n * Handles calculating and applying default sizes to BPMN elements.\n * Also estimates label widths based on text content.\n */\n\nimport type { ElkBpmnGraph } from '../types';\nimport type { NodeWithBpmn } from '../types/internal';\n\n/**\n * Default size dimensions for various BPMN element types\n */\nexport interface ElementSize {\n  width: number;\n  height: number;\n}\n\n/**\n * Size Calculator for BPMN elements\n * Applies default sizes based on element type and properties\n */\nexport class SizeCalculator {\n  /**\n   * Apply default sizes to all nodes in the graph\n   */\n  applyDefaultSizes(graph: ElkBpmnGraph): ElkBpmnGraph {\n    if (graph.children) {\n      graph.children = graph.children.map((child) => {\n        return this.applyDefaultSizesRecursive(child);\n      });\n    }\n    return graph;\n  }\n\n  /**\n   * Recursively apply default sizes to a node and its children\n   */\n  private applyDefaultSizesRecursive<T extends object>(node: T): T {\n    const result = { ...node };\n\n    // Apply sizes if this is a node with bpmn type\n    if ('bpmn' in result && 'id' in result) {\n      const bpmn = (result as unknown as NodeWithBpmn).bpmn;\n      const nodeResult = result as { width?: number; height?: number };\n\n      // Get default size based on type\n      const defaultSize = this.getDefaultSizeForType(bpmn.type, bpmn.name, bpmn.isExpanded);\n\n      if (nodeResult.width === undefined) {\n        nodeResult.width = defaultSize.width;\n      }\n      if (nodeResult.height === undefined) {\n        nodeResult.height = defaultSize.height;\n      }\n    }\n\n    // Process children recursively\n    if ('children' in result && Array.isArray((result as { children: unknown[] }).children)) {\n      (result as { children: unknown[] }).children = (result as { children: object[] }).children.map(\n        (child) => this.applyDefaultSizesRecursive(child)\n      );\n    }\n\n    // Process boundary events\n    if ('boundaryEvents' in result && Array.isArray((result as { boundaryEvents: unknown[] }).boundaryEvents)) {\n      const boundaryEvents = (result as { boundaryEvents: object[] }).boundaryEvents;\n      (result as { boundaryEvents: unknown[] }).boundaryEvents = boundaryEvents.map(\n        (be) => this.applyDefaultSizesRecursive(be)\n      );\n\n      // Ensure host node is wide enough to accommodate all boundary events with spacing\n      // Each boundary event is 36px wide, and we need at least 20px spacing between them\n      const beCount = boundaryEvents.length;\n      if (beCount > 1) {\n        const beWidth = 36;\n        const beSpacing = 20;\n        // Need: margin + (beWidth + spacing) * beCount - spacing + margin\n        // Simplified: (beCount * (beWidth + beSpacing)) + margin\n        const minWidth = beCount * (beWidth + beSpacing) + beSpacing;\n        const nodeResult = result as { width?: number };\n        if (nodeResult.width !== undefined && nodeResult.width < minWidth) {\n          nodeResult.width = minWidth;\n        }\n      }\n    }\n\n    // Process artifacts\n    if ('artifacts' in result && Array.isArray((result as { artifacts: unknown[] }).artifacts)) {\n      (result as { artifacts: unknown[] }).artifacts = (result as { artifacts: object[] }).artifacts.map(\n        (artifact) => this.applyDefaultSizesRecursive(artifact)\n      );\n    }\n\n    return result;\n  }\n\n  /**\n   * Estimate label width based on text content\n   * Uses approximate character width of 14px for CJK and 7px for ASCII\n   */\n  estimateLabelWidth(text?: string): number {\n    if (!text) return 50;\n\n    let width = 0;\n    for (const char of text) {\n      // CJK characters are wider\n      if (char.charCodeAt(0) > 255) {\n        width += 14; // ~14px for CJK characters\n      } else {\n        width += 7; // ~7px for ASCII characters\n      }\n    }\n\n    return Math.max(30, Math.min(width, 200)); // Clamp between 30 and 200\n  }\n\n  /**\n   * Get default size for a BPMN element type\n   */\n  getDefaultSizeForType(type: string, name?: string, isExpanded?: boolean): ElementSize {\n    // Expanded subprocesses\n    if (isExpanded === true) {\n      return { width: 300, height: 200 };\n    }\n\n    // Events\n    if (type.includes('Event')) {\n      return { width: 36, height: 36 };\n    }\n\n    // Gateways\n    if (type.includes('Gateway')) {\n      return { width: 50, height: 50 };\n    }\n\n    // Tasks and activities\n    if (type.includes('Task') || type === 'task' || type === 'callActivity') {\n      const nameLen = name?.length ?? 0;\n      if (nameLen > 12) return { width: 150, height: 80 };\n      if (nameLen > 8) return { width: 120, height: 80 };\n      return { width: 100, height: 80 };\n    }\n\n    // Collapsed subprocesses\n    if (type === 'subProcess' || type === 'transaction' || type === 'adHocSubProcess' || type === 'eventSubProcess') {\n      return { width: 100, height: 80 };\n    }\n\n    // Data objects\n    if (type === 'dataObject' || type === 'dataObjectReference' || type === 'dataInput' || type === 'dataOutput') {\n      return { width: 36, height: 50 };\n    }\n\n    // Data store\n    if (type === 'dataStoreReference') {\n      return { width: 50, height: 50 };\n    }\n\n    // Text annotation\n    if (type === 'textAnnotation') {\n      return { width: 100, height: 30 };\n    }\n\n    // Participant/Pool - ELK and the pool/lane arrangers resize non-empty\n    // pools to fit content; this default mostly applies to empty (black box)\n    // pools, which should stay compact.\n    if (type === 'participant') {\n      return { width: 680, height: 80 };\n    }\n\n    // Lane - let ELK calculate\n    if (type === 'lane') {\n      return { width: 680, height: 150 };\n    }\n\n    // Default\n    return { width: 100, height: 80 };\n  }\n}\n\n/**\n * Standalone function to apply default sizes to a graph\n * Convenience wrapper around SizeCalculator\n */\nexport function applyDefaultSizes(graph: ElkBpmnGraph): ElkBpmnGraph {\n  const calculator = new SizeCalculator();\n  return calculator.applyDefaultSizes(graph);\n}\n\n/**\n * Standalone function to estimate label width\n * Convenience wrapper around SizeCalculator\n */\nexport function estimateLabelWidth(text?: string): number {\n  const calculator = new SizeCalculator();\n  return calculator.estimateLabelWidth(text);\n}\n\n/**\n * Standalone function to get default size for a type\n * Convenience wrapper around SizeCalculator\n */\nexport function getDefaultSizeForType(type: string, name?: string, isExpanded?: boolean): ElementSize {\n  const calculator = new SizeCalculator();\n  return calculator.getDefaultSizeForType(type, name, isExpanded);\n}\n","/**\n * Boundary Event Collector\n * Collects boundary event information from the BPMN graph for post-processing.\n */\n\nimport type { ElkBpmnGraph } from '../../../types';\nimport type { NodeWithBpmn, BoundaryEventInfo } from '../../../types/internal';\n\n/**\n * Collect boundary event information for post-processing.\n * Returns a map of boundary event ID -> { attachedToRef, targets, boundaryIndex, totalBoundaries }\n *\n * @param graph - The ELK-BPMN input graph\n * @returns Map of boundary event ID to BoundaryEventInfo\n */\nexport function collectBoundaryEventInfo(\n  graph: ElkBpmnGraph\n): Map<string, BoundaryEventInfo> {\n  const info = new Map<string, BoundaryEventInfo>();\n  const edgeMap = new Map<string, string[]>(); // source -> targets\n\n  // First pass: collect all edges by source\n  const collectEdges = (node: NodeWithBpmn) => {\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const source = edge.sources?.[0];\n        const target = edge.targets?.[0];\n        if (!source || !target) continue;\n        if (!edgeMap.has(source)) {\n          edgeMap.set(source, []);\n        }\n        edgeMap.get(source)!.push(target);\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        collectEdges(child as NodeWithBpmn);\n      }\n    }\n  };\n\n  // Second pass: collect boundary events and their targets\n  const collectBoundaryEvents = (node: NodeWithBpmn) => {\n    if (node.boundaryEvents) {\n      const totalBoundaries = node.boundaryEvents.length;\n      node.boundaryEvents.forEach((be, index) => {\n        const targets = edgeMap.get(be.id) || [];\n        info.set(be.id, {\n          attachedToRef: be.attachedToRef,\n          targets,\n          boundaryIndex: index,\n          totalBoundaries,\n        });\n      });\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        collectBoundaryEvents(child as NodeWithBpmn);\n      }\n    }\n  };\n\n  for (const child of graph.children ?? []) {\n    collectEdges(child as NodeWithBpmn);\n    collectBoundaryEvents(child as NodeWithBpmn);\n  }\n\n  return info;\n}\n","/**\n * Boundary Event Mover\n * Handles identification and movement of boundary event target nodes.\n */\n\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../../types';\nimport type { NodeWithBpmn, BoundaryEventInfo, NodeMoveInfo } from '../../../types/internal';\n\n/**\n * Branch destination type enum for prioritization\n */\nexport enum BranchDestType {\n  MERGE_TO_MAIN = 1, // Branches that merge back to main flow (highest priority - closest to main flow)\n  TO_END_EVENT = 2, // Branches that end at end events (medium priority)\n  DEAD_END = 3, // Branches with no outgoing edges (lowest priority - furthest from main flow)\n}\n\n/**\n * Placed branch info for collision detection\n */\ninterface PlacedBranch {\n  minX: number;\n  maxX: number;\n  minY: number;\n  maxY: number;\n  destType: BranchDestType;\n}\n\n/**\n * Build maps for node lookups and edge relationships\n */\nexport function buildNodeAndEdgeMaps(\n  graph: ElkNode,\n  sizedGraph?: ElkBpmnGraph\n): {\n  nodeMap: Map<string, ElkNode>;\n  nodeTypeMap: Map<string, string>;\n  edgeMap: Map<string, string[]>;\n  reverseEdgeMap: Map<string, string[]>;\n} {\n  const nodeMap = new Map<string, ElkNode>();\n  const nodeTypeMap = new Map<string, string>();\n  const edgeMap = new Map<string, string[]>();\n  const reverseEdgeMap = new Map<string, string[]>();\n\n  // Helper to collect node types from sizedGraph\n  const collectNodeTypes = (node: NodeWithBpmn) => {\n    if (node.bpmn?.type) {\n      nodeTypeMap.set(node.id, node.bpmn.type);\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        collectNodeTypes(child as NodeWithBpmn);\n      }\n    }\n    if (node.boundaryEvents) {\n      for (const be of node.boundaryEvents) {\n        if ((be as NodeWithBpmn).bpmn?.type) {\n          nodeTypeMap.set(be.id, (be as NodeWithBpmn).bpmn!.type!);\n        }\n      }\n    }\n  };\n\n  // Collect node types from sizedGraph if provided\n  if (sizedGraph) {\n    for (const child of sizedGraph.children ?? []) {\n      collectNodeTypes(child as NodeWithBpmn);\n    }\n  }\n\n  const buildMaps = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const source = edge.sources?.[0];\n        const target = edge.targets?.[0];\n        if (source && target) {\n          if (!edgeMap.has(source)) {\n            edgeMap.set(source, []);\n          }\n          edgeMap.get(source)!.push(target);\n\n          if (!reverseEdgeMap.has(target)) {\n            reverseEdgeMap.set(target, []);\n          }\n          reverseEdgeMap.get(target)!.push(source);\n        }\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        buildMaps(child);\n      }\n    }\n  };\n  buildMaps(graph);\n\n  return { nodeMap, nodeTypeMap, edgeMap, reverseEdgeMap };\n}\n\n/**\n * Identify nodes that need to be moved below their attached boundary event parent\n * Returns a map of node ID -> new position info\n */\nexport function identifyNodesToMove(\n  graph: ElkNode,\n  boundaryEventInfo: Map<string, BoundaryEventInfo>,\n  sizedGraph: ElkBpmnGraph,\n  debug = false\n): Map<string, NodeMoveInfo> {\n  const movedNodes = new Map<string, NodeMoveInfo>();\n  const { nodeMap, nodeTypeMap, edgeMap, reverseEdgeMap } = buildNodeAndEdgeMaps(\n    graph,\n    sizedGraph\n  );\n\n  // Collect all boundary event target IDs (direct targets of boundary events)\n  const boundaryEventTargetIds = new Set<string>();\n  for (const [_beId, info] of boundaryEventInfo) {\n    for (const targetId of info.targets) {\n      boundaryEventTargetIds.add(targetId);\n    }\n  }\n\n  // Helper to check if a node is a merge point (has incoming edges from non-boundary-event sources)\n  const isMergePoint = (nodeId: string): boolean => {\n    const incomingSources = reverseEdgeMap.get(nodeId) || [];\n    if (incomingSources.length <= 1) return false;\n\n    for (const sourceId of incomingSources) {\n      if (!boundaryEventTargetIds.has(sourceId) && !movedNodes.has(sourceId)) {\n        if (debug) {\n          console.log(\n            `[BPMN] isMergePoint(${nodeId}): true - source ${sourceId} is from main flow`\n          );\n        }\n        return true;\n      }\n    }\n    if (debug) {\n      console.log(\n        `[BPMN] isMergePoint(${nodeId}): false - all ${incomingSources.length} sources are boundary event branches`\n      );\n    }\n    return false;\n  };\n\n  // Helper to trace a branch and determine its destination type\n  const getBranchDestinationType = (startNodeId: string): BranchDestType => {\n    const visited = new Set<string>();\n    const queue = [startNodeId];\n\n    while (queue.length > 0) {\n      const nodeId = queue.shift()!;\n      if (visited.has(nodeId)) continue;\n      visited.add(nodeId);\n\n      const node = nodeMap.get(nodeId);\n      if (!node) continue;\n\n      if (isMergePoint(nodeId)) {\n        return BranchDestType.MERGE_TO_MAIN;\n      }\n\n      const outgoingTargets = edgeMap.get(nodeId) || [];\n\n      if (outgoingTargets.length === 0) {\n        const nodeType = nodeTypeMap.get(nodeId);\n        if (nodeType === 'endEvent') {\n          return BranchDestType.TO_END_EVENT;\n        }\n        return BranchDestType.DEAD_END;\n      }\n\n      for (const targetId of outgoingTargets) {\n        if (!visited.has(targetId)) {\n          if (isMergePoint(targetId)) {\n            return BranchDestType.MERGE_TO_MAIN;\n          }\n          queue.push(targetId);\n        }\n      }\n    }\n\n    return BranchDestType.DEAD_END;\n  };\n\n  // Collect all boundary events with targets\n  const boundaryEventsWithTargets: Array<{\n    beId: string;\n    info: BoundaryEventInfo;\n    attachedNode: ElkNode;\n    beX: number;\n    attachedRight: number;\n    destType: BranchDestType;\n  }> = [];\n\n  for (const [beId, info] of boundaryEventInfo) {\n    if (info.targets.length === 0) continue;\n    const attachedNode = nodeMap.get(info.attachedToRef);\n    if (\n      !attachedNode ||\n      attachedNode.y === undefined ||\n      attachedNode.height === undefined\n    )\n      continue;\n\n    const attachedX = attachedNode.x ?? 0;\n    const attachedWidth = attachedNode.width ?? 100;\n    const attachedRight = attachedX + attachedWidth;\n    const spacing = attachedWidth / (info.totalBoundaries + 1);\n    const beX = attachedX + spacing * (info.boundaryIndex + 1);\n\n    const destType =\n      info.targets.length > 0\n        ? getBranchDestinationType(info.targets[0])\n        : BranchDestType.DEAD_END;\n\n    boundaryEventsWithTargets.push({\n      beId,\n      info,\n      attachedNode,\n      beX,\n      attachedRight,\n      destType,\n    });\n\n    if (debug) {\n      console.log(\n        `[BPMN] Branch ${beId} -> ${info.targets[0]}: destType=${BranchDestType[destType]}`\n      );\n    }\n  }\n\n  // Sort boundary events by destination type, then by X position\n  boundaryEventsWithTargets.sort((a, b) => {\n    if (a.destType !== b.destType) {\n      return a.destType - b.destType;\n    }\n    const xDiff = a.beX - b.beX;\n    if (Math.abs(xDiff) > 1) return xDiff;\n    return a.info.boundaryIndex - b.info.boundaryIndex;\n  });\n\n  // Find the global bottom Y of all attached nodes\n  let mainFlowBottom = 0;\n  for (const be of boundaryEventsWithTargets) {\n    const attachedY = be.attachedNode.y ?? 0;\n    const attachedHeight = be.attachedNode.height ?? 80;\n    const attachedBottom = attachedY + attachedHeight;\n    mainFlowBottom = Math.max(mainFlowBottom, attachedBottom);\n  }\n\n  // Layout constants\n  const minGap = 35;\n  const mergeToMainBaseY = mainFlowBottom + minGap + 50;\n  const toEndEventBaseY = mergeToMainBaseY + 80;\n  const deadEndBaseY = toEndEventBaseY + 100;\n  const horizontalGap = 50;\n\n  // Track placed branches\n  const placedBranches: PlacedBranch[] = [];\n\n  // Helper to calculate branch bounds\n  const calculateBranchBounds = (\n    targetId: string,\n    newX: number\n  ): { minX: number; maxX: number; height: number } => {\n    const targetNode = nodeMap.get(targetId);\n    const targetWidth = targetNode?.width ?? 100;\n    const targetHeight = targetNode?.height ?? 80;\n\n    let maxX = newX + targetWidth;\n    let totalHeight = targetHeight;\n\n    const visited = new Set<string>();\n    const queue = [targetId];\n    let currentMaxX = newX + targetWidth;\n\n    while (queue.length > 0) {\n      const nodeId = queue.shift()!;\n      if (visited.has(nodeId)) continue;\n      visited.add(nodeId);\n\n      const downstreamTargets = edgeMap.get(nodeId) || [];\n      for (const downId of downstreamTargets) {\n        if (isMergePoint(downId)) continue;\n\n        const downNode = nodeMap.get(downId);\n        if (downNode && !visited.has(downId)) {\n          const downWidth = downNode.width ?? 36;\n          currentMaxX += 20 + downWidth;\n          maxX = Math.max(maxX, currentMaxX);\n          totalHeight = Math.max(totalHeight, downNode.height ?? 36);\n          queue.push(downId);\n        }\n      }\n    }\n\n    return { minX: newX, maxX, height: totalHeight };\n  };\n\n  // Helper to check if X ranges overlap\n  const xRangesOverlap = (\n    minX1: number,\n    maxX1: number,\n    minX2: number,\n    maxX2: number\n  ): boolean => {\n    return !(maxX1 + horizontalGap < minX2 || maxX2 + horizontalGap < minX1);\n  };\n\n  // Helper to get base Y for each destination type\n  const getLayerBaseY = (destType: BranchDestType): number => {\n    switch (destType) {\n      case BranchDestType.MERGE_TO_MAIN:\n        return mergeToMainBaseY;\n      case BranchDestType.TO_END_EVENT:\n        return toEndEventBaseY;\n      case BranchDestType.DEAD_END:\n        return deadEndBaseY;\n      default:\n        return deadEndBaseY;\n    }\n  };\n\n  // Helper to find appropriate Y position for a new branch\n  const findYPosition = (\n    branchMinX: number,\n    branchMaxX: number,\n    branchHeight: number,\n    destType: BranchDestType\n  ): number => {\n    const layerBaseY = getLayerBaseY(destType);\n    let candidateY = layerBaseY;\n\n    const overlappingBranches = placedBranches.filter((b) =>\n      xRangesOverlap(branchMinX, branchMaxX, b.minX, b.maxX)\n    );\n\n    if (overlappingBranches.length === 0) {\n      return candidateY;\n    }\n\n    for (const branch of overlappingBranches) {\n      const requiredY = branch.maxY + minGap + 20;\n      candidateY = Math.max(candidateY, requiredY);\n    }\n\n    return candidateY;\n  };\n\n  // Process all boundary events in sorted order\n  for (const beEntry of boundaryEventsWithTargets) {\n    const { info, beX, attachedRight, destType } = beEntry;\n\n    if (debug) {\n      console.log(\n        `[BPMN] Processing boundary event at X=${beX} for ${info.attachedToRef}, destType=${BranchDestType[destType]}`\n      );\n    }\n\n    for (const targetId of info.targets) {\n      const targetNode = nodeMap.get(targetId);\n      if (!targetNode || targetNode.y === undefined) continue;\n\n      const targetWidth = targetNode.width ?? 100;\n      const targetHeight = targetNode.height ?? 80;\n\n      // Calculate new X position based on destination type\n      let newX: number;\n      if (destType === BranchDestType.MERGE_TO_MAIN) {\n        newX = attachedRight + 30;\n      } else if (destType === BranchDestType.TO_END_EVENT) {\n        newX = beX + 20;\n      } else {\n        newX = beX;\n      }\n\n      // Calculate branch bounds\n      const branchBounds = calculateBranchBounds(targetId, newX);\n\n      // Find appropriate Y position\n      const newY = findYPosition(\n        branchBounds.minX,\n        branchBounds.maxX,\n        branchBounds.height,\n        destType\n      );\n      const offset = newY - (targetNode.y ?? 0);\n      movedNodes.set(targetId, { newY, offset, newX });\n\n      if (debug) {\n        console.log(\n          `[BPMN] Moving ${targetId}: (${targetNode.x},${targetNode.y}) -> (${newX},${newY}), destType=${BranchDestType[destType]}`\n        );\n      }\n\n      // Propagate movement to downstream nodes\n      propagateMovement(\n        targetId,\n        newY,\n        nodeMap,\n        edgeMap,\n        movedNodes,\n        newX,\n        isMergePoint,\n        debug\n      );\n\n      // Register this branch\n      placedBranches.push({\n        minX: branchBounds.minX,\n        maxX: branchBounds.maxX,\n        minY: newY,\n        maxY: newY + branchBounds.height,\n        destType,\n      });\n    }\n  }\n\n  // Align merge-point end events with their main-flow predecessor.\n  // ELK can place a convergence end event (one that has both a main-flow\n  // incoming and a boundary branch incoming) far from the main flow band\n  // because it averages incoming-edge Y. Snap it back so the main flow\n  // doesn't curve up/down to reach the end event.\n  for (const [nodeId, node] of nodeMap) {\n    if (movedNodes.has(nodeId)) continue;\n    if (nodeTypeMap.get(nodeId) !== 'endEvent') continue;\n    const sources = reverseEdgeMap.get(nodeId) || [];\n    if (sources.length <= 1) continue;\n\n    let mainFlowSourceY: number | undefined;\n    let mainFlowSourceHeight = 80;\n    for (const sourceId of sources) {\n      if (boundaryEventTargetIds.has(sourceId) || movedNodes.has(sourceId)) continue;\n      if (sourceId.startsWith('boundary_')) continue;\n      const sourceNode = nodeMap.get(sourceId);\n      if (!sourceNode || sourceNode.y === undefined) continue;\n      mainFlowSourceY = sourceNode.y;\n      mainFlowSourceHeight = sourceNode.height ?? 80;\n      break;\n    }\n    if (mainFlowSourceY === undefined) continue;\n\n    const currentY = node.y ?? 0;\n    const currentHeight = node.height ?? 36;\n    const alignedY = mainFlowSourceY + (mainFlowSourceHeight - currentHeight) / 2;\n    if (Math.abs(currentY - alignedY) < 10) continue;\n\n    movedNodes.set(nodeId, {\n      newY: alignedY,\n      offset: alignedY - currentY,\n      newX: undefined,\n    });\n    if (debug) {\n      console.log(\n        `[BPMN] Aligning merge-point end event ${nodeId}: y ${currentY} -> ${alignedY} (main source y=${mainFlowSourceY})`\n      );\n    }\n  }\n\n  return movedNodes;\n}\n\n/**\n * Propagate movement to downstream nodes\n */\nexport function propagateMovement(\n  sourceId: string,\n  sourceNewY: number,\n  nodeMap: Map<string, ElkNode>,\n  edgeMap: Map<string, string[]>,\n  movedNodes: Map<string, NodeMoveInfo>,\n  sourceNewX?: number,\n  isMergePoint?: (nodeId: string) => boolean,\n  debug = false\n): void {\n  const sourceNode = nodeMap.get(sourceId);\n  const sourceWidth = sourceNode?.width ?? 100;\n  const sourceHeight = sourceNode?.height ?? 80;\n\n  const targets = edgeMap.get(sourceId) || [];\n  for (const targetId of targets) {\n    if (movedNodes.has(targetId)) {\n      const existingMove = movedNodes.get(targetId)!;\n      const currentSourceRight = (sourceNewX ?? 0) + sourceWidth + 20;\n\n      if (\n        existingMove.newX !== undefined &&\n        currentSourceRight > existingMove.newX\n      ) {\n        existingMove.newX = currentSourceRight;\n        if (debug) {\n          console.log(\n            `[BPMN] propagateMovement: updating ${targetId} X to ${currentSourceRight} (source is further right)`\n          );\n        }\n      } else if (debug) {\n        console.log(\n          `[BPMN] propagateMovement: skipping ${targetId} - already moved`\n        );\n      }\n      continue;\n    }\n\n    if (isMergePoint && isMergePoint(targetId)) {\n      if (debug) {\n        console.log(\n          `[BPMN] propagateMovement: skipping ${targetId} - is merge point`\n        );\n      }\n      continue;\n    }\n\n    const targetNode = nodeMap.get(targetId);\n    if (!targetNode || targetNode.y === undefined) continue;\n\n    const targetHeight = targetNode.height ?? 36;\n    const newY = sourceNewY + (sourceHeight - targetHeight) / 2;\n    const offset = newY - (targetNode.y ?? 0);\n\n    let newX: number | undefined;\n    if (sourceNewX !== undefined) {\n      newX = sourceNewX + sourceWidth + 20;\n    }\n\n    movedNodes.set(targetId, { newY, offset, newX });\n\n    if (debug) {\n      console.log(\n        `[BPMN] propagateMovement: moving ${targetId} to y=${newY}, newX=${newX}`\n      );\n    }\n\n    propagateMovement(\n      targetId,\n      newY,\n      nodeMap,\n      edgeMap,\n      movedNodes,\n      newX,\n      isMergePoint,\n      debug\n    );\n  }\n}\n\n/**\n * Reposition converging gateways based on their incoming edges.\n */\nexport function repositionConvergingGateways(\n  graph: ElkNode,\n  movedNodes: Map<string, NodeMoveInfo>,\n  boundaryEventInfo: Map<string, BoundaryEventInfo>,\n  debug = false\n): Map<string, NodeMoveInfo> {\n  const gatewayMoves = new Map<string, NodeMoveInfo>();\n\n  const nodeMap = new Map<string, ElkNode>();\n  const reverseEdgeMap = new Map<string, string[]>();\n\n  const buildMaps = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const source = edge.sources?.[0];\n        const target = edge.targets?.[0];\n        if (source && target) {\n          if (!reverseEdgeMap.has(target)) {\n            reverseEdgeMap.set(target, []);\n          }\n          reverseEdgeMap.get(target)!.push(source);\n        }\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        buildMaps(child);\n      }\n    }\n  };\n  buildMaps(graph);\n\n  // Collect boundary event target IDs\n  const boundaryEventTargetIds = new Set<string>();\n  for (const [_beId, info] of boundaryEventInfo) {\n    for (const targetId of info.targets) {\n      boundaryEventTargetIds.add(targetId);\n    }\n  }\n\n  // Find converging gateways\n  for (const [nodeId, node] of nodeMap) {\n    const incomingSources = reverseEdgeMap.get(nodeId) || [];\n    if (incomingSources.length <= 1) continue;\n\n    let hasMainFlowInput = false;\n    let hasBoundaryBranchInput = false;\n\n    for (const sourceId of incomingSources) {\n      if (boundaryEventTargetIds.has(sourceId) || movedNodes.has(sourceId)) {\n        hasBoundaryBranchInput = true;\n      } else if (!sourceId.startsWith('boundary_')) {\n        hasMainFlowInput = true;\n      }\n    }\n\n    if (!hasMainFlowInput || !hasBoundaryBranchInput) continue;\n\n    let maxSourceRightX = 0;\n    for (const sourceId of incomingSources) {\n      const sourceNode = nodeMap.get(sourceId);\n      if (!sourceNode) continue;\n\n      const moveInfo = movedNodes.get(sourceId);\n      const sourceX = moveInfo?.newX ?? sourceNode.x ?? 0;\n      const sourceWidth = sourceNode.width ?? 100;\n      const sourceRightX = sourceX + sourceWidth;\n\n      maxSourceRightX = Math.max(maxSourceRightX, sourceRightX);\n    }\n\n    const gatewayGap = 50;\n    const newGatewayX = maxSourceRightX + gatewayGap;\n    const currentGatewayX = node.x ?? 0;\n\n    if (newGatewayX > currentGatewayX) {\n      const currentY = node.y ?? 0;\n      gatewayMoves.set(nodeId, {\n        newY: currentY,\n        offset: 0,\n        newX: newGatewayX,\n      });\n\n      if (debug) {\n        console.log(\n          `[BPMN] Repositioning converging gateway ${nodeId}: x ${currentGatewayX} -> ${newGatewayX}`\n        );\n      }\n    }\n  }\n\n  return gatewayMoves;\n}\n\n/**\n * Apply node moves to the layouted graph\n */\nexport function applyNodeMoves(\n  graph: ElkNode,\n  movedNodes: Map<string, NodeMoveInfo>\n): void {\n  const applyMoves = (node: ElkNode) => {\n    const moveInfo = movedNodes.get(node.id);\n    if (moveInfo && node.y !== undefined) {\n      node.y = moveInfo.newY;\n      if (moveInfo.newX !== undefined) {\n        node.x = moveInfo.newX;\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        applyMoves(child);\n      }\n    }\n  };\n  applyMoves(graph);\n}\n","/**\n * Shared Debug Utilities\n * Centralized debug flag for consistent debug logging across the codebase.\n */\n\n/**\n * Flag to indicate CLI mode where debug output should be suppressed\n * to ensure clean stdout output.\n */\nlet cliMode = false;\n\n/**\n * Enable CLI mode which suppresses all debug output.\n * This should be called at the very start of the CLI entry point.\n */\nexport function enableCliMode(): void {\n  cliMode = true;\n}\n\n/**\n * Check if CLI mode is enabled.\n */\nexport function isCliMode(): boolean {\n  return cliMode;\n}\n\n/**\n * Check if debug logging is enabled.\n * Returns true only when DEBUG=true environment variable is set AND not in CLI mode.\n *\n * @example\n * ```bash\n * DEBUG=true bun run test -- -t \"21-subprocess\"\n * ```\n */\nexport function isDebugEnabled(): boolean {\n  if (cliMode) return false;\n\n  try {\n    return typeof process !== 'undefined' &&\n           typeof process.env !== 'undefined' &&\n           process.env?.['DEBUG'] === 'true';\n  } catch (e) {\n    // In browser environments, accessing process may throw an error\n    return false;\n  }\n}\n","/**\n * Edge Recalculator for Boundary Events\n * Handles edge waypoint recalculation for moved boundary event nodes.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { Point, Bounds, BoundaryEventInfo, NodeMoveInfo } from '../../../types/internal';\nimport { isDebugEnabled } from '../../../utils/debug';\n\n/**\n * Recalculate edge waypoints for edges connected to moved nodes\n * Implements orthogonal routing with obstacle avoidance\n */\nexport function recalculateEdgesForMovedNodes(\n  graph: ElkNode,\n  movedNodes: Map<string, NodeMoveInfo>,\n  boundaryEventInfo: Map<string, BoundaryEventInfo>\n): void {\n  const debug = isDebugEnabled();\n  // Build node map for position lookups (including boundary events)\n  const nodeMap = new Map<string, ElkNode>();\n  const buildNodeMap = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.children) {\n      for (const child of node.children) {\n        buildNodeMap(child);\n      }\n    }\n    // Also include boundary events\n    const nodeWithBE = node as unknown as { boundaryEvents?: ElkNode[] };\n    if (nodeWithBE.boundaryEvents) {\n      for (const be of nodeWithBE.boundaryEvents) {\n        nodeMap.set(be.id, be);\n      }\n    }\n  };\n  buildNodeMap(graph);\n\n  // Get all obstacle IDs: all flow nodes that could block edge paths\n  const obstacleIds = new Set<string>();\n\n  // Add attached nodes\n  for (const [, info] of boundaryEventInfo) {\n    obstacleIds.add(info.attachedToRef);\n  }\n  // Add all moved nodes as obstacles (they may block edge paths)\n  for (const [nodeId] of movedNodes) {\n    obstacleIds.add(nodeId);\n  }\n\n  // Add all flow nodes as potential obstacles (tasks, gateways, events, etc.)\n  const flowNodePatterns = [\n    /^task_/, /^gateway_/, /^start_/, /^end_/,\n    /^subprocess_/, /^call_/, /^intermediate_/, /^event_/, /^catch_/,\n  ];\n  for (const [nodeId] of nodeMap) {\n    if (flowNodePatterns.some(pattern => pattern.test(nodeId))) {\n      obstacleIds.add(nodeId);\n    }\n  }\n\n  // Calculate correct boundary event positions (they are attached to the bottom of their parent)\n  const boundaryEventPositions = new Map<string, Bounds>();\n  for (const [beId, info] of boundaryEventInfo) {\n    const attachedNode = nodeMap.get(info.attachedToRef);\n    if (attachedNode && attachedNode.x !== undefined && attachedNode.y !== undefined) {\n      const attachedX = attachedNode.x;\n      const attachedY = attachedNode.y;\n      const attachedWidth = attachedNode.width ?? 100;\n      const attachedHeight = attachedNode.height ?? 80;\n      const beWidth = 36;\n      const beHeight = 36;\n\n      // Calculate position on the bottom edge of the attached node\n      const spacing = attachedWidth / (info.totalBoundaries + 1);\n      const beX = attachedX + spacing * (info.boundaryIndex + 1) - beWidth / 2;\n      const beY = attachedY + attachedHeight - beHeight / 2;\n\n      boundaryEventPositions.set(beId, { x: beX, y: beY, width: beWidth, height: beHeight });\n    }\n  }\n\n  // Find and recalculate edges in each node\n  const processEdges = (node: ElkNode) => {\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const sourceId = edge.sources?.[0];\n        const targetId = edge.targets?.[0];\n\n        if (!sourceId || !targetId) continue;\n\n        // Recalculate if source OR target was moved, OR source is a boundary event\n        const sourceMoved = movedNodes.has(sourceId);\n        const targetMoved = movedNodes.has(targetId);\n        const sourceIsBoundaryEvent = boundaryEventInfo.has(sourceId);\n\n        if (sourceMoved || targetMoved || sourceIsBoundaryEvent) {\n          let sourceNode = nodeMap.get(sourceId);\n          const targetNode = nodeMap.get(targetId);\n\n          // For boundary events, use the calculated position\n          if (sourceIsBoundaryEvent && boundaryEventPositions.has(sourceId)) {\n            const bePos = boundaryEventPositions.get(sourceId)!;\n            sourceNode = { ...sourceNode, ...bePos } as ElkNode;\n          }\n\n          if (sourceNode && targetNode) {\n            recalculateEdgeWithObstacleAvoidance(\n              edge,\n              sourceNode,\n              targetNode,\n              obstacleIds,\n              nodeMap\n            );\n          }\n        }\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        processEdges(child);\n      }\n    }\n  };\n  processEdges(graph);\n}\n\n/**\n * Recalculate edge waypoints with orthogonal routing that avoids obstacles.\n * Key constraints:\n * 1. Edges MUST connect perpendicular to node boundaries\n * 2. Edges MUST NOT pass through any node\n */\nexport function recalculateEdgeWithObstacleAvoidance(\n  edge: ElkExtendedEdge,\n  source: ElkNode,\n  target: ElkNode,\n  obstacleIds: Set<string>,\n  nodeMap: Map<string, ElkNode>\n): void {\n  const debug = isDebugEnabled();\n  const sx = source.x ?? 0;\n  const sy = source.y ?? 0;\n  const sw = source.width ?? 100;\n  const sh = source.height ?? 80;\n\n  const tx = target.x ?? 0;\n  const ty = target.y ?? 0;\n  const tw = target.width ?? 36;\n  const th = target.height ?? 36;\n\n  // Collect all obstacles (excluding source and target)\n  const obstacles: Bounds[] = [];\n  for (const obsId of obstacleIds) {\n    const obs = nodeMap.get(obsId);\n    if (obs && obs.x !== undefined && obs.y !== undefined) {\n      // Skip source and target\n      if (obs.x === sx && obs.y === sy) continue;\n      if (obs.x === tx && obs.y === ty) continue;\n      obstacles.push({\n        x: obs.x,\n        y: obs.y,\n        width: obs.width ?? 100,\n        height: obs.height ?? 80,\n      });\n    }\n  }\n\n  if (debug) {\n    console.log(\n      `[BPMN] Edge ${edge.id}: source(${sx},${sy},${sw},${sh}) -> target(${tx},${ty},${tw},${th}), obstacles: ${obstacles.length}`\n    );\n  }\n\n  // Determine primary direction of travel\n  const dx = tx - sx;\n  const dy = ty - sy;\n  const absDx = Math.abs(dx);\n  const absDy = Math.abs(dy);\n  const isPrimarilyVertical = absDy > absDx;\n\n  const waypoints: Point[] = [];\n\n  if (isPrimarilyVertical && dy > 0) {\n    // Primary direction is DOWN - exit from bottom, enter from top\n    const startX = sx + sw / 2;\n    const startY = sy + sh;\n    const endX = tx + tw / 2;\n    const endY = ty;\n\n    waypoints.push({ x: startX, y: startY });\n\n    // Check for obstacles that would block a direct vertical path\n    const obstaclesToAvoid = findBlockingObstacles(\n      startX,\n      startY,\n      endX,\n      endY,\n      obstacles,\n      'vertical'\n    );\n\n    if (obstaclesToAvoid.length > 0) {\n      // Calculate left routing X\n      let leftAvoidX = Math.min(startX, endX);\n      for (const obs of obstaclesToAvoid) {\n        leftAvoidX = Math.min(leftAvoidX, obs.x - 30);\n      }\n      for (const obs of obstacles) {\n        if (obs.y < endY && obs.y + obs.height > startY) {\n          if (obs.x <= leftAvoidX + 20 && obs.x + obs.width >= leftAvoidX - 20) {\n            leftAvoidX = Math.min(leftAvoidX, obs.x - 30);\n          }\n        }\n      }\n\n      // Calculate right routing X\n      let rightAvoidX = Math.max(startX, endX);\n      for (const obs of obstaclesToAvoid) {\n        rightAvoidX = Math.max(rightAvoidX, obs.x + obs.width + 30);\n      }\n      for (const obs of obstacles) {\n        if (obs.y < endY && obs.y + obs.height > startY) {\n          if (obs.x <= rightAvoidX + 20 && obs.x + obs.width >= rightAvoidX - 20) {\n            rightAvoidX = Math.max(rightAvoidX, obs.x + obs.width + 30);\n          }\n        }\n      }\n\n      // Choose the shorter detour\n      const leftDistance = Math.abs(startX - leftAvoidX) + Math.abs(endX - leftAvoidX);\n      const rightDistance = Math.abs(startX - rightAvoidX) + Math.abs(endX - rightAvoidX);\n      const avoidX = leftDistance <= rightDistance ? leftAvoidX : rightAvoidX;\n\n      const exitY = startY + 20;\n      waypoints.push({ x: startX, y: exitY });\n      waypoints.push({ x: avoidX, y: exitY });\n      waypoints.push({ x: avoidX, y: endY - 20 });\n      waypoints.push({ x: endX, y: endY - 20 });\n    } else {\n      // No obstacles - simple Z-routing\n      const midY = (startY + endY) / 2;\n      waypoints.push({ x: startX, y: midY });\n      waypoints.push({ x: endX, y: midY });\n    }\n\n    waypoints.push({ x: endX, y: endY });\n  } else if (isPrimarilyVertical && dy < 0) {\n    // Primary direction is UP - exit from right, enter from bottom\n    const startX = sx + sw;\n    const startY = sy + sh / 2;\n    const endX = tx + tw / 2;\n    const endY = ty + th;\n\n    waypoints.push({ x: startX, y: startY });\n\n    // Find clearX that avoids all obstacles in the vertical path\n    let clearX = Math.max(sx + sw, tx + tw) + 30;\n    for (const obs of obstacles) {\n      if (obs.y < sy && obs.y + obs.height > ty) {\n        clearX = Math.max(clearX, obs.x + obs.width + 30);\n      }\n    }\n\n    // Check if the horizontal segment at endY would cross any obstacles\n    // The horizontal segment goes from (clearX, endY) to (endX, endY)\n    let horizontalClearY = endY;\n    const horizSegMinX = Math.min(clearX, endX);\n    const horizSegMaxX = Math.max(clearX, endX);\n    const margin = 20; // Minimum distance from obstacles\n\n    for (const obs of obstacles) {\n      // Check if obstacle overlaps with the horizontal segment\n      const obsRight = obs.x + obs.width;\n      const obsBottom = obs.y + obs.height;\n\n      // If obstacle is in the horizontal path (x-range overlaps)\n      if (obs.x < horizSegMaxX && obsRight > horizSegMinX) {\n        // And the horizontal segment is too close to the obstacle\n        if (horizontalClearY >= obs.y - margin && horizontalClearY <= obsBottom + margin) {\n          // Move the horizontal segment below this obstacle\n          horizontalClearY = Math.max(horizontalClearY, obsBottom + margin);\n        }\n      }\n    }\n\n    // Route: right -> down to clearY -> left to endX -> up to target\n    if (horizontalClearY > endY) {\n      // Need to go around obstacles below them\n      waypoints.push({ x: clearX, y: startY });\n      waypoints.push({ x: clearX, y: horizontalClearY });\n      waypoints.push({ x: endX, y: horizontalClearY });\n      waypoints.push({ x: endX, y: endY });\n    } else {\n      // Original simple routing\n      waypoints.push({ x: clearX, y: startY });\n      waypoints.push({ x: clearX, y: endY });\n      waypoints.push({ x: endX, y: endY });\n    }\n  } else if (!isPrimarilyVertical && dx > 0) {\n    // Primary direction is RIGHT - exit from right, enter from left\n    const startX = sx + sw;\n    const startY = sy + sh / 2;\n    const endX = tx;\n    const endY = ty + th / 2;\n\n    waypoints.push({ x: startX, y: startY });\n\n    const obstaclesToAvoid = findBlockingObstacles(\n      startX,\n      startY,\n      endX,\n      endY,\n      obstacles,\n      'horizontal'\n    );\n\n    if (obstaclesToAvoid.length > 0) {\n      let clearY = Math.max(sy + sh, ty + th) + 30;\n      for (const obs of obstaclesToAvoid) {\n        clearY = Math.max(clearY, obs.y + obs.height + 30);\n      }\n\n      waypoints.push({ x: startX + 20, y: startY });\n      waypoints.push({ x: startX + 20, y: clearY });\n      waypoints.push({ x: endX - 20, y: clearY });\n      waypoints.push({ x: endX - 20, y: endY });\n    } else {\n      // Simple Z-routing\n      const midX = (startX + endX) / 2;\n      waypoints.push({ x: midX, y: startY });\n      waypoints.push({ x: midX, y: endY });\n    }\n\n    waypoints.push({ x: endX, y: endY });\n  } else {\n    // Primary direction is LEFT - exit from left, enter from right\n    const startX = sx;\n    const startY = sy + sh / 2;\n    const endX = tx + tw;\n    const endY = ty + th / 2;\n\n    waypoints.push({ x: startX, y: startY });\n\n    let clearX = Math.min(sx, tx) - 30;\n    for (const obs of obstacles) {\n      clearX = Math.min(clearX, obs.x - 30);\n    }\n\n    waypoints.push({ x: clearX, y: startY });\n    waypoints.push({ x: clearX, y: endY });\n    waypoints.push({ x: endX, y: endY });\n  }\n\n  // Update edge sections\n  const firstWaypoint = waypoints[0];\n  const lastWaypoint = waypoints[waypoints.length - 1];\n  if (waypoints.length >= 2 && firstWaypoint && lastWaypoint) {\n    edge.sections = [\n      {\n        id: `${edge.id}_section_0`,\n        startPoint: firstWaypoint,\n        endPoint: lastWaypoint,\n        bendPoints: waypoints.slice(1, -1),\n      },\n    ];\n\n    if (debug) {\n      console.log(`[BPMN] Waypoints for ${edge.id}: ${JSON.stringify(waypoints)}`);\n    }\n  }\n}\n\n/**\n * Find obstacles that block a path between two points\n */\nexport function findBlockingObstacles(\n  startX: number,\n  startY: number,\n  endX: number,\n  endY: number,\n  obstacles: Bounds[],\n  direction: 'vertical' | 'horizontal'\n): Bounds[] {\n  const blocking: Bounds[] = [];\n  const margin = 5;\n\n  for (const obs of obstacles) {\n    const obsRight = obs.x + obs.width;\n    const obsBottom = obs.y + obs.height;\n\n    if (direction === 'vertical') {\n      const pathMinX = Math.min(startX, endX) - margin;\n      const pathMaxX = Math.max(startX, endX) + margin;\n      const pathMinY = Math.min(startY, endY);\n      const pathMaxY = Math.max(startY, endY);\n\n      if (obs.y < pathMaxY && obsBottom > pathMinY) {\n        if (obs.x < pathMaxX && obsRight > pathMinX) {\n          blocking.push(obs);\n        }\n      }\n    } else {\n      const pathMinX = Math.min(startX, endX);\n      const pathMaxX = Math.max(startX, endX);\n      const pathMinY = Math.min(startY, endY) - margin;\n      const pathMaxY = Math.max(startY, endY) + margin;\n\n      if (obs.x < pathMaxX && obsRight > pathMinX) {\n        if (obs.y < pathMaxY && obsBottom > pathMinY) {\n          blocking.push(obs);\n        }\n      }\n    }\n  }\n\n  return blocking;\n}\n","/**\n * Boundary Event Post-Processing Module\n * Re-exports all boundary event related functionality.\n */\n\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../../types';\nimport type { BoundaryEventInfo, NodeMoveInfo } from '../../../types/internal';\n\n// Export collector function\nexport { collectBoundaryEventInfo } from './collector';\n\n// Export mover functions\nexport {\n  identifyNodesToMove,\n  repositionConvergingGateways,\n  applyNodeMoves,\n  propagateMovement,\n  BranchDestType,\n} from './mover';\n\n// Export edge recalculator functions\nexport {\n  recalculateEdgesForMovedNodes,\n  recalculateEdgeWithObstacleAvoidance,\n  findBlockingObstacles,\n} from './edge-recalculator';\n\n// Import for class implementation\nimport { collectBoundaryEventInfo } from './collector';\nimport {\n  identifyNodesToMove,\n  repositionConvergingGateways,\n  applyNodeMoves,\n} from './mover';\nimport { recalculateEdgesForMovedNodes } from './edge-recalculator';\n\n/**\n * Handler for boundary event post-processing\n * Wraps the extracted functions in a class interface for backward compatibility.\n */\nexport class BoundaryEventHandler {\n  /**\n   * Collect boundary event information for post-processing\n   * Returns a map of boundary event ID -> { attachedToRef, targets, boundaryIndex, totalBoundaries }\n   */\n  collectInfo(graph: ElkBpmnGraph): Map<string, BoundaryEventInfo> {\n    return collectBoundaryEventInfo(graph);\n  }\n\n  /**\n   * Identify nodes that need to be moved below their attached boundary event parent\n   * Returns a map of node ID -> new position info\n   */\n  identifyNodesToMove(\n    graph: ElkNode,\n    boundaryEventInfo: Map<string, BoundaryEventInfo>,\n    sizedGraph: ElkBpmnGraph,\n    debug = false\n  ): Map<string, NodeMoveInfo> {\n    return identifyNodesToMove(graph, boundaryEventInfo, sizedGraph, debug);\n  }\n\n  /**\n   * Reposition converging gateways based on their incoming edges.\n   */\n  repositionConvergingGateways(\n    graph: ElkNode,\n    movedNodes: Map<string, NodeMoveInfo>,\n    boundaryEventInfo: Map<string, BoundaryEventInfo>,\n    debug = false\n  ): Map<string, NodeMoveInfo> {\n    return repositionConvergingGateways(graph, movedNodes, boundaryEventInfo, debug);\n  }\n\n  /**\n   * Apply node moves to the layouted graph\n   */\n  applyNodeMoves(graph: ElkNode, movedNodes: Map<string, NodeMoveInfo>): void {\n    applyNodeMoves(graph, movedNodes);\n  }\n\n  /**\n   * Recalculate edge waypoints for edges connected to moved nodes\n   */\n  recalculateEdgesForMovedNodes(\n    graph: ElkNode,\n    movedNodes: Map<string, NodeMoveInfo>,\n    boundaryEventInfo: Map<string, BoundaryEventInfo>\n  ): void {\n    recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo);\n  }\n}\n","/**\n * Geometry Utilities for Edge Routing\n * Provides geometric calculation functions for edge routing and obstacle avoidance.\n */\n\nimport type { Point, Bounds } from '../../types/internal';\n\n/**\n * Calculate Euclidean distance between two points\n */\nexport function distance(p1: Point, p2: Point): number {\n  return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));\n}\n\n/**\n * Calculate total path length of a series of waypoints\n */\nexport function calculatePathLength(waypoints: Point[]): number {\n  let length = 0;\n  for (let i = 0; i < waypoints.length - 1; i++) {\n    const p1 = waypoints[i];\n    const p2 = waypoints[i + 1];\n    if (p1 && p2) {\n      length += distance(p1, p2);\n    }\n  }\n  return length;\n}\n\n/**\n * Check if a line segment intersects a rectangle\n * Used for detecting edge-node collisions\n */\nexport function segmentIntersectsRect(\n  p1: Point,\n  p2: Point,\n  rect: Bounds\n): boolean {\n  const margin = 5;\n  const left = rect.x - margin;\n  const right = rect.x + rect.width + margin;\n  const top = rect.y - margin;\n  const bottom = rect.y + rect.height + margin;\n\n  // Check if both points are on the same side of the rectangle\n  if ((p1.x < left && p2.x < left) || (p1.x > right && p2.x > right)) return false;\n  if ((p1.y < top && p2.y < top) || (p1.y > bottom && p2.y > bottom)) return false;\n\n  // Check if segment is horizontal or vertical\n  if (Math.abs(p1.x - p2.x) < 1) {\n    // Vertical segment\n    const x = p1.x;\n    const minY = Math.min(p1.y, p2.y);\n    const maxY = Math.max(p1.y, p2.y);\n    return x >= left && x <= right && maxY >= top && minY <= bottom;\n  }\n\n  if (Math.abs(p1.y - p2.y) < 1) {\n    // Horizontal segment\n    const y = p1.y;\n    const minX = Math.min(p1.x, p2.x);\n    const maxX = Math.max(p1.x, p2.x);\n    return y >= top && y <= bottom && maxX >= left && minX <= right;\n  }\n\n  // For diagonal segments (shouldn't happen in orthogonal routing)\n  return true; // Assume intersection if not axis-aligned\n}\n\n/**\n * Check if a line segment crosses through a node's interior\n * More strict than segmentIntersectsRect - requires passing through the interior\n */\nexport function segmentCrossesNode(\n  p1: Point,\n  p2: Point,\n  node: Bounds\n): boolean {\n  const margin = 5;\n  const nodeLeft = node.x - margin;\n  const nodeRight = node.x + node.width + margin;\n  const nodeTop = node.y - margin;\n  const nodeBottom = node.y + node.height + margin;\n\n  // Check if segment is horizontal\n  if (Math.abs(p1.y - p2.y) < 1) {\n    const segY = p1.y;\n    const segMinX = Math.min(p1.x, p2.x);\n    const segMaxX = Math.max(p1.x, p2.x);\n\n    // Segment crosses if: y is within node's vertical range AND segment spans node's horizontal range\n    if (segY > nodeTop && segY < nodeBottom) {\n      if (segMinX < nodeRight && segMaxX > nodeLeft) {\n        // Check if segment actually passes through the interior (not just touching edges)\n        const interiorLeft = node.x + margin;\n        const interiorRight = node.x + node.width - margin;\n        if (segMinX < interiorRight && segMaxX > interiorLeft) {\n          return true;\n        }\n      }\n    }\n  }\n\n  // Check if segment is vertical\n  if (Math.abs(p1.x - p2.x) < 1) {\n    const segX = p1.x;\n    const segMinY = Math.min(p1.y, p2.y);\n    const segMaxY = Math.max(p1.y, p2.y);\n\n    // Segment crosses if: x is within node's horizontal range AND segment spans node's vertical range\n    if (segX > nodeLeft && segX < nodeRight) {\n      if (segMinY < nodeBottom && segMaxY > nodeTop) {\n        // Check if segment actually passes through the interior\n        const interiorTop = node.y + margin;\n        const interiorBottom = node.y + node.height - margin;\n        if (segMinY < interiorBottom && segMaxY > interiorTop) {\n          return true;\n        }\n      }\n    }\n  }\n\n  return false;\n}\n\n/**\n * Check if two rectangles overlap\n */\nexport function boundsOverlap(a: Bounds, b: Bounds, margin: number = 0): boolean {\n  return !(\n    a.x + a.width + margin < b.x ||\n    b.x + b.width + margin < a.x ||\n    a.y + a.height + margin < b.y ||\n    b.y + b.height + margin < a.y\n  );\n}\n\n/**\n * Get the center point of a bounds\n */\nexport function getCenter(bounds: Bounds): Point {\n  return {\n    x: bounds.x + bounds.width / 2,\n    y: bounds.y + bounds.height / 2,\n  };\n}\n\n/**\n * Calculate the midpoint between two points\n */\nexport function getMidpoint(p1: Point, p2: Point): Point {\n  return {\n    x: (p1.x + p2.x) / 2,\n    y: (p1.y + p2.y) / 2,\n  };\n}\n\n/**\n * Calculate connection point on a node based on direction\n */\nexport type ConnectionSide = 'left' | 'right' | 'top' | 'bottom';\n\nexport function getConnectionPoint(\n  bounds: Bounds,\n  side: ConnectionSide\n): Point {\n  const center = getCenter(bounds);\n\n  switch (side) {\n    case 'left':\n      return { x: bounds.x, y: center.y };\n    case 'right':\n      return { x: bounds.x + bounds.width, y: center.y };\n    case 'top':\n      return { x: center.x, y: bounds.y };\n    case 'bottom':\n      return { x: center.x, y: bounds.y + bounds.height };\n  }\n}\n\n/**\n * Determine the best connection side based on relative positions\n */\nexport function determineBestConnectionSide(\n  source: Bounds,\n  target: Bounds\n): { sourceSide: ConnectionSide; targetSide: ConnectionSide } {\n  const sourceCenter = getCenter(source);\n  const targetCenter = getCenter(target);\n\n  const dx = targetCenter.x - sourceCenter.x;\n  const dy = targetCenter.y - sourceCenter.y;\n\n  // Determine primary direction\n  if (Math.abs(dx) > Math.abs(dy)) {\n    // Horizontal movement\n    if (dx > 0) {\n      return { sourceSide: 'right', targetSide: 'left' };\n    } else {\n      return { sourceSide: 'left', targetSide: 'right' };\n    }\n  } else {\n    // Vertical movement\n    if (dy > 0) {\n      return { sourceSide: 'bottom', targetSide: 'top' };\n    } else {\n      return { sourceSide: 'top', targetSide: 'bottom' };\n    }\n  }\n}\n\n/**\n * Create an orthogonal path between two points with L-shaped or Z-shaped routing\n */\nexport function createOrthogonalPath(\n  start: Point,\n  end: Point,\n  primaryDirection: 'horizontal' | 'vertical' = 'horizontal'\n): Point[] {\n  const waypoints: Point[] = [start];\n\n  const dx = Math.abs(end.x - start.x);\n  const dy = Math.abs(end.y - start.y);\n\n  // If already aligned, direct connection\n  if (dx < 5 || dy < 5) {\n    waypoints.push(end);\n    return waypoints;\n  }\n\n  // Create L-shaped routing\n  if (primaryDirection === 'horizontal') {\n    const midX = (start.x + end.x) / 2;\n    waypoints.push({ x: midX, y: start.y });\n    waypoints.push({ x: midX, y: end.y });\n  } else {\n    const midY = (start.y + end.y) / 2;\n    waypoints.push({ x: start.x, y: midY });\n    waypoints.push({ x: end.x, y: midY });\n  }\n\n  waypoints.push(end);\n  return waypoints;\n}\n\n/**\n * Score a route based on obstacle crossings and path length\n * Lower score = better route\n */\nexport function scoreRoute(\n  start: Point,\n  bendPoints: Point[],\n  end: Point,\n  obstacles: Bounds[]\n): number {\n  let score = 0;\n  const crossingPenalty = 1000;\n  const lengthWeight = 0.1;\n\n  // Build full path\n  const path = [start, ...bendPoints, end];\n\n  // Check for crossings with each obstacle\n  for (const obs of obstacles) {\n    for (let i = 0; i < path.length - 1; i++) {\n      const p1 = path[i];\n      const p2 = path[i + 1];\n      if (p1 && p2 && segmentIntersectsRect(p1, p2, obs)) {\n        score += crossingPenalty;\n      }\n    }\n  }\n\n  // Add path length to score\n  for (let i = 0; i < path.length - 1; i++) {\n    const p1 = path[i];\n    const p2 = path[i + 1];\n    if (p1 && p2) {\n      score += distance(p1, p2) * lengthWeight;\n    }\n  }\n\n  return score;\n}\n\n/**\n * Find a clear vertical path that avoids obstacles\n * Returns the Y coordinate to route through, or null if direct path is clear\n */\nexport function findClearVerticalPath(\n  x: number,\n  startY: number,\n  endY: number,\n  obstacles: Bounds[]\n): number | null {\n  const minY = Math.min(startY, endY);\n  const maxY = Math.max(startY, endY);\n  const margin = 10;\n\n  // Check if any obstacle blocks the vertical path\n  for (const obs of obstacles) {\n    const obsLeft = obs.x - margin;\n    const obsRight = obs.x + obs.width + margin;\n    const obsTop = obs.y;\n    const obsBottom = obs.y + obs.height;\n\n    // Check if x is within obstacle's horizontal range\n    if (x >= obsLeft && x <= obsRight) {\n      // Check if obstacle is in our vertical path\n      if (obsBottom > minY && obsTop < maxY) {\n        // Found an obstacle - return a Y that goes around it\n        // Prefer going below the obstacle if there's more space\n        const spaceAbove = obsTop - minY;\n        const spaceBelow = maxY - obsBottom;\n\n        if (spaceBelow > spaceAbove && obsBottom + margin < maxY) {\n          return obsBottom + margin;\n        } else if (obsTop - margin > minY) {\n          return obsTop - margin;\n        }\n      }\n    }\n  }\n\n  return null; // No obstacle found, direct path is clear\n}\n\n/**\n * Calculate intersection point of two line segments.\n * Returns null if lines don't intersect within both segments.\n * Used for diamond edge intersection calculations.\n */\nexport function lineIntersection(\n  p1: Point,\n  p2: Point,\n  p3: Point,\n  p4: Point\n): Point | null {\n  const denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);\n  if (Math.abs(denom) < 0.0001) return null; // Lines are parallel\n\n  const ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denom;\n  const ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denom;\n\n  // Check if intersection is within both line segments\n  if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {\n    return {\n      x: p1.x + ua * (p2.x - p1.x),\n      y: p1.y + ua * (p2.y - p1.y),\n    };\n  }\n\n  return null;\n}\n\n/**\n * Find a clear horizontal path that avoids obstacles\n * Returns the X coordinate to route through, or null if direct path is clear\n */\nexport function findClearHorizontalPath(\n  y: number,\n  startX: number,\n  endX: number,\n  obstacles: Bounds[]\n): number | null {\n  const minX = Math.min(startX, endX);\n  const maxX = Math.max(startX, endX);\n  const margin = 10;\n\n  // Check if any obstacle blocks the horizontal path\n  for (const obs of obstacles) {\n    const obsTop = obs.y - margin;\n    const obsBottom = obs.y + obs.height + margin;\n    const obsLeft = obs.x;\n    const obsRight = obs.x + obs.width;\n\n    // Check if y is within obstacle's vertical range\n    if (y >= obsTop && y <= obsBottom) {\n      // Check if obstacle is in our horizontal path\n      if (obsRight > minX && obsLeft < maxX) {\n        // Found an obstacle - return an X that goes around it\n        // Prefer going right of the obstacle if there's more space\n        const spaceLeft = obsLeft - minX;\n        const spaceRight = maxX - obsRight;\n\n        if (spaceRight > spaceLeft && obsRight + margin < maxX) {\n          return obsRight + margin;\n        } else if (obsLeft - margin > minX) {\n          return obsLeft - margin;\n        }\n      }\n    }\n  }\n\n  return null; // No obstacle found, direct path is clear\n}\n","/**\n * BPMN Constants and Mappings\n */\n\n// ============================================================================\n// Default Element Sizes\n// ============================================================================\n\nexport const DEFAULT_SIZES = {\n  // Events (all types)\n  EVENT: { width: 36, height: 36 },\n\n  // Tasks (all types)\n  TASK: { width: 100, height: 80 },\n  TASK_WIDE: { width: 120, height: 80 },\n  TASK_WIDER: { width: 150, height: 80 },\n\n  // Gateways (all types)\n  GATEWAY: { width: 50, height: 50 },\n\n  // SubProcesses\n  SUBPROCESS_COLLAPSED: { width: 100, height: 80 },\n  SUBPROCESS_EXPANDED_MIN: { width: 300, height: 200 },\n\n  // Data Objects\n  DATA_OBJECT: { width: 36, height: 50 },\n  DATA_STORE: { width: 50, height: 50 },\n\n  // Text Annotation\n  TEXT_ANNOTATION: { width: 100, height: 30 },\n} as const;\n\n// ============================================================================\n// BPMN Element Type to XML Element Mapping\n// ============================================================================\n\nexport const BPMN_ELEMENT_MAP = {\n  // Events (bpmn-moddle uses PascalCase)\n  startEvent: 'bpmn:StartEvent',\n  endEvent: 'bpmn:EndEvent',\n  intermediateCatchEvent: 'bpmn:IntermediateCatchEvent',\n  intermediateThrowEvent: 'bpmn:IntermediateThrowEvent',\n  boundaryEvent: 'bpmn:BoundaryEvent',\n\n  // Tasks\n  task: 'bpmn:Task',\n  userTask: 'bpmn:UserTask',\n  serviceTask: 'bpmn:ServiceTask',\n  scriptTask: 'bpmn:ScriptTask',\n  businessRuleTask: 'bpmn:BusinessRuleTask',\n  sendTask: 'bpmn:SendTask',\n  receiveTask: 'bpmn:ReceiveTask',\n  manualTask: 'bpmn:ManualTask',\n\n  // Gateways\n  exclusiveGateway: 'bpmn:ExclusiveGateway',\n  parallelGateway: 'bpmn:ParallelGateway',\n  inclusiveGateway: 'bpmn:InclusiveGateway',\n  eventBasedGateway: 'bpmn:EventBasedGateway',\n  complexGateway: 'bpmn:ComplexGateway',\n\n  // SubProcesses\n  subProcess: 'bpmn:SubProcess',\n  transaction: 'bpmn:Transaction',\n  adHocSubProcess: 'bpmn:AdHocSubProcess',\n  eventSubProcess: 'bpmn:SubProcess', // Same element, different attribute\n\n  // Call Activity\n  callActivity: 'bpmn:CallActivity',\n\n  // Artifacts\n  dataObject: 'bpmn:DataObject',\n  dataObjectReference: 'bpmn:DataObjectReference',\n  dataInput: 'bpmn:DataInput',\n  dataOutput: 'bpmn:DataOutput',\n  dataStoreReference: 'bpmn:DataStoreReference',\n  textAnnotation: 'bpmn:TextAnnotation',\n  group: 'bpmn:Group',\n\n  // Flows\n  sequenceFlow: 'bpmn:SequenceFlow',\n  messageFlow: 'bpmn:MessageFlow',\n  dataInputAssociation: 'bpmn:DataInputAssociation',\n  dataOutputAssociation: 'bpmn:DataOutputAssociation',\n  association: 'bpmn:Association',\n\n  // Containers\n  collaboration: 'bpmn:Collaboration',\n  participant: 'bpmn:Participant',\n  process: 'bpmn:Process',\n  lane: 'bpmn:Lane',\n  laneSet: 'bpmn:LaneSet',\n} as const;\n\n// ============================================================================\n// Event Definition Type to XML Element Mapping\n// ============================================================================\n\nexport const EVENT_DEFINITION_MAP = {\n  none: null,\n  message: 'bpmn:MessageEventDefinition',\n  timer: 'bpmn:TimerEventDefinition',\n  error: 'bpmn:ErrorEventDefinition',\n  escalation: 'bpmn:EscalationEventDefinition',\n  cancel: 'bpmn:CancelEventDefinition',\n  compensation: 'bpmn:CompensateEventDefinition',\n  conditional: 'bpmn:ConditionalEventDefinition',\n  link: 'bpmn:LinkEventDefinition',\n  signal: 'bpmn:SignalEventDefinition',\n  terminate: 'bpmn:TerminateEventDefinition',\n  multiple: null, // Multiple event definitions\n  parallelMultiple: null, // Multiple parallel event definitions\n} as const;\n\n// ============================================================================\n// BPMN XML Namespaces\n// ============================================================================\n\nexport const BPMN_NAMESPACES = {\n  bpmn: 'http://www.omg.org/spec/BPMN/20100524/MODEL',\n  bpmndi: 'http://www.omg.org/spec/BPMN/20100524/DI',\n  dc: 'http://www.omg.org/spec/DD/20100524/DC',\n  di: 'http://www.omg.org/spec/DD/20100524/DI',\n  xsi: 'http://www.w3.org/2001/XMLSchema-instance',\n  camunda: 'http://camunda.org/schema/1.0/bpmn',\n} as const;\n\n// ============================================================================\n// Default ELK Layout Options\n// ============================================================================\n\nexport const DEFAULT_ELK_OPTIONS = {\n  'elk.algorithm': 'layered',\n  'elk.direction': 'RIGHT',\n  'elk.spacing.nodeNode': 50,\n  'elk.spacing.edgeNode': 30,\n  'elk.spacing.edgeEdge': 20,\n  'elk.layered.spacing.nodeNodeBetweenLayers': 80,\n  'elk.layered.spacing.edgeNodeBetweenLayers': 30,\n  'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n  'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',\n  'elk.edgeRouting': 'ORTHOGONAL',\n} as const;\n\n// ============================================================================\n// Element Categories\n// ============================================================================\n\nexport const EVENT_TYPES = [\n  'startEvent',\n  'endEvent',\n  'intermediateCatchEvent',\n  'intermediateThrowEvent',\n  'boundaryEvent',\n] as const;\n\nexport const TASK_TYPES = [\n  'task',\n  'userTask',\n  'serviceTask',\n  'scriptTask',\n  'businessRuleTask',\n  'sendTask',\n  'receiveTask',\n  'manualTask',\n] as const;\n\nexport const GATEWAY_TYPES = [\n  'exclusiveGateway',\n  'parallelGateway',\n  'inclusiveGateway',\n  'eventBasedGateway',\n  'complexGateway',\n] as const;\n\nexport const SUBPROCESS_TYPES = [\n  'subProcess',\n  'transaction',\n  'adHocSubProcess',\n  'eventSubProcess',\n] as const;\n\nexport const ARTIFACT_TYPES = [\n  'dataObject',\n  'dataObjectReference',\n  'dataStoreReference',\n  'textAnnotation',\n  'group',\n] as const;\n\n/**\n * Group element type constant\n */\nexport const GROUP_TYPE = 'group';\n\n/**\n * Set of artifact types for efficient lookup in layout processing.\n * Note: Excludes 'group' because groups are handled separately by GroupPositioner.\n */\nexport const ARTIFACT_TYPES_SET = new Set([\n  'dataObject',\n  'dataObjectReference',\n  'dataStoreReference',\n  'textAnnotation',\n]);\n\nexport const FLOW_TYPES = [\n  'sequenceFlow',\n  'messageFlow',\n  'dataInputAssociation',\n  'dataOutputAssociation',\n  'association',\n] as const;\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\nexport type EventTypeString = (typeof EVENT_TYPES)[number];\nexport type TaskTypeString = (typeof TASK_TYPES)[number];\nexport type GatewayTypeString = (typeof GATEWAY_TYPES)[number];\nexport type SubProcessTypeString = (typeof SUBPROCESS_TYPES)[number];\nexport type ArtifactTypeString = (typeof ARTIFACT_TYPES)[number];\nexport type FlowTypeString = (typeof FLOW_TYPES)[number];\nexport type BpmnElementType = keyof typeof BPMN_ELEMENT_MAP;\n","/**\n * Node Map Builder Utility\n * Provides shared functions for building node maps from ELK graphs.\n * Used by various post-processors to efficiently look up nodes by ID.\n */\n\nimport type { ElkNode } from 'elkjs';\n\n/**\n * Build a flat map of all nodes in the graph, keyed by ID.\n * Recursively traverses the graph to include all nested nodes.\n *\n * @param graph - The root ELK graph node\n * @returns A Map from node ID to ElkNode\n */\nexport function buildNodeMap(graph: ElkNode): Map<string, ElkNode> {\n  const nodeMap = new Map<string, ElkNode>();\n\n  const traverse = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.children) {\n      for (const child of node.children) {\n        traverse(child);\n      }\n    }\n  };\n\n  traverse(graph);\n  return nodeMap;\n}\n\n/**\n * Build a map of nodes with their parent references.\n * Useful when you need to know the parent of each node.\n *\n * @param graph - The root ELK graph node\n * @returns A tuple of [nodeMap, parentMap] where parentMap maps node ID to parent node\n */\nexport function buildNodeMapWithParents(\n  graph: ElkNode\n): [Map<string, ElkNode>, Map<string, ElkNode>] {\n  const nodeMap = new Map<string, ElkNode>();\n  const parentMap = new Map<string, ElkNode>();\n\n  const traverse = (node: ElkNode, parent?: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (parent) {\n      parentMap.set(node.id, parent);\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        traverse(child, node);\n      }\n    }\n  };\n\n  traverse(graph);\n  return [nodeMap, parentMap];\n}\n\n/**\n * Build a map of nodes with accumulated absolute offsets.\n * Useful when you need absolute coordinates for nodes in nested containers.\n *\n * @param graph - The root ELK graph node\n * @param isContainer - Function to determine if a node is a container (adds offset)\n * @returns A Map from node ID to { node, offsetX, offsetY }\n */\nexport function buildNodeMapWithOffsets(\n  graph: ElkNode,\n  isContainer: (node: ElkNode) => boolean\n): Map<string, { node: ElkNode; offsetX: number; offsetY: number }> {\n  const nodeMap = new Map<string, { node: ElkNode; offsetX: number; offsetY: number }>();\n\n  const traverse = (node: ElkNode, offsetX: number, offsetY: number) => {\n    nodeMap.set(node.id, { node, offsetX, offsetY });\n\n    if (node.children) {\n      // Calculate new offset for children\n      const addOffset = isContainer(node);\n      const newOffsetX = addOffset ? offsetX + (node.x ?? 0) : offsetX;\n      const newOffsetY = addOffset ? offsetY + (node.y ?? 0) : offsetY;\n\n      for (const child of node.children) {\n        traverse(child, newOffsetX, newOffsetY);\n      }\n    }\n  };\n\n  traverse(graph, 0, 0);\n  return nodeMap;\n}\n\n/**\n * Build a map of node absolute positions.\n * Calculates absolute x, y coordinates for each node.\n *\n * @param graph - The root ELK graph node\n * @param isContainer - Function to determine if a node is a container\n * @returns A Map from node ID to { x, y, width, height } in absolute coordinates\n */\nexport function buildAbsolutePositionMap(\n  graph: ElkNode,\n  isContainer: (node: ElkNode) => boolean\n): Map<string, { x: number; y: number; width: number; height: number }> {\n  const positionMap = new Map<string, { x: number; y: number; width: number; height: number }>();\n\n  const traverse = (node: ElkNode, offsetX: number, offsetY: number) => {\n    const absX = offsetX + (node.x ?? 0);\n    const absY = offsetY + (node.y ?? 0);\n\n    positionMap.set(node.id, {\n      x: absX,\n      y: absY,\n      width: node.width ?? 0,\n      height: node.height ?? 0,\n    });\n\n    if (node.children) {\n      // Calculate new offset for children\n      const addOffset = isContainer(node);\n      const newOffsetX = addOffset ? absX : offsetX;\n      const newOffsetY = addOffset ? absY : offsetY;\n\n      for (const child of node.children) {\n        traverse(child, newOffsetX, newOffsetY);\n      }\n    }\n  };\n\n  traverse(graph, 0, 0);\n  return positionMap;\n}\n","/**\n * Artifact Positioner\n * Handles repositioning of BPMN artifacts (data objects, data stores, annotations)\n * to be positioned above/near their associated tasks.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { Point, Bounds, NodeWithBpmn, ArtifactInfo, Obstacle } from '../../types/internal';\nimport {\n  segmentIntersectsRect,\n  scoreRoute,\n  findClearVerticalPath,\n} from '../edge-routing/geometry-utils';\nimport { ARTIFACT_TYPES_SET } from '../../types/bpmn-constants';\nimport { buildNodeMap } from '../../utils/node-map-builder';\n\n/**\n * Artifact types that should be repositioned above their associated tasks\n * @deprecated Use ARTIFACT_TYPES_SET from bpmn-constants instead\n */\nexport const ARTIFACT_TYPES = ARTIFACT_TYPES_SET;\n\n/**\n * Handler for artifact repositioning\n */\nexport class ArtifactPositioner {\n  /**\n   * Collect artifact information for post-processing\n   * Returns a map of artifact ID -> { associatedTaskId, isInput }\n   */\n  collectInfo(graph: ElkBpmnGraph): Map<string, ArtifactInfo> {\n    const info = new Map<string, ArtifactInfo>();\n\n    const collectFromNode = (node: NodeWithBpmn) => {\n      // Build a set of artifact IDs in this node\n      const artifactIds = new Set<string>();\n      if (node.children) {\n        for (const child of node.children) {\n          const childNode = child as NodeWithBpmn;\n          if (childNode.bpmn && ARTIFACT_TYPES.has(childNode.bpmn.type)) {\n            artifactIds.add(childNode.id);\n          }\n        }\n      }\n\n      // Find associations between artifacts and tasks from edges\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const sourceId = edge.sources?.[0];\n          const targetId = edge.targets?.[0];\n          const edgeType = edge.bpmn?.type;\n\n          if (!sourceId || !targetId) continue;\n\n          // Skip artifact-to-artifact associations (e.g., between two dataStores)\n          // These should not be used for positioning\n          if (artifactIds.has(sourceId) && artifactIds.has(targetId)) {\n            continue;\n          }\n\n          // Data input association: artifact -> task\n          if (edgeType === 'dataInputAssociation' || edgeType === 'association') {\n            if (artifactIds.has(sourceId)) {\n              info.set(sourceId, { associatedTaskId: targetId, isInput: true });\n            }\n          }\n          // Data output association: task -> artifact\n          if (edgeType === 'dataOutputAssociation') {\n            if (artifactIds.has(targetId)) {\n              info.set(targetId, { associatedTaskId: sourceId, isInput: false });\n            }\n          }\n        }\n      }\n\n      // Recurse into children\n      if (node.children) {\n        for (const child of node.children) {\n          collectFromNode(child as NodeWithBpmn);\n        }\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      collectFromNode(child as NodeWithBpmn);\n    }\n\n    return info;\n  }\n\n  /**\n   * Reposition artifacts to be above their associated tasks\n   */\n  reposition(graph: ElkNode, artifactInfo: Map<string, ArtifactInfo>): void {\n    // Build node map\n    const nodeMap = buildNodeMap(graph);\n\n    // Track horizontal offset for each task (for multiple artifacts)\n    const taskInputOffsets = new Map<string, number>();\n    const taskOutputOffsets = new Map<string, number>();\n\n    // Reposition each artifact\n    for (const [artifactId, info] of artifactInfo) {\n      const artifactNode = nodeMap.get(artifactId);\n      const taskNode = nodeMap.get(info.associatedTaskId);\n\n      if (!artifactNode || !taskNode) continue;\n      if (taskNode.x === undefined || taskNode.y === undefined) continue;\n\n      const artifactWidth = artifactNode.width ?? 36;\n      const artifactHeight = artifactNode.height ?? 50;\n      const taskWidth = taskNode.width ?? 100;\n\n      // Position artifact above the task\n      // Input artifacts on the left, output artifacts on the right\n      let newX: number;\n      if (info.isInput) {\n        const currentOffset = taskInputOffsets.get(info.associatedTaskId) ?? 0;\n        newX = taskNode.x + currentOffset;\n        taskInputOffsets.set(info.associatedTaskId, currentOffset + artifactWidth + 15);\n      } else {\n        const currentOffset = taskOutputOffsets.get(info.associatedTaskId) ?? 0;\n        newX = taskNode.x + taskWidth + 15 + currentOffset; // Position to the right of task\n        taskOutputOffsets.set(info.associatedTaskId, currentOffset + artifactWidth + 15);\n      }\n      const newY = taskNode.y - artifactHeight - 20; // 20px gap above task\n\n      artifactNode.x = newX;\n      artifactNode.y = newY;\n    }\n\n    // Recalculate edges for repositioned artifacts\n    this.recalculateEdges(graph, artifactInfo, nodeMap);\n  }\n\n  /**\n   * Recalculate edges connected to repositioned artifacts\n   */\n  private recalculateEdges(\n    graph: ElkNode,\n    artifactInfo: Map<string, ArtifactInfo>,\n    nodeMap: Map<string, ElkNode>\n  ): void {\n    const processEdges = (node: ElkNode) => {\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const sourceId = edge.sources?.[0];\n          const targetId = edge.targets?.[0];\n\n          if (!sourceId || !targetId) continue;\n\n          // Check if this edge involves an artifact\n          const sourceIsArtifact = artifactInfo.has(sourceId);\n          const targetIsArtifact = artifactInfo.has(targetId);\n\n          if (sourceIsArtifact || targetIsArtifact) {\n            const sourceNode = nodeMap.get(sourceId);\n            const targetNode = nodeMap.get(targetId);\n\n            if (sourceNode && targetNode) {\n              this.recalculateArtifactEdge(edge, sourceNode, targetNode, sourceIsArtifact);\n            }\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          processEdges(child);\n        }\n      }\n    };\n    processEdges(graph);\n  }\n\n  /**\n   * Recalculate a single artifact edge (simple version)\n   */\n  private recalculateArtifactEdge(\n    edge: ElkExtendedEdge,\n    source: ElkNode,\n    target: ElkNode,\n    sourceIsArtifact: boolean\n  ): void {\n    const sx = source.x ?? 0;\n    const sy = source.y ?? 0;\n    const sw = source.width ?? 36;\n    const sh = source.height ?? 50;\n\n    const tx = target.x ?? 0;\n    const ty = target.y ?? 0;\n    const tw = target.width ?? 100;\n    const th = target.height ?? 80;\n\n    let startPoint: Point;\n    let endPoint: Point;\n\n    if (sourceIsArtifact) {\n      // Artifact -> Task (input): artifact is above/left of task\n      // Start from bottom of artifact, end at top of task\n      startPoint = { x: sx + sw / 2, y: sy + sh };\n      endPoint = { x: Math.min(Math.max(sx + sw / 2, tx), tx + tw), y: ty };\n    } else {\n      // Task -> Artifact (output): artifact is above/right of task\n      // Start from top-right of task, end at bottom of artifact\n      const artifactCenterX = tx + tw / 2;\n      startPoint = { x: Math.min(sx + sw, artifactCenterX), y: sy };\n      endPoint = { x: artifactCenterX, y: ty + th };\n    }\n\n    edge.sections = [{\n      id: `${edge.id}_section_0`,\n      startPoint,\n      endPoint,\n      bendPoints: [],\n    }];\n  }\n\n  /**\n   * Recalculate artifact edges with obstacle avoidance\n   * Implements orthogonal routing that avoids crossing other elements\n   */\n  recalculateWithObstacleAvoidance(\n    graph: ElkNode,\n    artifactInfo: Map<string, ArtifactInfo>\n  ): void {\n    // Build node map for position lookups\n    const nodeMap = buildNodeMap(graph);\n\n    // Collect all obstacles (non-artifact nodes)\n    const obstacles: Obstacle[] = [];\n    const collectObstacles = (node: ElkNode) => {\n      if (node.x !== undefined && node.y !== undefined && !artifactInfo.has(node.id)) {\n        // Skip groups (they're just visual overlays)\n        const isGroup = node.id.includes('group');\n        if (!isGroup) {\n          obstacles.push({\n            id: node.id,\n            x: node.x,\n            y: node.y,\n            width: node.width ?? 100,\n            height: node.height ?? 80,\n          });\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          collectObstacles(child);\n        }\n      }\n    };\n    collectObstacles(graph);\n\n    // Process edges\n    const processEdges = (node: ElkNode) => {\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const sourceId = edge.sources?.[0];\n          const targetId = edge.targets?.[0];\n\n          if (!sourceId || !targetId) continue;\n\n          // Check if this edge involves an artifact\n          const sourceIsArtifact = artifactInfo.has(sourceId);\n          const targetIsArtifact = artifactInfo.has(targetId);\n\n          if (sourceIsArtifact || targetIsArtifact) {\n            const sourceNode = nodeMap.get(sourceId);\n            const targetNode = nodeMap.get(targetId);\n\n            if (sourceNode && targetNode) {\n              this.recalculateEdgeWithObstacles(\n                edge,\n                sourceNode,\n                targetNode,\n                sourceIsArtifact,\n                obstacles.filter(o => o.id !== sourceId && o.id !== targetId)\n              );\n            }\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          processEdges(child);\n        }\n      }\n    };\n    processEdges(graph);\n  }\n\n  /**\n   * Recalculate a single artifact edge with orthogonal routing and obstacle avoidance\n   */\n  private recalculateEdgeWithObstacles(\n    edge: ElkExtendedEdge,\n    source: ElkNode,\n    target: ElkNode,\n    sourceIsArtifact: boolean,\n    obstacles: Obstacle[]\n  ): void {\n    const sx = source.x ?? 0;\n    const sy = source.y ?? 0;\n    const sw = source.width ?? 36;\n    const sh = source.height ?? 50;\n\n    const tx = target.x ?? 0;\n    const ty = target.y ?? 0;\n    const tw = target.width ?? 100;\n    const th = target.height ?? 80;\n\n    // Determine connection points based on relative positions\n    let startPoint: Point;\n    let endPoint: Point;\n    const bendPoints: Point[] = [];\n\n    const sourceCenterX = sx + sw / 2;\n    const sourceCenterY = sy + sh / 2;\n    const targetCenterX = tx + tw / 2;\n    const targetCenterY = ty + th / 2;\n\n    // Determine if we're going up, down, left, or right\n    const goingRight = targetCenterX > sourceCenterX + sw / 2;\n    const goingLeft = targetCenterX < sourceCenterX - sw / 2;\n    const goingDown = targetCenterY > sourceCenterY + sh / 2;\n    const goingUp = targetCenterY < sourceCenterY - sh / 2;\n\n    if (sourceIsArtifact) {\n      // Artifact is source (data input association: artifact -> task)\n      if (goingDown) {\n        // Source above target: exit from bottom, enter from top\n        startPoint = { x: sourceCenterX, y: sy + sh };\n        endPoint = { x: targetCenterX, y: ty };\n\n        // Check for obstacles and route around them\n        const routeY = findClearVerticalPath(startPoint.x, startPoint.y, endPoint.y, obstacles);\n        if (Math.abs(startPoint.x - endPoint.x) > 5 || routeY !== null) {\n          if (routeY !== null && routeY !== startPoint.y && routeY !== endPoint.y) {\n            bendPoints.push({ x: startPoint.x, y: routeY });\n            bendPoints.push({ x: endPoint.x, y: routeY });\n          } else {\n            // Simple L-shaped routing\n            const midY = (startPoint.y + endPoint.y) / 2;\n            bendPoints.push({ x: startPoint.x, y: midY });\n            bendPoints.push({ x: endPoint.x, y: midY });\n          }\n        }\n      } else if (goingUp) {\n        // Source below target: exit from top, enter from bottom\n        startPoint = { x: sourceCenterX, y: sy };\n        endPoint = { x: targetCenterX, y: ty + th };\n\n        const midY = (startPoint.y + endPoint.y) / 2;\n        if (Math.abs(startPoint.x - endPoint.x) > 5) {\n          bendPoints.push({ x: startPoint.x, y: midY });\n          bendPoints.push({ x: endPoint.x, y: midY });\n        }\n      } else if (goingRight) {\n        // Source left of target: exit from right, enter from left\n        startPoint = { x: sx + sw, y: sourceCenterY };\n        endPoint = { x: tx, y: targetCenterY };\n\n        // Route with obstacle avoidance\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      } else {\n        // Source right of target: exit from left, enter from right\n        startPoint = { x: sx, y: sourceCenterY };\n        endPoint = { x: tx + tw, y: targetCenterY };\n\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      }\n    } else {\n      // Task is source (data output association: task -> artifact)\n      if (goingUp) {\n        // Target above source: exit from top, enter from bottom\n        startPoint = { x: sourceCenterX, y: sy };\n        endPoint = { x: targetCenterX, y: ty + th };\n\n        const midY = (startPoint.y + endPoint.y) / 2;\n        if (Math.abs(startPoint.x - endPoint.x) > 5) {\n          bendPoints.push({ x: startPoint.x, y: midY });\n          bendPoints.push({ x: endPoint.x, y: midY });\n        }\n      } else if (goingDown) {\n        // Target below source: exit from bottom, enter from top\n        startPoint = { x: sourceCenterX, y: sy + sh };\n        endPoint = { x: targetCenterX, y: ty };\n\n        const midY = (startPoint.y + endPoint.y) / 2;\n        if (Math.abs(startPoint.x - endPoint.x) > 5) {\n          bendPoints.push({ x: startPoint.x, y: midY });\n          bendPoints.push({ x: endPoint.x, y: midY });\n        }\n      } else if (goingRight) {\n        // Target right of source: exit from right, enter from left\n        startPoint = { x: sx + sw, y: sourceCenterY };\n        endPoint = { x: tx, y: targetCenterY };\n\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      } else {\n        // Target left of source: exit from left, enter from right\n        startPoint = { x: sx, y: sourceCenterY };\n        endPoint = { x: tx + tw, y: targetCenterY };\n\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      }\n    }\n\n    edge.sections = [{\n      id: `${edge.id}_section_0`,\n      startPoint,\n      endPoint,\n      bendPoints: bendPoints.length > 0 ? bendPoints : undefined,\n    }];\n  }\n\n  /**\n   * Add orthogonal bend points with obstacle avoidance\n   */\n  private addOrthogonalBendPoints(\n    start: Point,\n    end: Point,\n    bendPoints: Point[],\n    obstacles: Bounds[]\n  ): void {\n    const margin = 15;\n\n    // Check if direct path (with one bend) crosses any obstacle\n    const midX = (start.x + end.x) / 2;\n    const midY = (start.y + end.y) / 2;\n\n    // Try different routing strategies\n    const strategies: Array<{ points: Point[]; score: number }> = [];\n\n    // Strategy 1: Horizontal first, then vertical\n    const s1: Point[] = [\n      { x: midX, y: start.y },\n      { x: midX, y: end.y },\n    ];\n    strategies.push({ points: s1, score: scoreRoute(start, s1, end, obstacles) });\n\n    // Strategy 2: Vertical first, then horizontal\n    const s2: Point[] = [\n      { x: start.x, y: midY },\n      { x: end.x, y: midY },\n    ];\n    strategies.push({ points: s2, score: scoreRoute(start, s2, end, obstacles) });\n\n    // Strategy 3: Route above obstacles\n    const maxObstacleTop = Math.min(...obstacles.map(o => o.y), start.y, end.y);\n    const routeAboveY = maxObstacleTop - margin;\n    const s3: Point[] = [\n      { x: start.x, y: routeAboveY },\n      { x: end.x, y: routeAboveY },\n    ];\n    strategies.push({ points: s3, score: scoreRoute(start, s3, end, obstacles) });\n\n    // Strategy 4: Route below obstacles\n    const maxObstacleBottom = Math.max(...obstacles.map(o => o.y + o.height), start.y, end.y);\n    const routeBelowY = maxObstacleBottom + margin;\n    const s4: Point[] = [\n      { x: start.x, y: routeBelowY },\n      { x: end.x, y: routeBelowY },\n    ];\n    strategies.push({ points: s4, score: scoreRoute(start, s4, end, obstacles) });\n\n    // Strategy 5: Route to the right of obstacles\n    const maxObstacleRight = Math.max(...obstacles.map(o => o.x + o.width), start.x, end.x);\n    const routeRightX = maxObstacleRight + margin;\n    const s5: Point[] = [\n      { x: routeRightX, y: start.y },\n      { x: routeRightX, y: end.y },\n    ];\n    strategies.push({ points: s5, score: scoreRoute(start, s5, end, obstacles) });\n\n    // Choose the best strategy (lowest score = fewer crossings + shorter path)\n    strategies.sort((a, b) => a.score - b.score);\n    const best = strategies[0];\n\n    // Only add bend points if they're significantly different from start/end\n    for (const bp of best.points) {\n      if (Math.abs(bp.x - start.x) > 5 || Math.abs(bp.y - start.y) > 5) {\n        if (Math.abs(bp.x - end.x) > 5 || Math.abs(bp.y - end.y) > 5) {\n          bendPoints.push(bp);\n        }\n      }\n    }\n  }\n}\n","/**\n * Group Positioner\n * Handles repositioning of BPMN Group elements to surround their grouped elements.\n * Groups are visual overlays that don't participate in ELK layout.\n */\n\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, GroupInfo } from '../../types/internal';\nimport { GROUP_TYPE } from '../../types/bpmn-constants';\nimport { buildNodeMapWithParents } from '../../utils/node-map-builder';\n\n// Re-export GROUP_TYPE for backward compatibility\nexport { GROUP_TYPE };\n\n/**\n * Handler for group repositioning\n */\nexport class GroupPositioner {\n  /**\n   * Collect Group information for post-processing\n   * Returns a map of group ID -> { groupedElements, padding, name, parentId }\n   */\n  collectInfo(graph: ElkBpmnGraph): Map<string, GroupInfo> {\n    const info = new Map<string, GroupInfo>();\n\n    const collectFromNode = (node: NodeWithBpmn, parentId: string) => {\n      if (node.children) {\n        for (const child of node.children) {\n          const childNode = child as NodeWithBpmn;\n          if (childNode.bpmn?.type === GROUP_TYPE) {\n            const bpmn = childNode.bpmn as { groupedElements?: string[]; padding?: number; name?: string };\n            info.set(childNode.id, {\n              groupedElements: bpmn.groupedElements ?? [],\n              padding: bpmn.padding ?? 20,\n              name: bpmn.name,\n              parentId,\n            });\n          }\n          // Recurse into children\n          collectFromNode(childNode, childNode.id);\n        }\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      collectFromNode(child as NodeWithBpmn, (child as NodeWithBpmn).id);\n    }\n\n    return info;\n  }\n\n  /**\n   * Remove Groups from the graph before ELK layout\n   * Groups will be repositioned after layout based on their grouped elements\n   */\n  removeFromGraph(graph: ElkBpmnGraph, groupInfo: Map<string, GroupInfo>): void {\n    const groupIds = new Set(groupInfo.keys());\n\n    const removeFromNode = (node: NodeWithBpmn) => {\n      if (node.children) {\n        node.children = node.children.filter((child) => {\n          const childNode = child as NodeWithBpmn;\n          return !groupIds.has(childNode.id);\n        });\n\n        // Recurse into remaining children\n        for (const child of node.children) {\n          removeFromNode(child as NodeWithBpmn);\n        }\n      }\n\n      // Also remove edges that connect to groups\n      if (node.edges) {\n        node.edges = node.edges.filter((edge) => {\n          const sourceId = edge.sources[0];\n          const targetId = edge.targets[0];\n          return !groupIds.has(sourceId) && !groupIds.has(targetId);\n        });\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      removeFromNode(child as NodeWithBpmn);\n    }\n  }\n\n  /**\n   * Reposition Groups to surround their grouped elements\n   * Modifies existing Group nodes in the layouted graph\n   */\n  reposition(\n    graph: ElkNode,\n    groupInfo: Map<string, GroupInfo>,\n    _originalGraph: ElkBpmnGraph\n  ): void {\n    if (groupInfo.size === 0) return;\n\n    // Build node map for position lookups\n    const [nodeMap, parentMap] = buildNodeMapWithParents(graph);\n\n    // Process each group\n    for (const [groupId, info] of groupInfo) {\n      // Find the existing group node in the layouted graph\n      const groupNode = nodeMap.get(groupId);\n      if (!groupNode) continue;\n\n      // If no grouped elements specified, keep the ELK-calculated position\n      if (info.groupedElements.length === 0) continue;\n\n      // Calculate bounding box of grouped elements\n      let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n\n      for (const elementId of info.groupedElements) {\n        const elementNode = nodeMap.get(elementId);\n        if (!elementNode || elementNode.x === undefined || elementNode.y === undefined) continue;\n\n        // Get position of the element relative to the same parent container as the group\n        // Elements might be nested in lanes, so we need to traverse up to the group's parent\n        let absX = elementNode.x ?? 0;\n        let absY = elementNode.y ?? 0;\n        let currentParent = parentMap.get(elementId);\n        const groupParent = parentMap.get(groupId);\n\n        // Traverse up to find common ancestor or group's parent\n        while (currentParent && currentParent !== groupParent && currentParent.id !== info.parentId) {\n          absX += currentParent.x ?? 0;\n          absY += currentParent.y ?? 0;\n          currentParent = parentMap.get(currentParent.id);\n        }\n\n        const w = elementNode.width ?? 100;\n        const h = elementNode.height ?? 80;\n\n        minX = Math.min(minX, absX);\n        minY = Math.min(minY, absY);\n        maxX = Math.max(maxX, absX + w);\n        maxY = Math.max(maxY, absY + h);\n      }\n\n      // Check if we found any valid elements\n      if (minX === Infinity) continue;\n\n      // Add padding\n      const padding = info.padding;\n      minX -= padding;\n      minY -= padding;\n      maxX += padding;\n      maxY += padding;\n\n      // Update the group node's position and size\n      groupNode.x = minX;\n      groupNode.y = minY;\n      groupNode.width = maxX - minX;\n      groupNode.height = maxY - minY;\n    }\n  }\n}\n","/**\n * Lane Arranger\n * Handles rearranging lanes to stack vertically within pools.\n * Uses simple sequential stacking for lane positioning.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, Point } from '../../types/internal';\nimport { isDebugEnabled } from '../../utils/debug';\n\ntype ElkNodeWithBpmn = ElkNode & { bpmn?: NodeWithBpmn['bpmn'] };\n\n/**\n * Handler for lane rearrangement\n */\nexport class LaneArranger {\n  private readonly laneHeaderWidth = 30;\n  private readonly laneMinHorizontalPadding = 32;\n  private readonly laneMaxHorizontalPadding = 96;\n  private readonly laneMinVerticalPadding = 24;\n  private readonly laneMaxVerticalPadding = 80;\n  private readonly emptyLaneContentWidth = 220;\n  // Empty lanes should not claim node-sized vertical real estate.\n  private readonly emptyLaneMinHeight = 60;\n\n  /**\n   * Rearrange lanes within pools to stack vertically\n   */\n  rearrange(layouted: ElkNode, original: ElkBpmnGraph): void {\n    // Find pools in collaborations and process them\n    if (layouted.children) {\n      for (let i = 0; i < layouted.children.length; i++) {\n        const child = layouted.children[i];\n        const origChild = original.children?.[i] as NodeWithBpmn | undefined;\n\n        // Check if this is a collaboration with pools\n        if (origChild?.bpmn?.type === 'collaboration' && child.children) {\n          for (let j = 0; j < child.children.length; j++) {\n            const pool = child.children[j];\n            const origPool = (origChild.children as NodeWithBpmn[] | undefined)?.[j];\n            if (origPool?.bpmn?.type === 'participant') {\n              this.processPool(pool, origPool);\n            }\n          }\n        } else if (origChild?.bpmn?.type === 'participant') {\n          // Direct pool (not in collaboration)\n          this.processPool(child, origChild);\n        }\n      }\n    }\n  }\n\n  /**\n   * Process a single pool to arrange its lanes\n   */\n  private processPool(pool: ElkNode, origPool: NodeWithBpmn | undefined): void {\n    if (!pool.children || !origPool?.children) return;\n\n    // Check if this pool has lanes\n    const hasLanes = (origPool.children as NodeWithBpmn[]).some(c => c.bpmn?.type === 'lane');\n    if (!hasLanes) return;\n\n    // Get layouted nodes (flattened at pool level after ELK)\n    const layoutedNodes = new Map<string, ElkNode>();\n    let maxNodeWidth = 100;\n    for (const child of pool.children) {\n      layoutedNodes.set(child.id, child);\n      maxNodeWidth = Math.max(maxNodeWidth, child.width ?? 100);\n    }\n\n    const horizontalPadding = this.calculateHorizontalPadding(maxNodeWidth);\n\n    // Compute pool-wide global X span so all lanes share the same horizontal\n    // coordinate system. Without this, each lane recenters to its own minX\n    // and ELK's column alignment across lanes is destroyed.\n    let globalMinX = Infinity;\n    let globalMaxX = 0;\n    for (const child of pool.children) {\n      const x = child.x ?? 0;\n      const w = child.width ?? 100;\n      if (x < globalMinX) globalMinX = x;\n      if (x + w > globalMaxX) globalMaxX = x + w;\n    }\n    const contentSpan = isFinite(globalMinX) ? globalMaxX - globalMinX : 0;\n    // Top-level lane content origin equals horizontalPadding (lane-relative).\n    // Each leaf node's final lane-relative x = (origPoolX - globalMinX) + horizontalPadding.\n    const globalXOffset = isFinite(globalMinX) ? (horizontalPadding - globalMinX) : 0;\n\n    // Calculate pool width (content width + dynamic side paddings)\n    const poolContentWidth = Math.max(\n      this.emptyLaneContentWidth + horizontalPadding * 2,\n      contentSpan + horizontalPadding * 2\n    );\n\n    // Build lane structure - lanes fill the full pool width\n    const result = this.buildLaneStructure(\n      origPool.children as NodeWithBpmn[],\n      layoutedNodes,\n      0,\n      poolContentWidth,\n      horizontalPadding,\n      globalXOffset\n    );\n\n    // Update pool - lanes fill the entire pool, no gaps\n    pool.children = result.lanes;\n    pool.width = this.laneHeaderWidth + poolContentWidth;\n    pool.height = result.totalHeight;\n\n    // Recalculate edge waypoints\n    if (pool.edges) {\n      this.recalculatePoolEdges(pool, result.lanes);\n    }\n  }\n\n  /**\n   * Recursively build lane structure with positioned nodes\n   * Uses ConstraintSolver for vertical stacking\n   */\n  private buildLaneStructure(\n    origChildren: NodeWithBpmn[],\n    layoutedNodes: Map<string, ElkNode>,\n    startY: number,\n    maxRight: number,\n    horizontalPadding: number,\n    xOffset: number\n  ): { lanes: ElkNode[]; totalHeight: number } {\n    const lanes: ElkNode[] = [];\n\n    // Filter to get only lanes and sort by partition\n    const origLanes = origChildren.filter(c => c.bpmn?.type === 'lane');\n    origLanes.sort((a, b) => {\n      const partA = a.layoutOptions?.['elk.partitioning.partition'];\n      const partB = b.layoutOptions?.['elk.partitioning.partition'];\n      return (partA !== undefined ? Number(partA) : 0) - (partB !== undefined ? Number(partB) : 0);\n    });\n\n    if (origLanes.length === 0) {\n      return { lanes: [], totalHeight: 0 };\n    }\n\n    // Calculate heights for each lane\n    const laneHeights = new Map<string, number>();\n    const laneNodes = new Map<string, ElkNode[]>();\n\n    for (const origLane of origLanes) {\n      const hasNestedLanes = origLane.children?.some((c: unknown) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n\n      if (hasNestedLanes) {\n        const nestedWidth = maxRight - this.laneHeaderWidth;\n        // Nested lanes sit at x=laneHeaderWidth within their parent lane, so\n        // their inner X system is shifted by another laneHeaderWidth.\n        const nested = this.buildLaneStructure(\n          origLane.children as NodeWithBpmn[],\n          layoutedNodes,\n          0,\n          nestedWidth,\n          horizontalPadding,\n          xOffset - this.laneHeaderWidth\n        );\n        laneHeights.set(origLane.id, nested.totalHeight);\n        laneNodes.set(origLane.id, nested.lanes);\n      } else {\n        const nodesInLane: ElkNode[] = [];\n        if (origLane.children) {\n          for (const child of origLane.children) {\n            const node = layoutedNodes.get((child as NodeWithBpmn).id);\n            if (node) nodesInLane.push(node);\n          }\n        }\n\n        let minY = Infinity;\n        let maxY = 0;\n        let maxNodeHeight = 80;\n        for (const node of nodesInLane) {\n          minY = Math.min(minY, node.y ?? 0);\n          maxY = Math.max(maxY, (node.y ?? 0) + (node.height ?? 80));\n          maxNodeHeight = Math.max(maxNodeHeight, node.height ?? 80);\n        }\n\n        let laneHeight: number;\n        let yOffset = 0;\n        if (nodesInLane.length > 0) {\n          const contentHeight = maxY - minY;\n          const verticalPadding = this.calculateVerticalPadding(maxNodeHeight);\n          laneHeight = contentHeight + verticalPadding * 2;\n          yOffset = verticalPadding - minY;\n        } else {\n          // Empty lane: collapse to a slim baseline rather than reserving\n          // node-sized vertical space.\n          laneHeight = this.emptyLaneMinHeight;\n        }\n\n        // Per-lane Y offset (each lane has its own vertical baseline) but\n        // shared X offset (preserves ELK's column alignment across lanes).\n        for (const node of nodesInLane) {\n          node.x = (node.x ?? 0) + xOffset;\n          node.y = (node.y ?? 0) + yOffset;\n        }\n\n        laneHeights.set(origLane.id, laneHeight);\n        laneNodes.set(origLane.id, nodesInLane);\n      }\n    }\n\n    // Simple sequential stacking - lanes stack from startY downward\n    let currentY = startY;\n\n    // Build lane nodes with sequential positions\n    for (const origLane of origLanes) {\n      const height = laneHeights.get(origLane.id) ?? 100;\n      const children = laneNodes.get(origLane.id) ?? [];\n      const hasNestedLanes = origLane.children?.some((c: unknown) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n\n      if (hasNestedLanes) {\n        for (const nestedLane of children) {\n          nestedLane.width = maxRight - this.laneHeaderWidth;\n        }\n      }\n\n      const laneNode: ElkNodeWithBpmn = {\n        id: origLane.id,\n        x: this.laneHeaderWidth,\n        y: currentY,\n        width: maxRight,\n        height: height,\n        children: children,\n        bpmn: origLane.bpmn,\n      };\n      lanes.push(laneNode);\n      currentY += height;\n    }\n\n    const totalHeight = currentY - startY;\n    return { lanes, totalHeight };\n  }\n\n  private calculateHorizontalPadding(maxNodeWidth: number): number {\n    return this.clamp(Math.round(maxNodeWidth * 0.45), this.laneMinHorizontalPadding, this.laneMaxHorizontalPadding);\n  }\n\n  private calculateVerticalPadding(maxNodeHeight: number): number {\n    return this.clamp(Math.round(maxNodeHeight * 0.5), this.laneMinVerticalPadding, this.laneMaxVerticalPadding);\n  }\n\n  private clamp(value: number, min: number, max: number): number {\n    return Math.max(min, Math.min(max, value));\n  }\n\n\n  /**\n   * Recalculate edge waypoints after node positions have shifted (lane stacking).\n   * Produces a simple perpendicular L-shape. Obstacle avoidance is delegated to EdgeFixer.\n   */\n  private recalculatePoolEdges(pool: ElkNode, lanes: ElkNode[]): void {\n    if (!pool.edges) return;\n\n    const nodePositions = this.collectAbsoluteNodePositions(lanes);\n\n    for (const edge of pool.edges) {\n      const sourceId = edge.sources?.[0];\n      const targetId = edge.targets?.[0];\n      const src = sourceId ? nodePositions.get(sourceId) : undefined;\n      const dst = targetId ? nodePositions.get(targetId) : undefined;\n      if (!src || !dst) continue;\n\n      const waypoints = this.buildSimpleLRoute(src, dst);\n      (edge as ElkExtendedEdge & { _poolRelativeCoords?: boolean })._poolRelativeCoords = true;\n      const last = waypoints[waypoints.length - 1];\n      const first = waypoints[0];\n      if (!first || !last) continue;\n      edge.sections = [{\n        id: `${edge.id}_s0`,\n        startPoint: first,\n        endPoint: last,\n        bendPoints: waypoints.length > 2 ? waypoints.slice(1, -1) : undefined,\n      }];\n    }\n  }\n\n  /**\n   * Collect absolute (pool-relative) positions of all flow nodes inside the given lanes,\n   * recursing through nested lanes.\n   */\n  private collectAbsoluteNodePositions(\n    lanes: ElkNode[]\n  ): Map<string, { x: number; y: number; width: number; height: number }> {\n    const positions = new Map<string, { x: number; y: number; width: number; height: number }>();\n    const walk = (container: ElkNode, offsetX: number, offsetY: number) => {\n      if (!container.children) return;\n      for (const child of container.children) {\n        const absX = offsetX + (child.x ?? 0);\n        const absY = offsetY + (child.y ?? 0);\n        positions.set(child.id, {\n          x: absX,\n          y: absY,\n          width: child.width ?? 100,\n          height: child.height ?? 80,\n        });\n        walk(child, absX, absY);\n      }\n    };\n    for (const lane of lanes) {\n      walk(lane, lane.x ?? 0, lane.y ?? 0);\n    }\n    return positions;\n  }\n\n  /**\n   * Build a perpendicular L-shape route between two nodes. The shape prefers\n   * horizontal flow (right→left) when source is left of target, falling back\n   * to vertical (bottom→top) when nodes are nearly column-aligned.\n   * EdgeFixer will replace this with a pathfinding route if it crosses nodes.\n   */\n  private buildSimpleLRoute(\n    src: { x: number; y: number; width: number; height: number },\n    dst: { x: number; y: number; width: number; height: number }\n  ): Point[] {\n    const srcCx = src.x + src.width / 2;\n    const srcCy = src.y + src.height / 2;\n    const dstCx = dst.x + dst.width / 2;\n    const dstCy = dst.y + dst.height / 2;\n    const dx = dstCx - srcCx;\n    const dy = dstCy - srcCy;\n\n    // Choose horizontal-primary unless nodes are clearly stacked vertically.\n    const horizontalPrimary = Math.abs(dx) > 30 || Math.abs(dy) < 50;\n\n    let startX: number, startY: number, endX: number, endY: number;\n    if (horizontalPrimary) {\n      startY = srcCy;\n      endY = dstCy;\n      if (dx >= 0) {\n        startX = src.x + src.width;\n        endX = dst.x;\n      } else {\n        startX = src.x;\n        endX = dst.x + dst.width;\n      }\n    } else {\n      startX = srcCx;\n      endX = dstCx;\n      if (dy >= 0) {\n        startY = src.y + src.height;\n        endY = dst.y;\n      } else {\n        startY = src.y;\n        endY = dst.y + dst.height;\n      }\n    }\n\n    const points: Point[] = [{ x: startX, y: startY }];\n    if (horizontalPrimary && Math.abs(startY - endY) > 1) {\n      // Bend at midpoint of horizontal span\n      const midX = (startX + endX) / 2;\n      points.push({ x: midX, y: startY });\n      points.push({ x: midX, y: endY });\n    } else if (!horizontalPrimary && Math.abs(startX - endX) > 1) {\n      const midY = (startY + endY) / 2;\n      points.push({ x: startX, y: midY });\n      points.push({ x: endX, y: midY });\n    }\n    points.push({ x: endX, y: endY });\n    return points;\n  }\n}\n","/**\n * Constraint-based Layout Solver\n * Uses kiwi.js (Cassowary algorithm) for declarative layout constraints.\n * Replaces imperative post-processing with declarative constraint specifications.\n *\n * Note: Cassowary has specific ordering requirements:\n * - Constraints should be added before edit variables\n * - Use a two-phase approach: collect all constraints, then solve\n */\n\nimport * as kiwi from 'kiwi.js';\nimport type { Bounds } from '../../types/internal';\n\n// ============================================================================\n// Constraint Types\n// ============================================================================\n\n/**\n * Constraint type definitions for BPMN layout\n */\nexport type LayoutConstraint =\n  | AlignXConstraint\n  | AlignYConstraint\n  | LeftOfConstraint\n  | RightOfConstraint\n  | AboveConstraint\n  | BelowConstraint\n  | NoOverlapConstraint\n  | FixedPositionConstraint\n  | InContainerConstraint\n  | MinDistanceConstraint;\n\nexport interface AlignXConstraint {\n  type: 'alignX';\n  nodes: string[];\n  strength?: ConstraintStrength;\n}\n\nexport interface AlignYConstraint {\n  type: 'alignY';\n  nodes: string[];\n  strength?: ConstraintStrength;\n}\n\nexport interface LeftOfConstraint {\n  type: 'leftOf';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface RightOfConstraint {\n  type: 'rightOf';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface AboveConstraint {\n  type: 'above';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface BelowConstraint {\n  type: 'below';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface NoOverlapConstraint {\n  type: 'noOverlap';\n  nodes: [string, string];\n  margin: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface FixedPositionConstraint {\n  type: 'fixedPosition';\n  node: string;\n  x?: number;\n  y?: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface InContainerConstraint {\n  type: 'inContainer';\n  node: string;\n  container: string;\n  padding: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface MinDistanceConstraint {\n  type: 'minDistance';\n  node1: string;\n  node2: string;\n  axis: 'x' | 'y';\n  minDistance: number;\n  strength?: ConstraintStrength;\n}\n\nexport type ConstraintStrength = 'required' | 'strong' | 'medium' | 'weak';\n\n// ============================================================================\n// Node Variables\n// ============================================================================\n\ninterface NodeVariables {\n  x: kiwi.Variable;\n  y: kiwi.Variable;\n  width: number;\n  height: number;\n  initialX: number;\n  initialY: number;\n}\n\ninterface PendingConstraint {\n  constraint: LayoutConstraint;\n  strength: number;\n}\n\n// ============================================================================\n// Constraint Solver\n// ============================================================================\n\nexport interface ConstraintSolverOptions {\n  /** Default strength for constraints without explicit strength */\n  defaultStrength?: ConstraintStrength;\n  /** Enable debug logging */\n  debug?: boolean;\n}\n\nconst DEFAULT_OPTIONS: ConstraintSolverOptions = {\n  defaultStrength: 'strong',\n  debug: false,\n};\n\n/**\n * Constraint-based layout solver using Cassowary algorithm\n *\n * Usage pattern:\n * 1. Add all nodes with addNode()\n * 2. Add all constraints with addConstraint()\n * 3. Call solve() to get results\n *\n * The solver handles the correct ordering internally.\n */\nexport class ConstraintSolver {\n  private solver: kiwi.Solver | null = null;\n  private variables: Map<string, NodeVariables>;\n  private pendingConstraints: PendingConstraint[];\n  private kiwiConstraints: kiwi.Constraint[];\n  private options: ConstraintSolverOptions;\n  private solved: boolean = false;\n\n  constructor(options?: ConstraintSolverOptions) {\n    this.variables = new Map();\n    this.pendingConstraints = [];\n    this.kiwiConstraints = [];\n    this.options = { ...DEFAULT_OPTIONS, ...options };\n  }\n\n  /**\n   * Add a node to the solver\n   * Note: Nodes are stored but not added to solver until solve() is called\n   */\n  addNode(\n    id: string,\n    initialX: number,\n    initialY: number,\n    width: number,\n    height: number\n  ): void {\n    if (this.variables.has(id)) {\n      if (this.options.debug) {\n        console.log(`[Constraint] Node ${id} already exists, skipping`);\n      }\n      return;\n    }\n\n    const x = new kiwi.Variable(`${id}_x`);\n    const y = new kiwi.Variable(`${id}_y`);\n\n    // Store the node with initial values - will be added to solver in solve()\n    this.variables.set(id, { x, y, width, height, initialX, initialY });\n\n    if (this.options.debug) {\n      console.log(`[Constraint] Added node ${id} at (${initialX}, ${initialY})`);\n    }\n  }\n\n  /**\n   * Add a node from bounds\n   */\n  addNodeFromBounds(id: string, bounds: Bounds): void {\n    this.addNode(id, bounds.x, bounds.y, bounds.width, bounds.height);\n  }\n\n  /**\n   * Add multiple nodes from a map\n   */\n  addNodesFromMap(nodes: Map<string, Bounds>): void {\n    for (const [id, bounds] of nodes) {\n      this.addNodeFromBounds(id, bounds);\n    }\n  }\n\n  /**\n   * Add a constraint\n   * Note: Constraints are stored and applied when solve() is called\n   */\n  addConstraint(constraint: LayoutConstraint): boolean {\n    // Check if all referenced nodes exist\n    const nodeIds = this.getConstraintNodeIds(constraint);\n    for (const id of nodeIds) {\n      if (!this.variables.has(id)) {\n        if (this.options.debug) {\n          console.log(`[Constraint] Node ${id} not found for constraint`);\n        }\n        return false;\n      }\n    }\n\n    if (constraint.type === 'noOverlap') {\n      // NoOverlap is handled specially - it's a disjunctive constraint\n      // Cassowary doesn't directly support disjunctions\n      if (this.options.debug) {\n        console.log(`[Constraint] noOverlap constraint requires special handling`);\n      }\n      return false;\n    }\n\n    const strength = this.getStrength(constraint.strength);\n    this.pendingConstraints.push({ constraint, strength });\n    return true;\n  }\n\n  /**\n   * Get node IDs referenced by a constraint\n   */\n  private getConstraintNodeIds(constraint: LayoutConstraint): string[] {\n    switch (constraint.type) {\n      case 'alignX':\n      case 'alignY':\n        return constraint.nodes;\n      case 'leftOf':\n      case 'rightOf':\n      case 'above':\n      case 'below':\n        return [constraint.node, constraint.reference];\n      case 'fixedPosition':\n        return [constraint.node];\n      case 'inContainer':\n        return [constraint.node, constraint.container];\n      case 'minDistance':\n        return [constraint.node1, constraint.node2];\n      case 'noOverlap':\n        return constraint.nodes;\n      default:\n        return [];\n    }\n  }\n\n  /**\n   * Add multiple constraints\n   */\n  addConstraints(constraints: LayoutConstraint[]): number {\n    let successCount = 0;\n    for (const constraint of constraints) {\n      if (this.addConstraint(constraint)) {\n        successCount++;\n      }\n    }\n    return successCount;\n  }\n\n  /**\n   * Build and solve the constraint system\n   */\n  solve(): Map<string, { x: number; y: number }> {\n    if (this.solved) {\n      // Return cached results\n      const result = new Map<string, { x: number; y: number }>();\n      for (const [id, vars] of this.variables) {\n        result.set(id, {\n          x: vars.x.value(),\n          y: vars.y.value(),\n        });\n      }\n      return result;\n    }\n\n    // Create fresh solver\n    this.solver = new kiwi.Solver();\n    this.kiwiConstraints = [];\n\n    // Step 1: Add all kiwi constraints FIRST (before edit variables)\n    for (const pending of this.pendingConstraints) {\n      this.applyConstraint(pending.constraint, pending.strength);\n    }\n\n    // Step 2: Add edit variables and suggest initial values\n    for (const [_id, vars] of this.variables) {\n      this.solver.addEditVariable(vars.x, kiwi.Strength.weak);\n      this.solver.addEditVariable(vars.y, kiwi.Strength.weak);\n      this.solver.suggestValue(vars.x, vars.initialX);\n      this.solver.suggestValue(vars.y, vars.initialY);\n    }\n\n    // Step 3: Solve\n    try {\n      this.solver.updateVariables();\n      this.solved = true;\n    } catch (error) {\n      if (this.options.debug) {\n        console.error(`[Constraint] Solver failed:`, error);\n      }\n    }\n\n    const result = new Map<string, { x: number; y: number }>();\n    for (const [id, vars] of this.variables) {\n      result.set(id, {\n        x: vars.x.value(),\n        y: vars.y.value(),\n      });\n    }\n    return result;\n  }\n\n  /**\n   * Apply a constraint to the solver\n   */\n  private applyConstraint(constraint: LayoutConstraint, strength: number): boolean {\n    try {\n      switch (constraint.type) {\n        case 'alignX':\n          return this.addAlignXConstraint(constraint, strength);\n        case 'alignY':\n          return this.addAlignYConstraint(constraint, strength);\n        case 'leftOf':\n          return this.addLeftOfConstraint(constraint, strength);\n        case 'rightOf':\n          return this.addRightOfConstraint(constraint, strength);\n        case 'above':\n          return this.addAboveConstraint(constraint, strength);\n        case 'below':\n          return this.addBelowConstraint(constraint, strength);\n        case 'fixedPosition':\n          return this.addFixedPositionConstraint(constraint, strength);\n        case 'inContainer':\n          return this.addInContainerConstraint(constraint, strength);\n        case 'minDistance':\n          return this.addMinDistanceConstraint(constraint, strength);\n        default:\n          return false;\n      }\n    } catch (error) {\n      if (this.options.debug) {\n        console.error(`[Constraint] Failed to apply constraint:`, error);\n      }\n      return false;\n    }\n  }\n\n  /**\n   * Get full bounds including width and height\n   */\n  solveWithBounds(): Map<string, Bounds> {\n    const positions = this.solve();\n    const result = new Map<string, Bounds>();\n\n    for (const [id, pos] of positions) {\n      const vars = this.variables.get(id);\n      if (vars) {\n        result.set(id, {\n          x: pos.x,\n          y: pos.y,\n          width: vars.width,\n          height: vars.height,\n        });\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Clear all nodes and constraints\n   */\n  clear(): void {\n    this.solver = null;\n    this.variables.clear();\n    this.pendingConstraints = [];\n    this.kiwiConstraints = [];\n    this.solved = false;\n  }\n\n  // ============================================================================\n  // Private: Constraint Implementations\n  // ============================================================================\n\n  private addAlignXConstraint(\n    constraint: AlignXConstraint,\n    strength: number\n  ): boolean {\n    const nodes = constraint.nodes\n      .map((id) => this.variables.get(id))\n      .filter((v): v is NodeVariables => v !== undefined);\n\n    if (nodes.length < 2) return false;\n\n    // Align all X coordinates to the first node's X\n    const referenceX = nodes[0].x;\n    for (let i = 1; i < nodes.length; i++) {\n      // x[i] == x[0] => x[i] - x[0] == 0\n      // Expression: x[i] + (-1 * x[0]) + 0 == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodes[i].x, [-1, referenceX]),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  private addAlignYConstraint(\n    constraint: AlignYConstraint,\n    strength: number\n  ): boolean {\n    const nodes = constraint.nodes\n      .map((id) => this.variables.get(id))\n      .filter((v): v is NodeVariables => v !== undefined);\n\n    if (nodes.length < 2) return false;\n\n    // Align all Y coordinates to the first node's Y\n    const referenceY = nodes[0].y;\n    for (let i = 1; i < nodes.length; i++) {\n      // y[i] == y[0] => y[i] - y[0] == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodes[i].y, [-1, referenceY]),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  private addLeftOfConstraint(\n    constraint: LeftOfConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.x + node.width + minGap <= reference.x\n    // => reference.x - node.x >= node.width + minGap\n    // => reference.x - node.x - (width + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = nodeVars.width + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(refVars.x, [-1, nodeVars.x], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addRightOfConstraint(\n    constraint: RightOfConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.x >= reference.x + reference.width + minGap\n    // node.x - reference.x - (width + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = refVars.width + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.x, [-1, refVars.x], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addAboveConstraint(\n    constraint: AboveConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.y + node.height + minGap <= reference.y\n    // reference.y - node.y - (height + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = nodeVars.height + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(refVars.y, [-1, nodeVars.y], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addBelowConstraint(\n    constraint: BelowConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.y >= reference.y + reference.height + minGap\n    // node.y - reference.y - (height + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = refVars.height + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.y, [-1, refVars.y], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addFixedPositionConstraint(\n    constraint: FixedPositionConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    if (!nodeVars) return false;\n\n    if (constraint.x !== undefined) {\n      // x == fixedX => x - fixedX == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodeVars.x, -constraint.x),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    if (constraint.y !== undefined) {\n      // y == fixedY => y - fixedY == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodeVars.y, -constraint.y),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  private addInContainerConstraint(\n    constraint: InContainerConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const containerVars = this.variables.get(constraint.container);\n    if (!nodeVars || !containerVars) return false;\n\n    const padding = constraint.padding;\n\n    // node.x >= container.x + padding\n    // node.x - container.x - padding >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const leftC = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.x, [-1, containerVars.x], -padding),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(leftC);\n    this.kiwiConstraints.push(leftC);\n\n    // node.y >= container.y + padding\n    // node.y - container.y - padding >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const topC = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.y, [-1, containerVars.y], -padding),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(topC);\n    this.kiwiConstraints.push(topC);\n\n    // node.x + node.width <= container.x + container.width - padding\n    // container.x - node.x + (container.width - padding - node.width) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const rightC = new kiwi.Constraint(\n      new kiwi.Expression(\n        containerVars.x,\n        [-1, nodeVars.x],\n        containerVars.width - padding - nodeVars.width\n      ),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(rightC);\n    this.kiwiConstraints.push(rightC);\n\n    // node.y + node.height <= container.y + container.height - padding\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const bottomC = new kiwi.Constraint(\n      new kiwi.Expression(\n        containerVars.y,\n        [-1, nodeVars.y],\n        containerVars.height - padding - nodeVars.height\n      ),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(bottomC);\n    this.kiwiConstraints.push(bottomC);\n\n    return true;\n  }\n\n  private addMinDistanceConstraint(\n    constraint: MinDistanceConstraint,\n    strength: number\n  ): boolean {\n    const node1Vars = this.variables.get(constraint.node1);\n    const node2Vars = this.variables.get(constraint.node2);\n    if (!node1Vars || !node2Vars) return false;\n\n    if (constraint.axis === 'x') {\n      // |node1.x - node2.x| >= minDistance\n      // We need to handle this as: node1.x - node2.x >= minDistance OR node2.x - node1.x >= minDistance\n      // Cassowary can't handle OR, so we use a soft constraint that prefers separation\n      // This is a simplification - in practice, we rely on other constraints to maintain order\n\n      // Use a weaker constraint: prefer node2.x > node1.x + width + minDistance\n      // node2.x - node1.x - (width + minDistance) >= 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const size = node1Vars.width;\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(\n          node2Vars.x,\n          [-1, node1Vars.x],\n          -(size + constraint.minDistance)\n        ),\n        kiwi.Operator.Ge,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    } else {\n      // node2.y - node1.y - (height + minDistance) >= 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const size = node1Vars.height;\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(\n          node2Vars.y,\n          [-1, node1Vars.y],\n          -(size + constraint.minDistance)\n        ),\n        kiwi.Operator.Ge,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  // ============================================================================\n  // Private: Helpers\n  // ============================================================================\n\n  private getStrength(strength?: ConstraintStrength): number {\n    const s = strength ?? this.options.defaultStrength ?? 'strong';\n    switch (s) {\n      case 'required':\n        return kiwi.Strength.required;\n      case 'strong':\n        return kiwi.Strength.strong;\n      case 'medium':\n        return kiwi.Strength.medium;\n      case 'weak':\n        return kiwi.Strength.weak;\n      default:\n        return kiwi.Strength.strong;\n    }\n  }\n}\n\n// ============================================================================\n// BPMN Constraint Generator\n// ============================================================================\n\nexport interface BpmnConstraintGeneratorOptions {\n  /** Minimum horizontal gap between nodes */\n  horizontalGap: number;\n  /** Minimum vertical gap between nodes */\n  verticalGap: number;\n  /** Gap between boundary event targets and their parent */\n  boundaryEventGap: number;\n  /** Padding inside containers */\n  containerPadding: number;\n}\n\nconst DEFAULT_BPMN_OPTIONS: BpmnConstraintGeneratorOptions = {\n  horizontalGap: 50,\n  verticalGap: 40,\n  boundaryEventGap: 50,\n  containerPadding: 20,\n};\n\n/**\n * Generate BPMN-specific layout constraints\n */\nexport function generateBpmnConstraints(\n  nodes: Map<string, Bounds>,\n  edges: Array<{ source: string; target: string; type?: string }>,\n  boundaryEvents: Array<{ id: string; attachedToRef: string; targetId?: string }>,\n  lanes: Array<{ id: string; parentId: string }>,\n  options?: Partial<BpmnConstraintGeneratorOptions>\n): LayoutConstraint[] {\n  const opts = { ...DEFAULT_BPMN_OPTIONS, ...options };\n  const constraints: LayoutConstraint[] = [];\n\n  // 1. Sequence flow direction constraints (source left of target)\n  for (const edge of edges) {\n    if (edge.type === 'sequenceFlow' || !edge.type) {\n      if (nodes.has(edge.source) && nodes.has(edge.target)) {\n        constraints.push({\n          type: 'leftOf',\n          node: edge.source,\n          reference: edge.target,\n          minGap: opts.horizontalGap,\n          strength: 'strong',\n        });\n      }\n    }\n  }\n\n  // 2. Boundary event targets below their attached tasks\n  for (const be of boundaryEvents) {\n    if (be.targetId && nodes.has(be.attachedToRef) && nodes.has(be.targetId)) {\n      constraints.push({\n        type: 'below',\n        node: be.targetId,\n        reference: be.attachedToRef,\n        minGap: opts.boundaryEventGap,\n        strength: 'required',\n      });\n    }\n  }\n\n  // 3. Lanes stacked vertically\n  const lanesByParent = new Map<string, string[]>();\n  for (const lane of lanes) {\n    const parentLanes = lanesByParent.get(lane.parentId) || [];\n    parentLanes.push(lane.id);\n    lanesByParent.set(lane.parentId, parentLanes);\n  }\n\n  for (const [_parentId, laneIds] of lanesByParent) {\n    for (let i = 1; i < laneIds.length; i++) {\n      if (nodes.has(laneIds[i - 1]) && nodes.has(laneIds[i])) {\n        constraints.push({\n          type: 'below',\n          node: laneIds[i],\n          reference: laneIds[i - 1],\n          minGap: 0,\n          strength: 'required',\n        });\n      }\n    }\n  }\n\n  return constraints;\n}\n","/**\n * Pool Arranger\n * Handles rearranging pools (participants) within collaborations.\n * Uses ConstraintSolver for vertical stacking calculations.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, Point, Bounds, ArtifactInfo } from '../../types/internal';\nimport { ARTIFACT_TYPES } from './artifact-positioner';\nimport { ConstraintSolver } from '../constraint';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Handler for pool arrangement\n */\nexport class PoolArranger {\n  private readonly poolHeaderWidth = 55;\n  private readonly poolPaddingX = 25;\n  private readonly poolPaddingY = 40;\n  private readonly minPoolHeight = 100;\n  private readonly maxPoolPaddingX = 120;\n  private readonly maxPoolPaddingY = 90;\n\n  /**\n   * Rearrange pools within collaborations\n   */\n  rearrange(layouted: ElkNode, original: ElkBpmnGraph): void {\n    if (!layouted.children) return;\n\n    for (let i = 0; i < layouted.children.length; i++) {\n      const child = layouted.children[i];\n      const origChild = original.children?.[i] as NodeWithBpmn | undefined;\n\n      // Check if this is a collaboration\n      if (origChild?.bpmn?.type === 'collaboration' && child.children && child.children.length > 0) {\n        // Check if this collaboration had cross-pool edges (nodes were flattened)\n        const hasCrossPoolEdges = origChild.edges && origChild.edges.length > 0;\n        const hasMultiplePools = ((origChild.children as NodeWithBpmn[] | undefined)?.filter(\n          c => c.bpmn?.type === 'participant'\n        ).length ?? 0) > 1;\n\n        // Check if children were flattened\n        const origPools = (origChild.children as NodeWithBpmn[] | undefined)?.filter(\n          c => c.bpmn?.type === 'participant'\n        ) ?? [];\n        const poolIdsInLayouted = new Set(child.children.map(c => c.id));\n        const poolsFoundInLayouted = origPools.filter(p => poolIdsInLayouted.has(p.id)).length;\n        const childrenAreFlattened = poolsFoundInLayouted < origPools.length / 2;\n\n        if (hasCrossPoolEdges && hasMultiplePools && childrenAreFlattened) {\n          this.rearrangeCollaborationWithCrossPoolEdges(child, origChild);\n        } else {\n          this.stackPoolsVertically(child, origChild);\n        }\n      }\n    }\n  }\n\n  /**\n   * Stack pools vertically within a collaboration\n   */\n  private stackPoolsVertically(collab: ElkNode, origCollab: NodeWithBpmn): void {\n    if (!collab.children || collab.children.length === 0) return;\n\n    const pools: ElkNode[] = [];\n    const origPoolMap = new Map<string, NodeWithBpmn>();\n\n    // Collect pools and build original pool map\n    for (const child of collab.children) {\n      const origPool = origCollab.children?.find((c: unknown) => (c as NodeWithBpmn).id === child.id) as NodeWithBpmn | undefined;\n      if (origPool?.bpmn?.type === 'participant') {\n        pools.push(child);\n        origPoolMap.set(child.id, origPool);\n      }\n    }\n\n    if (pools.length === 0) return;\n\n    // Sort pools by original order\n    const poolOrder = new Map<string, number>();\n    origCollab.children?.forEach((c: unknown, idx: number) => {\n      const node = c as NodeWithBpmn;\n      if (node.bpmn?.type === 'participant') {\n        poolOrder.set(node.id, idx);\n      }\n    });\n    pools.sort((a, b) => (poolOrder.get(a.id) ?? 0) - (poolOrder.get(b.id) ?? 0));\n\n    const poolTargetWidths = new Map<string, number>();\n    const poolPaddingById = new Map<string, { x: number; y: number }>();\n\n    // Calculate target widths before normalizing pools to the same width\n    let maxPoolWidth = 0;\n    for (const pool of pools) {\n      const origPool = origPoolMap.get(pool.id);\n      const isBlackBox = origPool?.bpmn?.isBlackBox === true;\n      const hasLanes = (origPool?.children as NodeWithBpmn[] | undefined)?.some(c => c.bpmn?.type === 'lane');\n      const currentWidth = pool.width ?? 680;\n\n      if (hasLanes || isBlackBox) {\n        poolTargetWidths.set(pool.id, currentWidth);\n        maxPoolWidth = Math.max(maxPoolWidth, currentWidth);\n      } else {\n        const padding = this.calculateDynamicPoolPadding(pool);\n        const targetWidth = currentWidth + padding.x * 2;\n        poolPaddingById.set(pool.id, padding);\n        poolTargetWidths.set(pool.id, targetWidth);\n        maxPoolWidth = Math.max(maxPoolWidth, targetWidth);\n      }\n    }\n\n    // Calculate heights and prepare pools\n    const poolHeights = new Map<string, number>();\n    for (const pool of pools) {\n      const origPool = origPoolMap.get(pool.id);\n      // Treat empty pools (no children) as black box so they collapse to a\n      // narrow strip instead of inheriting a node-sized default height.\n      const isBlackBox = origPool?.bpmn?.isBlackBox === true ||\n        !((origPool?.children as NodeWithBpmn[] | undefined)?.length);\n      const hasLanes = (origPool?.children as NodeWithBpmn[] | undefined)?.some(c => c.bpmn?.type === 'lane');\n      const originalTargetWidth = poolTargetWidths.get(pool.id) ?? (pool.width ?? 680);\n\n      pool.width = maxPoolWidth;\n      if (isBlackBox) {\n        pool.height = 60;\n      } else if (!hasLanes) {\n        const padding = poolPaddingById.get(pool.id) ?? this.calculateDynamicPoolPadding(pool);\n        const centeredOffsetX = Math.max(0, Math.round((maxPoolWidth - originalTargetWidth) / 2));\n        const offsetX = padding.x + centeredOffsetX;\n        const offsetY = padding.y;\n\n        pool.height = (pool.height ?? 200) + offsetY * 2;\n        this.offsetPoolChildren(pool, offsetX, offsetY);\n      }\n      poolHeights.set(pool.id, pool.height ?? 200);\n    }\n\n    // Use ConstraintSolver for vertical stacking\n    const solver = new ConstraintSolver();\n    for (const pool of pools) {\n      const height = poolHeights.get(pool.id) ?? 200;\n      solver.addNode(pool.id, 0, 0, maxPoolWidth, height);\n    }\n\n    // Add below constraints for sequential stacking\n    for (let i = 1; i < pools.length; i++) {\n      solver.addConstraint({\n        type: 'below',\n        node: pools[i].id,\n        reference: pools[i - 1].id,\n        minGap: 0,\n        strength: 'required',\n      });\n    }\n\n    const positions = solver.solve();\n    const nodePositions = new Map<string, Bounds>();\n\n    // Apply solved positions\n    let totalHeight = 0;\n    for (const pool of pools) {\n      const pos = positions.get(pool.id);\n      pool.x = 0;\n      pool.y = pos?.y ?? totalHeight;\n\n      nodePositions.set(pool.id, {\n        x: pool.x,\n        y: pool.y,\n        width: pool.width ?? 680,\n        height: pool.height ?? 200,\n      });\n\n      this.collectNodePositionsInPool(pool, pool.x, pool.y, nodePositions);\n      totalHeight = pool.y + (pool.height ?? 200);\n    }\n\n    // Update collaboration dimensions\n    collab.width = maxPoolWidth;\n    collab.height = totalHeight;\n\n    // Recalculate message flows\n    if (collab.edges && origCollab.edges) {\n      this.recalculateMessageFlows(collab.edges, nodePositions, pools, origCollab.edges);\n    }\n  }\n\n  /**\n   * Rearrange collaboration with cross-pool edges\n   */\n  private rearrangeCollaborationWithCrossPoolEdges(\n    collab: ElkNode,\n    origCollab: NodeWithBpmn\n  ): void {\n    if (!collab.children || !origCollab.children) return;\n\n    // Build map of node ID -> pool ID and identify artifacts\n    const nodeToPool = new Map<string, string>();\n    const artifactIds = new Set<string>();\n\n    for (const origPool of origCollab.children as NodeWithBpmn[]) {\n      if (origPool.bpmn?.type === 'participant' && origPool.children) {\n        const hasLanes = origPool.children.some((c: unknown) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n        if (hasLanes) {\n          const mapNodesInLanes = (children: NodeWithBpmn[]) => {\n            for (const child of children) {\n              if (child.bpmn?.type === 'lane') {\n                if (child.children) mapNodesInLanes(child.children as NodeWithBpmn[]);\n              } else {\n                nodeToPool.set(child.id, origPool.id);\n                if (ARTIFACT_TYPES.has(child.bpmn?.type)) {\n                  artifactIds.add(child.id);\n                }\n              }\n            }\n          };\n          mapNodesInLanes(origPool.children as NodeWithBpmn[]);\n        } else {\n          for (const child of origPool.children) {\n            const childNode = child as NodeWithBpmn;\n            nodeToPool.set(childNode.id, origPool.id);\n            if (ARTIFACT_TYPES.has(childNode.bpmn?.type)) {\n              artifactIds.add(childNode.id);\n            }\n          }\n        }\n      }\n    }\n\n    // Get layouted nodes\n    const layoutedNodes = new Map<string, ElkNode>();\n    for (const child of collab.children) {\n      layoutedNodes.set(child.id, child);\n    }\n\n    // Group nodes by pool and calculate X bounds\n    const poolNodesMap = new Map<string, ElkNode[]>();\n    const poolXBounds = new Map<string, { minX: number; maxX: number }>();\n    let globalMinX = Infinity;\n\n    for (const [nodeId, poolId] of nodeToPool) {\n      const node = layoutedNodes.get(nodeId);\n      if (!node) continue;\n\n      if (!poolNodesMap.has(poolId)) {\n        poolNodesMap.set(poolId, []);\n      }\n      poolNodesMap.get(poolId)!.push(node);\n\n      if (!artifactIds.has(nodeId)) {\n        const x = node.x ?? 0;\n        const w = node.width ?? 100;\n        const bounds = poolXBounds.get(poolId) ?? { minX: Infinity, maxX: 0 };\n        bounds.minX = Math.min(bounds.minX, x);\n        bounds.maxX = Math.max(bounds.maxX, x + w);\n        poolXBounds.set(poolId, bounds);\n        globalMinX = Math.min(globalMinX, x);\n      }\n    }\n\n    // Sort pools by original order\n    const origPools = (origCollab.children as NodeWithBpmn[]).filter(c => c.bpmn?.type === 'participant');\n    origPools.sort((a, b) => {\n      const partA = a.layoutOptions?.['elk.partitioning.partition'];\n      const partB = b.layoutOptions?.['elk.partitioning.partition'];\n      if (partA !== undefined && partB !== undefined) {\n        return Number(partA) - Number(partB);\n      }\n      return 0;\n    });\n\n    // Calculate max content width\n    let globalMaxX = 0;\n    for (const bounds of poolXBounds.values()) {\n      globalMaxX = Math.max(globalMaxX, bounds.maxX);\n    }\n    const maxContentWidth = globalMaxX - globalMinX;\n    const poolWidth = this.poolHeaderWidth + maxContentWidth + this.poolPaddingX * 2;\n\n    // Build pool structures\n    const pools: ElkNode[] = [];\n    let currentY = 0;\n\n    for (const origPool of origPools) {\n      const poolNodes = poolNodesMap.get(origPool.id) ?? [];\n      const isBlackBox = origPool.bpmn?.isBlackBox === true || !origPool.children?.length;\n\n      if (isBlackBox) {\n        pools.push({\n          id: origPool.id,\n          x: 0,\n          y: currentY,\n          width: poolWidth,\n          height: 60,\n          children: [],\n        });\n        currentY += 60;\n      } else {\n        const regularNodes = poolNodes.filter(n => !artifactIds.has(n.id));\n        const artifactNodes = poolNodes.filter(n => artifactIds.has(n.id));\n\n        let maxNodeHeight = 0;\n        for (const node of regularNodes) {\n          maxNodeHeight = Math.max(maxNodeHeight, node.height ?? 80);\n        }\n        const poolHeight = Math.max(this.minPoolHeight, maxNodeHeight + this.poolPaddingY * 2);\n\n        const adjustedNodes: ElkNode[] = [];\n        for (const node of regularNodes) {\n          const nodeHeight = node.height ?? 80;\n          const newY = (poolHeight - nodeHeight) / 2;\n          const newX = this.poolHeaderWidth + (node.x ?? 0) - globalMinX + this.poolPaddingX;\n\n          adjustedNodes.push({\n            ...node,\n            x: newX,\n            y: newY,\n          });\n        }\n\n        // Position artifacts\n        for (const artifact of artifactNodes) {\n          const { task: associatedTask, isInput } = this.findArtifactAssociatedTask(\n            artifact.id,\n            origCollab.edges ?? [],\n            adjustedNodes\n          );\n\n          if (associatedTask) {\n            const artifactWidth = artifact.width ?? 36;\n            const artifactHeight = artifact.height ?? 50;\n            const taskX = associatedTask.x ?? 0;\n            const taskY = associatedTask.y ?? 0;\n            const taskWidth = associatedTask.width ?? 100;\n            const taskHeight = associatedTask.height ?? 80;\n\n            const newX = taskX + taskWidth + 15;\n            const newY = taskY + (taskHeight - artifactHeight) / 2;\n\n            adjustedNodes.push({\n              ...artifact,\n              x: newX,\n              y: Math.max(5, newY),\n            });\n          } else {\n            const newX = this.poolHeaderWidth + (artifact.x ?? 0) - globalMinX + this.poolPaddingX;\n            const artifactHeight = artifact.height ?? 50;\n            const newY = (poolHeight - artifactHeight) / 2;\n\n            adjustedNodes.push({\n              ...artifact,\n              x: newX,\n              y: newY,\n            });\n          }\n        }\n\n        pools.push({\n          id: origPool.id,\n          x: 0,\n          y: currentY,\n          width: poolWidth,\n          height: poolHeight,\n          children: adjustedNodes,\n        });\n        currentY += poolHeight;\n      }\n    }\n\n    // Update collaboration\n    collab.children = pools;\n    collab.width = poolWidth;\n    collab.height = currentY;\n\n    // Recalculate edges\n    if (collab.edges) {\n      const nodePositions = new Map<string, Bounds>();\n\n      for (const pool of pools) {\n        const poolX = pool.x ?? 0;\n        const poolY = pool.y ?? 0;\n\n        nodePositions.set(pool.id, {\n          x: poolX,\n          y: poolY,\n          width: pool.width ?? 680,\n          height: pool.height ?? 200,\n        });\n\n        if (pool.children) {\n          for (const child of pool.children) {\n            nodePositions.set(child.id, {\n              x: poolX + (child.x ?? 0),\n              y: poolY + (child.y ?? 0),\n              width: child.width ?? 100,\n              height: child.height ?? 80,\n            });\n          }\n        }\n      }\n\n      this.recalculateMessageFlows(collab.edges, nodePositions, pools, origCollab.edges);\n    }\n  }\n\n  private calculateDynamicPoolPadding(pool: ElkNode): { x: number; y: number } {\n    let maxNodeWidth = 100;\n    let maxNodeHeight = 80;\n\n    if (pool.children) {\n      for (const child of pool.children) {\n        maxNodeWidth = Math.max(maxNodeWidth, child.width ?? 100);\n        maxNodeHeight = Math.max(maxNodeHeight, child.height ?? 80);\n      }\n    }\n\n    const x = this.clamp(Math.round(maxNodeWidth * 0.45), this.poolPaddingX, this.maxPoolPaddingX);\n    const y = this.clamp(Math.round(maxNodeHeight * 0.45), this.poolPaddingY / 2, this.maxPoolPaddingY);\n\n    return { x, y };\n  }\n\n  private clamp(value: number, min: number, max: number): number {\n    return Math.max(min, Math.min(max, value));\n  }\n\n  /**\n   * Offset all children within a pool\n   */\n  private offsetPoolChildren(pool: ElkNode, offsetX: number, offsetY: number): void {\n    if (!pool.children) return;\n\n    for (const child of pool.children) {\n      if (child.x !== undefined) {\n        child.x += offsetX;\n      }\n      if (child.y !== undefined) {\n        child.y += offsetY;\n      }\n      this.offsetPoolChildren(child, 0, 0);\n    }\n\n    if (pool.edges) {\n      for (const edge of pool.edges) {\n        if (edge.sections) {\n          for (const section of edge.sections) {\n            if (section.startPoint) {\n              section.startPoint.x += offsetX;\n              section.startPoint.y += offsetY;\n            }\n            if (section.endPoint) {\n              section.endPoint.x += offsetX;\n              section.endPoint.y += offsetY;\n            }\n            if (section.bendPoints) {\n              for (const bp of section.bendPoints) {\n                bp.x += offsetX;\n                bp.y += offsetY;\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Collect node positions within a pool\n   */\n  private collectNodePositionsInPool(\n    container: ElkNode,\n    offsetX: number,\n    offsetY: number,\n    positions: Map<string, Bounds>\n  ): void {\n    if (!container.children) return;\n\n    for (const child of container.children) {\n      const absX = offsetX + (child.x ?? 0);\n      const absY = offsetY + (child.y ?? 0);\n\n      positions.set(child.id, {\n        x: absX,\n        y: absY,\n        width: child.width ?? 100,\n        height: child.height ?? 80,\n      });\n\n      this.collectNodePositionsInPool(child, absX, absY, positions);\n    }\n  }\n\n  /**\n   * Recalculate message flows after pools have been repositioned\n   */\n  private recalculateMessageFlows(\n    edges: ElkExtendedEdge[],\n    nodePositions: Map<string, Bounds>,\n    pools: ElkNode[],\n    originalEdges?: Array<{ id: string; sources: string[]; targets: string[]; bpmn?: { type?: string } }>\n  ): void {\n    const edgeTypeMap = new Map<string, string>();\n    if (originalEdges) {\n      for (const origEdge of originalEdges) {\n        if (origEdge.bpmn?.type) {\n          edgeTypeMap.set(origEdge.id, origEdge.bpmn.type);\n        }\n      }\n    }\n\n    // Identify blackbox pools (pools with no children or very small height)\n    const blackboxPoolIds = new Set<string>();\n    for (const pool of pools) {\n      const isBlackbox = !pool.children || pool.children.length === 0 || (pool.height ?? 0) <= 80;\n      if (isBlackbox) {\n        blackboxPoolIds.add(pool.id);\n      }\n    }\n\n    for (const edge of edges) {\n      const sourceId = edge.sources?.[0];\n      const targetId = edge.targets?.[0];\n      const edgeType = edgeTypeMap.get(edge.id) ?? (edge as { bpmn?: { type?: string } }).bpmn?.type;\n\n      const sourcePos = sourceId ? nodePositions.get(sourceId) : undefined;\n      const targetPos = targetId ? nodePositions.get(targetId) : undefined;\n\n      if (!sourcePos || !targetPos) continue;\n\n      const isSequenceFlow = edgeType === 'sequenceFlow';\n      const isMessageFlow = edgeType === 'messageFlow';\n      const isDataAssociation = edgeType === 'dataInputAssociation' || edgeType === 'dataOutputAssociation';\n\n      const waypoints: Point[] = [];\n\n      if (isSequenceFlow) {\n        this.createSequenceFlowWaypoints(sourcePos, targetPos, waypoints);\n      } else if (isMessageFlow) {\n        this.createMessageFlowWaypoints(sourcePos, targetPos, waypoints, nodePositions, targetId, sourceId, blackboxPoolIds);\n      } else if (isDataAssociation) {\n        (edge as ElkExtendedEdge & { _absoluteCoords?: boolean })._absoluteCoords = true;\n        edge.sections = [];\n        continue;\n      } else {\n        this.createSequenceFlowWaypoints(sourcePos, targetPos, waypoints);\n      }\n\n      (edge as ElkExtendedEdge & { _absoluteCoords?: boolean })._absoluteCoords = true;\n      edge.sections = [{\n        id: `${edge.id}_s0`,\n        startPoint: waypoints[0],\n        endPoint: waypoints[waypoints.length - 1],\n        bendPoints: waypoints.length > 2 ? waypoints.slice(1, -1) : undefined,\n      }];\n\n      // Update label positions\n      if (edge.labels && edge.labels.length > 0) {\n        const midIdx = Math.floor(waypoints.length / 2);\n        const labelPoint = waypoints[midIdx] ?? waypoints[0];\n        for (const label of edge.labels) {\n          const labelWidth = label.width ?? 50;\n          const labelHeight = label.height ?? 14;\n          label.x = labelPoint.x - labelWidth / 2;\n          label.y = labelPoint.y - labelHeight - 5;\n        }\n      }\n    }\n  }\n\n  /**\n   * Create waypoints for sequence flows\n   */\n  private createSequenceFlowWaypoints(\n    sourcePos: Bounds,\n    targetPos: Bounds,\n    waypoints: Point[]\n  ): void {\n    const sourceCenterX = sourcePos.x + sourcePos.width / 2;\n    const sourceCenterY = sourcePos.y + sourcePos.height / 2;\n    const targetCenterX = targetPos.x + targetPos.width / 2;\n    const targetCenterY = targetPos.y + targetPos.height / 2;\n\n    const goingRight = targetCenterX > sourceCenterX;\n    const goingDown = targetCenterY > sourceCenterY + 30;\n    const goingUp = targetCenterY < sourceCenterY - 30;\n    const sameLevel = !goingDown && !goingUp;\n\n    if (goingRight) {\n      if (sameLevel) {\n        const startX = sourcePos.x + sourcePos.width;\n        const startY = sourceCenterY;\n        const endX = targetPos.x;\n        const endY = targetCenterY;\n\n        waypoints.push({ x: startX, y: startY });\n        if (Math.abs(startY - endY) > 10) {\n          const midX = (startX + endX) / 2;\n          waypoints.push({ x: midX, y: startY });\n          waypoints.push({ x: midX, y: endY });\n        }\n        waypoints.push({ x: endX, y: endY });\n      } else if (goingDown) {\n        const startX = sourceCenterX;\n        const startY = sourcePos.y + sourcePos.height;\n        const endX = targetPos.x;\n        const endY = targetCenterY;\n\n        waypoints.push({ x: startX, y: startY });\n        waypoints.push({ x: startX, y: endY });\n        waypoints.push({ x: endX, y: endY });\n      } else {\n        const startX = sourceCenterX;\n        const startY = sourcePos.y;\n        const endX = targetPos.x;\n        const endY = targetCenterY;\n\n        waypoints.push({ x: startX, y: startY });\n        waypoints.push({ x: startX, y: endY });\n        waypoints.push({ x: endX, y: endY });\n      }\n    } else {\n      const startX = sourcePos.x;\n      const startY = sourceCenterY;\n      const endX = targetPos.x + targetPos.width;\n      const endY = targetCenterY;\n\n      waypoints.push({ x: startX, y: startY });\n\n      const loopY = Math.max(sourcePos.y + sourcePos.height, targetPos.y + targetPos.height) + 30;\n      waypoints.push({ x: startX, y: loopY });\n      waypoints.push({ x: endX, y: loopY });\n\n      waypoints.push({ x: endX, y: endY });\n    }\n  }\n\n  /**\n   * Create waypoints for message flows\n   * Routes message flows to avoid being too close to other nodes in the target pool\n   */\n  private createMessageFlowWaypoints(\n    sourcePos: Bounds,\n    targetPos: Bounds,\n    waypoints: Point[],\n    nodePositions: Map<string, Bounds>,\n    targetId?: string,\n    sourceId?: string,\n    blackboxPoolIds?: Set<string>\n  ): void {\n    let startX: number, startY: number, endX: number, endY: number;\n\n    const goingDown = sourcePos.y + sourcePos.height < targetPos.y;\n\n    // Check if target/source is a blackbox participant using the passed set\n    const isTargetBlackbox = targetId ? blackboxPoolIds?.has(targetId) ?? false : false;\n    const isSourceBlackbox = sourceId ? blackboxPoolIds?.has(sourceId) ?? false : false;\n\n    if (goingDown) {\n      startX = sourcePos.x + sourcePos.width / 2;\n      startY = sourcePos.y + sourcePos.height;\n\n      // For blackbox targets, prefer connecting directly below the source if within target's X range\n      if (isTargetBlackbox) {\n        const targetLeft = targetPos.x;\n        const targetRight = targetPos.x + targetPos.width;\n        // Use source's X if it falls within target's range (with some margin)\n        if (startX >= targetLeft + 20 && startX <= targetRight - 20) {\n          endX = startX;\n        } else {\n          endX = targetPos.x + targetPos.width / 2;\n        }\n      } else {\n        endX = targetPos.x + targetPos.width / 2;\n      }\n      endY = targetPos.y;\n    } else {\n      startX = sourcePos.x + sourcePos.width / 2;\n      startY = sourcePos.y;\n\n      // For blackbox targets, prefer connecting directly above the source if within target's X range\n      if (isTargetBlackbox) {\n        const targetLeft = targetPos.x;\n        const targetRight = targetPos.x + targetPos.width;\n        if (startX >= targetLeft + 20 && startX <= targetRight - 20) {\n          endX = startX;\n        } else {\n          endX = targetPos.x + targetPos.width / 2;\n        }\n      } else {\n        endX = targetPos.x + targetPos.width / 2;\n      }\n      endY = targetPos.y + targetPos.height;\n    }\n\n    // Similarly, for blackbox sources, adjust startX to align with endX if possible\n    if (isSourceBlackbox) {\n      const sourceLeft = sourcePos.x;\n      const sourceRight = sourcePos.x + sourcePos.width;\n      if (endX >= sourceLeft + 20 && endX <= sourceRight - 20) {\n        startX = endX;\n      }\n    }\n\n    // Patterns to identify containers (pools, lanes, etc.) vs flow nodes\n    const containerPatterns = [/^pool_/, /^participant_/, /^lane_/, /^process_/, /^collaboration_/];\n    const minClearance = 25; // Minimum distance to keep from nodes\n\n    // Calculate the Y range of source and target pools (approximate)\n    const sourcePoolYMin = sourcePos.y - 50;\n    const sourcePoolYMax = sourcePos.y + sourcePos.height + 50;\n    const targetPoolYMin = targetPos.y - 50;\n    const targetPoolYMax = targetPos.y + targetPos.height + 50;\n\n    // First, check if a straight vertical line from startX would hit any obstacles\n    // This applies to ALL message flows, not just those with horizontal distance\n    const fullVerticalMinY = Math.min(startY, endY);\n    const fullVerticalMaxY = Math.max(startY, endY);\n\n    // Collect all nodes that would block a straight vertical path at startX\n    const nodesBlockingDirectPath: Array<{ id: string; bounds: Bounds }> = [];\n    for (const [nodeId, bounds] of nodePositions) {\n      if (nodeId === targetId || nodeId === sourceId) continue;\n\n      // Skip container nodes\n      const isContainer = containerPatterns.some(pattern => pattern.test(nodeId));\n      if (isContainer) continue;\n\n      const nodeLeft = bounds.x;\n      const nodeRight = bounds.x + bounds.width;\n      const nodeTop = bounds.y;\n      const nodeBottom = bounds.y + bounds.height;\n\n      // Skip nodes in source/target pool\n      const inSourcePool = nodeTop >= sourcePoolYMin && nodeBottom <= sourcePoolYMax;\n      const inTargetPool = nodeTop >= targetPoolYMin && nodeBottom <= targetPoolYMax;\n      if (inSourcePool || inTargetPool) continue;\n\n      // Check if node blocks the vertical line at startX\n      const overlapsVerticalLine = startX >= nodeLeft - minClearance && startX <= nodeRight + minClearance;\n      const nodeInVerticalRange = nodeBottom > fullVerticalMinY && nodeTop < fullVerticalMaxY;\n\n      if (overlapsVerticalLine && nodeInVerticalRange) {\n        nodesBlockingDirectPath.push({ id: nodeId, bounds });\n      }\n    }\n\n    // If there are obstacles in the direct path, we need to find a clear route\n    let finalRouteX = startX;\n    if (nodesBlockingDirectPath.length > 0) {\n      // Find a clear X position that avoids ALL obstacles in the vertical path\n      // Try both left and right directions and pick the one with smaller shift\n\n      // Collect all obstacle X ranges\n      const allObstacles: Array<{ left: number; right: number }> = [];\n      for (const { bounds } of nodesBlockingDirectPath) {\n        allObstacles.push({\n          left: bounds.x - minClearance,\n          right: bounds.x + bounds.width + minClearance,\n        });\n      }\n\n      // Also check for other nodes that might be in the way at potential route positions\n      // We need to find a gap that's clear all the way down\n      for (const [nodeId, bounds] of nodePositions) {\n        if (nodeId === targetId || nodeId === sourceId) continue;\n        const isContainer = containerPatterns.some(pattern => pattern.test(nodeId));\n        if (isContainer) continue;\n\n        const nodeTop = bounds.y;\n        const nodeBottom = bounds.y + bounds.height;\n        const inSourcePool = nodeTop >= sourcePoolYMin && nodeBottom <= sourcePoolYMax;\n        const inTargetPool = nodeTop >= targetPoolYMin && nodeBottom <= targetPoolYMax;\n        if (inSourcePool || inTargetPool) continue;\n\n        const nodeInVerticalRange = nodeBottom > fullVerticalMinY && nodeTop < fullVerticalMaxY;\n        if (nodeInVerticalRange) {\n          allObstacles.push({\n            left: bounds.x - minClearance,\n            right: bounds.x + bounds.width + minClearance,\n          });\n        }\n      }\n\n      // Sort obstacles by left edge\n      allObstacles.sort((a, b) => a.left - b.left);\n\n      // Merge overlapping obstacles\n      const mergedObstacles: Array<{ left: number; right: number }> = [];\n      for (const obs of allObstacles) {\n        if (mergedObstacles.length === 0) {\n          mergedObstacles.push({ ...obs });\n        } else {\n          const last = mergedObstacles[mergedObstacles.length - 1];\n          if (obs.left <= last.right) {\n            last.right = Math.max(last.right, obs.right);\n          } else {\n            mergedObstacles.push({ ...obs });\n          }\n        }\n      }\n\n      // Find the best route X - either to the left of all obstacles or to the right\n      // or in a gap between obstacles\n      let bestRouteX = startX;\n      let bestShift = Infinity;\n\n      // Option 1: Go to the left of all obstacles\n      if (mergedObstacles.length > 0) {\n        const leftMost = mergedObstacles[0].left;\n        if (leftMost > 20) { // Make sure we don't go off the diagram\n          const shiftNeeded = Math.abs(startX - leftMost);\n          if (shiftNeeded < bestShift) {\n            bestShift = shiftNeeded;\n            bestRouteX = leftMost;\n          }\n        }\n      }\n\n      // Option 2: Go to the right of all obstacles\n      if (mergedObstacles.length > 0) {\n        const rightMost = mergedObstacles[mergedObstacles.length - 1].right;\n        const shiftNeeded = Math.abs(startX - rightMost);\n        if (shiftNeeded < bestShift) {\n          bestShift = shiftNeeded;\n          bestRouteX = rightMost;\n        }\n      }\n\n      // Option 3: Find a gap between obstacles that's close to startX\n      for (let i = 0; i < mergedObstacles.length - 1; i++) {\n        const gapLeft = mergedObstacles[i].right;\n        const gapRight = mergedObstacles[i + 1].left;\n        const gapWidth = gapRight - gapLeft;\n\n        if (gapWidth >= 10) { // Minimum gap width\n          const gapCenter = (gapLeft + gapRight) / 2;\n          const shiftNeeded = Math.abs(startX - gapCenter);\n          if (shiftNeeded < bestShift) {\n            bestShift = shiftNeeded;\n            bestRouteX = gapCenter;\n          }\n        }\n      }\n\n      finalRouteX = bestRouteX;\n    }\n\n    // Now determine if we need horizontal routing\n    const horizontalDist = Math.abs(startX - endX);\n\n    waypoints.push({ x: startX, y: startY });\n\n    // Check if we need to route around obstacles (finalRouteX differs from startX)\n    // This only applies when startX and endX are close (blackbox case)\n    const needsObstacleAvoidance = Math.abs(finalRouteX - startX) > 5 && horizontalDist <= 5;\n\n    if (needsObstacleAvoidance) {\n      // Route around obstacles for blackbox: go horizontally to finalRouteX, then vertically, then horizontally to endX\n      waypoints.push({ x: finalRouteX, y: startY });\n      waypoints.push({ x: finalRouteX, y: endY });\n      if (Math.abs(finalRouteX - endX) > 5) {\n        waypoints.push({ x: endX, y: endY });\n      }\n    } else if (horizontalDist > 5) {\n      // Normal horizontal routing (source and target at different X)\n      let routeY = horizontalDist > 200 ? endY - 20 : (startY + endY) / 2;\n\n      // Adjust routeY to avoid nodes in the horizontal path\n      if (targetId) {\n        const minX = Math.min(startX, endX);\n        const maxX = Math.max(startX, endX);\n\n        for (const [nodeId, bounds] of nodePositions) {\n          if (nodeId === targetId || nodeId === sourceId) continue;\n\n          const nodeLeft = bounds.x;\n          const nodeRight = bounds.x + bounds.width;\n          const nodeTop = bounds.y;\n          const nodeBottom = bounds.y + bounds.height;\n\n          const overlapsHorizontally = nodeRight > minX && nodeLeft < maxX;\n\n          if (overlapsHorizontally) {\n            if (goingDown) {\n              if (routeY >= nodeTop && routeY <= nodeBottom) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              } else if (nodeTop > startY && nodeTop < endY) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              }\n            } else {\n              if (routeY >= nodeTop && routeY <= nodeBottom) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              } else if (nodeTop < startY && nodeBottom > endY) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              }\n            }\n          }\n        }\n\n        // Keep routeY in reasonable range\n        if (goingDown) {\n          routeY = Math.max(routeY, startY + 10);\n          routeY = Math.min(routeY, endY - 10);\n        } else {\n          routeY = Math.max(routeY, endY + 10);\n          routeY = Math.min(routeY, startY - 10);\n        }\n      }\n\n      waypoints.push({ x: startX, y: routeY });\n      waypoints.push({ x: endX, y: routeY });\n      waypoints.push({ x: endX, y: endY });\n    } else {\n      // Direct vertical path - no obstacles and same X position\n      waypoints.push({ x: endX, y: endY });\n    }\n  }\n\n  /**\n   * Find the task associated with an artifact\n   */\n  private findArtifactAssociatedTask(\n    artifactId: string,\n    edges: Array<{ id: string; sources: string[]; targets: string[]; bpmn?: { type?: string } }>,\n    adjustedNodes: ElkNode[]\n  ): { task: ElkNode | undefined; isInput: boolean } {\n    const nodeMap = new Map<string, ElkNode>();\n    for (const node of adjustedNodes) {\n      nodeMap.set(node.id, node);\n    }\n\n    for (const edge of edges) {\n      const edgeType = edge.bpmn?.type;\n\n      if (edgeType === 'dataInputAssociation' || edgeType === 'association') {\n        if (edge.sources.includes(artifactId)) {\n          const targetId = edge.targets[0];\n          const targetNode = nodeMap.get(targetId);\n          if (targetNode) return { task: targetNode, isInput: true };\n        }\n      }\n\n      if (edgeType === 'dataOutputAssociation') {\n        if (edge.targets.includes(artifactId)) {\n          const sourceId = edge.sources[0];\n          const sourceNode = nodeMap.get(sourceId);\n          if (sourceNode) return { task: sourceNode, isInput: false };\n        }\n      }\n    }\n\n    return { task: undefined, isInput: false };\n  }\n}\n","/**\n * Layout Compactor\n * Reduces unnecessary whitespace in layouts while maintaining relative positions and constraints.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { Bounds } from '../../types/internal';\n\nexport interface CompactorOptions {\n  /** Minimum horizontal gap between nodes */\n  minHorizontalGap: number;\n  /** Minimum vertical gap between nodes */\n  minVerticalGap: number;\n  /** Whether to compact horizontally */\n  compactHorizontal: boolean;\n  /** Whether to compact vertically */\n  compactVertical: boolean;\n  /** Whether to consider edge dependencies */\n  considerDependencies: boolean;\n}\n\nconst DEFAULT_OPTIONS: CompactorOptions = {\n  minHorizontalGap: 60,\n  minVerticalGap: 40,\n  compactHorizontal: true,\n  compactVertical: true,\n  considerDependencies: true,\n};\n\n/**\n * Compact layout to reduce whitespace while maintaining constraints\n */\nexport class Compactor {\n  private options: CompactorOptions;\n\n  constructor(options?: Partial<CompactorOptions>) {\n    this.options = { ...DEFAULT_OPTIONS, ...options };\n  }\n\n  /**\n   * Compact the graph layout\n   */\n  compact(graph: ElkNode): void {\n    if (!graph.children || graph.children.length === 0) return;\n\n    // Build node bounds map\n    const nodeBounds = this.collectNodeBounds(graph);\n\n    if (nodeBounds.length === 0) return;\n\n    // Collect edges for dependency tracking\n    const edges = this.collectEdges(graph);\n\n    if (this.options.considerDependencies && edges.length > 0) {\n      // Compact with dependency consideration\n      this.compactWithDependencies(graph, nodeBounds, edges);\n    } else {\n      // Simple compaction\n      if (this.options.compactHorizontal) {\n        this.compactHorizontalSimple(nodeBounds);\n      }\n      if (this.options.compactVertical) {\n        this.compactVerticalSimple(nodeBounds);\n      }\n      // Apply bounds back to nodes\n      this.applyBounds(graph, nodeBounds);\n    }\n\n    // Recursively compact children\n    for (const child of graph.children) {\n      if ((child as ElkNode).children && (child as ElkNode).children!.length > 0) {\n        this.compact(child as ElkNode);\n      }\n    }\n  }\n\n  /**\n   * Collect node bounds from graph\n   */\n  private collectNodeBounds(graph: ElkNode): Array<Bounds & { id: string }> {\n    const bounds: Array<Bounds & { id: string }> = [];\n\n    if (!graph.children) return bounds;\n\n    for (const child of graph.children) {\n      const node = child as ElkNode;\n      if (node.x !== undefined && node.y !== undefined) {\n        bounds.push({\n          id: node.id,\n          x: node.x,\n          y: node.y,\n          width: node.width ?? 0,\n          height: node.height ?? 0,\n        });\n      }\n    }\n\n    return bounds;\n  }\n\n  /**\n   * Collect edges from graph.\n   *\n   * Boundary-event sources are excluded because their stored coordinates are\n   * stale: the diagram builder repositions boundary events visually onto the\n   * parent task's border, but their ELK-given x/y remain unchanged. Using\n   * those positions as a compaction anchor pulls the boundary target way to\n   * the left, far from where it should sit visually.\n   */\n  private collectEdges(graph: ElkNode): Array<{ source: string; target: string }> {\n    const edges: Array<{ source: string; target: string }> = [];\n\n    const collectFromNode = (node: ElkNode) => {\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const elkEdge = edge as ElkExtendedEdge;\n          if (elkEdge.sources && elkEdge.targets) {\n            for (const source of elkEdge.sources) {\n              if (source.startsWith('boundary_')) continue;\n              for (const target of elkEdge.targets) {\n                edges.push({ source, target });\n              }\n            }\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          collectFromNode(child as ElkNode);\n        }\n      }\n    };\n\n    collectFromNode(graph);\n    return edges;\n  }\n\n  /**\n   * Simple horizontal compaction - move nodes left while maintaining minimum gap\n   */\n  private compactHorizontalSimple(nodes: Array<Bounds & { id: string }>): void {\n    if (nodes.length === 0) return;\n\n    // Sort by X coordinate\n    nodes.sort((a, b) => a.x - b.x);\n\n    // Find minimum X (keep first node's position as anchor)\n    const minX = nodes[0].x;\n\n    // Compact from left to right\n    for (let i = 1; i < nodes.length; i++) {\n      const prev = nodes[i - 1];\n      const curr = nodes[i];\n\n      // Check if nodes are on the same horizontal band (Y overlap)\n      if (this.hasVerticalOverlap(prev, curr)) {\n        const minAllowedX = prev.x + prev.width + this.options.minHorizontalGap;\n\n        // Only move left, never right\n        if (curr.x > minAllowedX) {\n          curr.x = minAllowedX;\n        }\n      }\n    }\n\n    // Normalize to start from original min X\n    const newMinX = Math.min(...nodes.map((n) => n.x));\n    const offsetX = minX - newMinX;\n    if (offsetX > 0) {\n      for (const node of nodes) {\n        node.x += offsetX;\n      }\n    }\n  }\n\n  /**\n   * Simple vertical compaction - move nodes up while maintaining minimum gap\n   */\n  private compactVerticalSimple(nodes: Array<Bounds & { id: string }>): void {\n    if (nodes.length === 0) return;\n\n    // Sort by Y coordinate\n    nodes.sort((a, b) => a.y - b.y);\n\n    // Find minimum Y (keep first node's position as anchor)\n    const minY = nodes[0].y;\n\n    // Compact from top to bottom\n    for (let i = 1; i < nodes.length; i++) {\n      const prev = nodes[i - 1];\n      const curr = nodes[i];\n\n      // Check if nodes are on the same vertical band (X overlap)\n      if (this.hasHorizontalOverlap(prev, curr)) {\n        const minAllowedY = prev.y + prev.height + this.options.minVerticalGap;\n\n        // Only move up, never down\n        if (curr.y > minAllowedY) {\n          curr.y = minAllowedY;\n        }\n      }\n    }\n\n    // Normalize to start from original min Y\n    const newMinY = Math.min(...nodes.map((n) => n.y));\n    const offsetY = minY - newMinY;\n    if (offsetY > 0) {\n      for (const node of nodes) {\n        node.y += offsetY;\n      }\n    }\n  }\n\n  /**\n   * Compact with dependency consideration using topological sort\n   */\n  private compactWithDependencies(\n    graph: ElkNode,\n    nodeBounds: Array<Bounds & { id: string }>,\n    edges: Array<{ source: string; target: string }>\n  ): void {\n    // Build node map for quick lookup\n    const boundsMap = new Map<string, Bounds & { id: string }>();\n    for (const node of nodeBounds) {\n      boundsMap.set(node.id, node);\n    }\n\n    // Build dependency graph (target depends on source)\n    const dependencies = new Map<string, Set<string>>();\n    for (const edge of edges) {\n      if (!dependencies.has(edge.target)) {\n        dependencies.set(edge.target, new Set());\n      }\n      dependencies.get(edge.target)!.add(edge.source);\n    }\n\n    // Topological sort\n    const sorted = this.topologicalSort([...boundsMap.keys()], dependencies);\n\n    // Compact horizontally following dependency order\n    if (this.options.compactHorizontal) {\n      for (const nodeId of sorted) {\n        const node = boundsMap.get(nodeId);\n        if (!node) continue;\n\n        const deps = dependencies.get(nodeId);\n        if (!deps || deps.size === 0) continue;\n\n        // Find the rightmost edge of all dependencies\n        let maxRight = 0;\n        for (const depId of deps) {\n          const dep = boundsMap.get(depId);\n          if (dep) {\n            maxRight = Math.max(maxRight, dep.x + dep.width);\n          }\n        }\n\n        // Compact to minimum allowed position\n        const targetX = maxRight + this.options.minHorizontalGap;\n        if (node.x > targetX) {\n          node.x = targetX;\n        }\n      }\n    }\n\n    // Apply bounds back to nodes\n    this.applyBounds(graph, nodeBounds);\n  }\n\n  /**\n   * Apply bounds back to graph nodes\n   */\n  private applyBounds(graph: ElkNode, bounds: Array<Bounds & { id: string }>): void {\n    const boundsMap = new Map<string, Bounds & { id: string }>();\n    for (const b of bounds) {\n      boundsMap.set(b.id, b);\n    }\n\n    if (!graph.children) return;\n\n    for (const child of graph.children) {\n      const node = child as ElkNode;\n      const b = boundsMap.get(node.id);\n      if (b) {\n        node.x = b.x;\n        node.y = b.y;\n      }\n    }\n  }\n\n  /**\n   * Check if two nodes have vertical overlap (same horizontal band)\n   */\n  private hasVerticalOverlap(a: Bounds, b: Bounds): boolean {\n    const aTop = a.y;\n    const aBottom = a.y + a.height;\n    const bTop = b.y;\n    const bBottom = b.y + b.height;\n\n    return aTop < bBottom && bTop < aBottom;\n  }\n\n  /**\n   * Check if two nodes have horizontal overlap (same vertical band)\n   */\n  private hasHorizontalOverlap(a: Bounds, b: Bounds): boolean {\n    const aLeft = a.x;\n    const aRight = a.x + a.width;\n    const bLeft = b.x;\n    const bRight = b.x + b.width;\n\n    return aLeft < bRight && bLeft < aRight;\n  }\n\n  /**\n   * Topological sort using Kahn's algorithm\n   */\n  private topologicalSort(\n    nodes: string[],\n    dependencies: Map<string, Set<string>>\n  ): string[] {\n    const inDegree = new Map<string, number>();\n    const adjacencyList = new Map<string, string[]>();\n\n    // Initialize\n    for (const node of nodes) {\n      inDegree.set(node, 0);\n      adjacencyList.set(node, []);\n    }\n\n    // Build adjacency list and compute in-degrees\n    for (const [target, sources] of dependencies) {\n      for (const source of sources) {\n        if (adjacencyList.has(source)) {\n          adjacencyList.get(source)!.push(target);\n          inDegree.set(target, (inDegree.get(target) ?? 0) + 1);\n        }\n      }\n    }\n\n    // Find nodes with no dependencies\n    const queue: string[] = [];\n    for (const node of nodes) {\n      if ((inDegree.get(node) ?? 0) === 0) {\n        queue.push(node);\n      }\n    }\n\n    const sorted: string[] = [];\n\n    while (queue.length > 0) {\n      const node = queue.shift()!;\n      sorted.push(node);\n\n      for (const dependent of adjacencyList.get(node) ?? []) {\n        const newDegree = (inDegree.get(dependent) ?? 0) - 1;\n        inDegree.set(dependent, newDegree);\n        if (newDegree === 0) {\n          queue.push(dependent);\n        }\n      }\n    }\n\n    // If there are cycles, append remaining nodes\n    for (const node of nodes) {\n      if (!sorted.includes(node)) {\n        sorted.push(node);\n      }\n    }\n\n    return sorted;\n  }\n}\n\n/**\n * Standalone function for horizontal compaction\n */\nexport function compactHorizontal(\n  nodes: Array<{ id: string; x: number; width: number }>,\n  minGap: number\n): void {\n  if (nodes.length === 0) return;\n\n  // Sort by X coordinate\n  nodes.sort((a, b) => a.x - b.x);\n\n  // Compact from left to right\n  for (let i = 1; i < nodes.length; i++) {\n    const prev = nodes[i - 1];\n    const curr = nodes[i];\n\n    const minX = prev.x + prev.width + minGap;\n\n    // Only move left, never right\n    if (curr.x > minX) {\n      curr.x = minX;\n    }\n  }\n}\n\n/**\n * Standalone function for vertical compaction\n */\nexport function compactVertical(\n  nodes: Array<{ id: string; y: number; height: number }>,\n  minGap: number\n): void {\n  if (nodes.length === 0) return;\n\n  // Sort by Y coordinate\n  nodes.sort((a, b) => a.y - b.y);\n\n  // Compact from top to bottom\n  for (let i = 1; i < nodes.length; i++) {\n    const prev = nodes[i - 1];\n    const curr = nodes[i];\n\n    const minY = prev.y + prev.height + minGap;\n\n    // Only move up, never down\n    if (curr.y > minY) {\n      curr.y = minY;\n    }\n  }\n}\n","/**\n * Pathfinding Router\n * Uses pathfinding library (A* algorithm) for obstacle-avoiding edge routing.\n * Provides better edge routing quality compared to simple obstacle detection.\n */\n\nimport PF from 'pathfinding';\nimport type { Bounds, Point } from '../../types/internal';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PathfindingOptions {\n  /** Grid cell size in pixels (smaller = more precise but slower) */\n  cellSize: number;\n  /** Margin around obstacles */\n  obstacleMargin: number;\n  /** Allow diagonal movement (usually false for BPMN orthogonal routing) */\n  allowDiagonal: boolean;\n  /** Padding around the grid bounds */\n  gridPadding: number;\n}\n\nconst DEFAULT_OPTIONS: PathfindingOptions = {\n  cellSize: 10,\n  obstacleMargin: 5,\n  allowDiagonal: false,\n  gridPadding: 50,\n};\n\nexport interface RouteResult {\n  /** Path points in absolute coordinates */\n  path: Point[];\n  /** Whether a valid path was found */\n  success: boolean;\n}\n\n// ============================================================================\n// Pathfinding Router\n// ============================================================================\n\n/**\n * Router that uses A* pathfinding for obstacle-avoiding edge routing\n */\nexport class PathfindingRouter {\n  private options: PathfindingOptions;\n  private obstacles: Bounds[] = [];\n  private gridBounds: Bounds | null = null;\n  private grid: PF.Grid | null = null;\n  private finder: PF.AStarFinder;\n\n  constructor(options?: Partial<PathfindingOptions>) {\n    this.options = { ...DEFAULT_OPTIONS, ...options };\n    this.finder = new PF.AStarFinder({\n      allowDiagonal: this.options.allowDiagonal,\n      dontCrossCorners: true,\n    });\n  }\n\n  /**\n   * Set obstacles (nodes that edges should avoid)\n   */\n  setObstacles(obstacles: Bounds[]): void {\n    this.obstacles = obstacles.map((obs) => ({\n      x: obs.x - this.options.obstacleMargin,\n      y: obs.y - this.options.obstacleMargin,\n      width: obs.width + this.options.obstacleMargin * 2,\n      height: obs.height + this.options.obstacleMargin * 2,\n    }));\n\n    // Calculate grid bounds\n    this.calculateGridBounds();\n\n    // Build the grid\n    this.buildGrid();\n  }\n\n  /**\n   * Find a path between two points avoiding obstacles\n   */\n  findPath(source: Point, target: Point): RouteResult {\n    if (!this.grid || !this.gridBounds) {\n      return { path: [source, target], success: false };\n    }\n\n    // Convert points to grid coordinates\n    const startGrid = this.toGridCoords(source);\n    const endGrid = this.toGridCoords(target);\n\n    // Clamp to grid bounds\n    const gridWidth = this.grid.width;\n    const gridHeight = this.grid.height;\n\n    const clampedStart = {\n      x: Math.max(0, Math.min(gridWidth - 1, startGrid.x)),\n      y: Math.max(0, Math.min(gridHeight - 1, startGrid.y)),\n    };\n    const clampedEnd = {\n      x: Math.max(0, Math.min(gridWidth - 1, endGrid.x)),\n      y: Math.max(0, Math.min(gridHeight - 1, endGrid.y)),\n    };\n\n    // Clone grid for pathfinding (finder modifies the grid)\n    const gridClone = this.grid.clone();\n\n    // Ensure start and end cells are walkable\n    gridClone.setWalkableAt(clampedStart.x, clampedStart.y, true);\n    gridClone.setWalkableAt(clampedEnd.x, clampedEnd.y, true);\n\n    // Find path\n    const gridPath = this.finder.findPath(\n      clampedStart.x,\n      clampedStart.y,\n      clampedEnd.x,\n      clampedEnd.y,\n      gridClone\n    );\n\n    if (gridPath.length === 0) {\n      // No path found, return direct line\n      return { path: [source, target], success: false };\n    }\n\n    // Convert grid path to absolute coordinates\n    const absolutePath = gridPath.map(([gx, gy]) => this.toAbsoluteCoords({ x: gx, y: gy }));\n\n    // Simplify the path (remove redundant points)\n    const simplifiedPath = this.simplifyPath(absolutePath);\n\n    // Ensure start and end points are exact\n    if (simplifiedPath.length > 0) {\n      simplifiedPath[0] = source;\n      simplifiedPath[simplifiedPath.length - 1] = target;\n    }\n\n    return { path: simplifiedPath, success: true };\n  }\n\n  /**\n   * Find an orthogonal path (only horizontal and vertical segments)\n   */\n  findOrthogonalPath(source: Point, target: Point): RouteResult {\n    const result = this.findPath(source, target);\n\n    if (!result.success) {\n      // Create a simple orthogonal path\n      return {\n        path: this.createSimpleOrthogonalPath(source, target),\n        success: false,\n      };\n    }\n\n    // Orthogonalize the path\n    const orthogonalPath = this.orthogonalizePath(result.path);\n\n    return { path: orthogonalPath, success: true };\n  }\n\n  /**\n   * Route an edge from source node to target node\n   */\n  routeEdge(\n    sourceNode: Bounds,\n    targetNode: Bounds,\n    sourcePort?: 'top' | 'bottom' | 'left' | 'right',\n    targetPort?: 'top' | 'bottom' | 'left' | 'right'\n  ): RouteResult {\n    // Determine connection points\n    const source = this.getConnectionPoint(sourceNode, sourcePort ?? this.getBestSourcePort(sourceNode, targetNode));\n    const target = this.getConnectionPoint(targetNode, targetPort ?? this.getBestTargetPort(sourceNode, targetNode));\n\n    return this.findOrthogonalPath(source, target);\n  }\n\n  // ============================================================================\n  // Private: Grid Building\n  // ============================================================================\n\n  private calculateGridBounds(): void {\n    if (this.obstacles.length === 0) {\n      this.gridBounds = { x: 0, y: 0, width: 100, height: 100 };\n      return;\n    }\n\n    let minX = Infinity;\n    let minY = Infinity;\n    let maxX = -Infinity;\n    let maxY = -Infinity;\n\n    for (const obs of this.obstacles) {\n      minX = Math.min(minX, obs.x);\n      minY = Math.min(minY, obs.y);\n      maxX = Math.max(maxX, obs.x + obs.width);\n      maxY = Math.max(maxY, obs.y + obs.height);\n    }\n\n    const padding = this.options.gridPadding;\n    this.gridBounds = {\n      x: minX - padding,\n      y: minY - padding,\n      width: maxX - minX + padding * 2,\n      height: maxY - minY + padding * 2,\n    };\n  }\n\n  private buildGrid(): void {\n    if (!this.gridBounds) return;\n\n    const cellSize = this.options.cellSize;\n    const gridWidth = Math.ceil(this.gridBounds.width / cellSize);\n    const gridHeight = Math.ceil(this.gridBounds.height / cellSize);\n\n    // Create grid with all cells walkable\n    this.grid = new PF.Grid(gridWidth, gridHeight);\n\n    // Mark obstacle cells as unwalkable\n    for (const obs of this.obstacles) {\n      const startX = Math.floor((obs.x - this.gridBounds.x) / cellSize);\n      const startY = Math.floor((obs.y - this.gridBounds.y) / cellSize);\n      const endX = Math.ceil((obs.x + obs.width - this.gridBounds.x) / cellSize);\n      const endY = Math.ceil((obs.y + obs.height - this.gridBounds.y) / cellSize);\n\n      for (let gx = startX; gx < endX; gx++) {\n        for (let gy = startY; gy < endY; gy++) {\n          if (gx >= 0 && gx < gridWidth && gy >= 0 && gy < gridHeight) {\n            this.grid.setWalkableAt(gx, gy, false);\n          }\n        }\n      }\n    }\n  }\n\n  // ============================================================================\n  // Private: Coordinate Conversion\n  // ============================================================================\n\n  private toGridCoords(point: Point): { x: number; y: number } {\n    if (!this.gridBounds) return { x: 0, y: 0 };\n\n    return {\n      x: Math.round((point.x - this.gridBounds.x) / this.options.cellSize),\n      y: Math.round((point.y - this.gridBounds.y) / this.options.cellSize),\n    };\n  }\n\n  private toAbsoluteCoords(gridPoint: { x: number; y: number }): Point {\n    if (!this.gridBounds) return { x: 0, y: 0 };\n\n    return {\n      x: gridPoint.x * this.options.cellSize + this.gridBounds.x,\n      y: gridPoint.y * this.options.cellSize + this.gridBounds.y,\n    };\n  }\n\n  // ============================================================================\n  // Private: Path Processing\n  // ============================================================================\n\n  private simplifyPath(path: Point[]): Point[] {\n    if (path.length <= 2) return path;\n\n    const result: Point[] = [path[0]];\n\n    for (let i = 1; i < path.length - 1; i++) {\n      const prev = path[i - 1];\n      const curr = path[i];\n      const next = path[i + 1];\n\n      // Check if direction changes\n      const dx1 = curr.x - prev.x;\n      const dy1 = curr.y - prev.y;\n      const dx2 = next.x - curr.x;\n      const dy2 = next.y - curr.y;\n\n      // Normalize directions\n      const dir1x = dx1 === 0 ? 0 : dx1 / Math.abs(dx1);\n      const dir1y = dy1 === 0 ? 0 : dy1 / Math.abs(dy1);\n      const dir2x = dx2 === 0 ? 0 : dx2 / Math.abs(dx2);\n      const dir2y = dy2 === 0 ? 0 : dy2 / Math.abs(dy2);\n\n      // Keep point if direction changes\n      if (dir1x !== dir2x || dir1y !== dir2y) {\n        result.push(curr);\n      }\n    }\n\n    result.push(path[path.length - 1]);\n    return result;\n  }\n\n  private orthogonalizePath(path: Point[]): Point[] {\n    if (path.length <= 1) return path;\n\n    const result: Point[] = [path[0]];\n\n    for (let i = 1; i < path.length; i++) {\n      const prev = result[result.length - 1];\n      const curr = path[i];\n\n      // If not already orthogonal, add intermediate point\n      if (prev.x !== curr.x && prev.y !== curr.y) {\n        // Prefer horizontal-then-vertical routing\n        result.push({ x: curr.x, y: prev.y });\n      }\n\n      result.push(curr);\n    }\n\n    return result;\n  }\n\n  private createSimpleOrthogonalPath(source: Point, target: Point): Point[] {\n    // Simple L-shaped or Z-shaped path\n    const midX = (source.x + target.x) / 2;\n\n    if (source.y === target.y) {\n      return [source, target];\n    }\n\n    if (source.x === target.x) {\n      return [source, target];\n    }\n\n    // Create a path with intermediate points\n    return [\n      source,\n      { x: midX, y: source.y },\n      { x: midX, y: target.y },\n      target,\n    ];\n  }\n\n  // ============================================================================\n  // Private: Connection Points\n  // ============================================================================\n\n  private getConnectionPoint(node: Bounds, port: 'top' | 'bottom' | 'left' | 'right'): Point {\n    switch (port) {\n      case 'top':\n        return { x: node.x + node.width / 2, y: node.y };\n      case 'bottom':\n        return { x: node.x + node.width / 2, y: node.y + node.height };\n      case 'left':\n        return { x: node.x, y: node.y + node.height / 2 };\n      case 'right':\n        return { x: node.x + node.width, y: node.y + node.height / 2 };\n    }\n  }\n\n  private getBestSourcePort(source: Bounds, target: Bounds): 'top' | 'bottom' | 'left' | 'right' {\n    const sourceCenterX = source.x + source.width / 2;\n    const sourceCenterY = source.y + source.height / 2;\n    const targetCenterX = target.x + target.width / 2;\n    const targetCenterY = target.y + target.height / 2;\n\n    const dx = targetCenterX - sourceCenterX;\n    const dy = targetCenterY - sourceCenterY;\n\n    if (Math.abs(dx) > Math.abs(dy)) {\n      return dx > 0 ? 'right' : 'left';\n    } else {\n      return dy > 0 ? 'bottom' : 'top';\n    }\n  }\n\n  private getBestTargetPort(source: Bounds, target: Bounds): 'top' | 'bottom' | 'left' | 'right' {\n    const sourceCenterX = source.x + source.width / 2;\n    const sourceCenterY = source.y + source.height / 2;\n    const targetCenterX = target.x + target.width / 2;\n    const targetCenterY = target.y + target.height / 2;\n\n    const dx = sourceCenterX - targetCenterX;\n    const dy = sourceCenterY - targetCenterY;\n\n    if (Math.abs(dx) > Math.abs(dy)) {\n      return dx > 0 ? 'right' : 'left';\n    } else {\n      return dy > 0 ? 'bottom' : 'top';\n    }\n  }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Route multiple edges with obstacle avoidance\n */\nexport function routeEdges(\n  edges: Array<{\n    id: string;\n    source: Bounds;\n    target: Bounds;\n    sourcePort?: 'top' | 'bottom' | 'left' | 'right';\n    targetPort?: 'top' | 'bottom' | 'left' | 'right';\n  }>,\n  obstacles: Bounds[],\n  options?: Partial<PathfindingOptions>\n): Map<string, Point[]> {\n  const router = new PathfindingRouter(options);\n  router.setObstacles(obstacles);\n\n  const results = new Map<string, Point[]>();\n\n  for (const edge of edges) {\n    const result = router.routeEdge(edge.source, edge.target, edge.sourcePort, edge.targetPort);\n    results.set(edge.id, result.path);\n  }\n\n  return results;\n}\n\n/**\n * Find a path between two points avoiding obstacles\n */\nexport function findPathAvoidingObstacles(\n  source: Point,\n  target: Point,\n  obstacles: Bounds[],\n  options?: Partial<PathfindingOptions>\n): Point[] {\n  const router = new PathfindingRouter(options);\n  router.setObstacles(obstacles);\n  const result = router.findOrthogonalPath(source, target);\n  return result.path;\n}\n","/**\n * Edge Fixer\n * Detects and fixes edges that cross through nodes.\n * Uses PathfindingRouter for obstacle-avoiding pathfinding.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { Point, Bounds, NodeWithBpmn } from '../../types/internal';\nimport { EVENT_TYPES, GATEWAY_TYPES, SUBPROCESS_TYPES, TASK_TYPES } from '../../types/bpmn-constants';\nimport { segmentCrossesNode, createOrthogonalPath } from './geometry-utils';\nimport { PathfindingRouter } from './pathfinding-router';\nimport { isDebugEnabled } from '../../utils/debug';\n\nconst SUBPROCESS_TYPE_SET = new Set<string>(SUBPROCESS_TYPES);\n// Nodes that act as obstacles for edge routing. Detected by bpmn.type rather\n// than ID prefix because IDs like `tx_end` (a transaction's internal end event)\n// share a prefix with their parent and would slip past a regex-based filter.\nconst OBSTACLE_TYPE_SET = new Set<string>([\n  ...EVENT_TYPES.filter((t) => t !== 'boundaryEvent'),\n  ...TASK_TYPES,\n  ...GATEWAY_TYPES,\n  'callActivity',\n  // Collapsed subprocesses are obstacles; expanded ones are containers and\n  // handled by the isContainer branch below.\n  ...SUBPROCESS_TYPES,\n]);\n\n// A node whose x/y is a coordinate system for its descendants and edges.\n// Expanded subprocesses, pools, lanes, and processes all share this property:\n// child positions and edge waypoints are stored relative to them.\nfunction isContainer(bpmn: NodeWithBpmn['bpmn']): boolean {\n  if (!bpmn) return false;\n  const type = bpmn.type;\n  if (!type) return false;\n  if (type === 'participant' || type === 'lane' || type === 'process') return true;\n  return bpmn.isExpanded === true && SUBPROCESS_TYPE_SET.has(type);\n}\n\nfunction isFlowObstacle(bpmn: NodeWithBpmn['bpmn']): boolean {\n  if (!bpmn?.type) return false;\n  if (bpmn.type === 'boundaryEvent') return false;\n  // Skip expanded subprocesses — they're containers, not obstacles.\n  if (bpmn.isExpanded === true && SUBPROCESS_TYPE_SET.has(bpmn.type)) return false;\n  return OBSTACLE_TYPE_SET.has(bpmn.type);\n}\n\n/**\n * Handler for edge crossing detection and fixing\n */\nexport class EdgeFixer {\n  private readonly margin = 15;\n  private router: PathfindingRouter;\n\n  constructor() {\n    this.router = new PathfindingRouter({\n      cellSize: 10,\n      obstacleMargin: this.margin,\n      allowDiagonal: false,\n      gridPadding: 50,\n    });\n  }\n\n  /**\n   * Fix edges that cross through nodes\n   */\n  fix(graph: ElkNode): void {\n    // Obstacles for crossing-detection. Excludes containers (expanded\n    // subprocesses, pools/lanes) because edges crossing their borders is\n    // expected behavior, not a routing failure.\n    const obstaclesByContainer = new Map<string, Map<string, Bounds>>();\n    // All anchorable nodes (obstacles + container nodes that can act as\n    // edge source/target). Snap consults this so it can re-anchor edges\n    // that start/end on a subprocess after post-processing resized it.\n    const anchorsByContainer = new Map<string, Map<string, Bounds>>();\n    const boundaryEventIds = new Set<string>();\n\n    const isPoolType = (bpmn: NodeWithBpmn['bpmn']): boolean =>\n      bpmn?.type === 'participant' || bpmn?.type === 'process';\n\n    const recordNode = (\n      bucket: Map<string, Map<string, Bounds>>,\n      containerId: string,\n      id: string,\n      bounds: Bounds\n    ) => {\n      if (!bucket.has(containerId)) bucket.set(containerId, new Map());\n      bucket.get(containerId)!.set(id, bounds);\n    };\n\n    const collectNodePositions = (\n      node: ElkNode,\n      offsetX: number = 0,\n      offsetY: number = 0,\n      containerId: string = 'root'\n    ) => {\n      const bpmn = (node as unknown as NodeWithBpmn).bpmn;\n      const currentContainerId = isPoolType(bpmn) ? node.id : containerId;\n      if (bpmn?.type === 'boundaryEvent') boundaryEventIds.add(node.id);\n\n      if (node.x !== undefined && node.y !== undefined) {\n        // Use visual dimensions for edge anchoring/crossing. ELK inflates\n        // event heights (label band) and gateway widths (long-label band),\n        // but edges should attach to the visible shape, not the layout box.\n        const visualWidth = bpmn?._visualWidth ?? node.width ?? 100;\n        const visualHeight = bpmn?._visualHeight ?? node.height ?? 80;\n        const bounds: Bounds = {\n          x: offsetX + node.x,\n          y: offsetY + node.y,\n          width: visualWidth,\n          height: visualHeight,\n        };\n        const obstacle = isFlowObstacle(bpmn);\n        // Subprocesses (and any container that can host edge endpoints) are\n        // anchorable even though they aren't obstacles.\n        const anchorable = obstacle || (bpmn?.isExpanded === true && SUBPROCESS_TYPE_SET.has(bpmn.type));\n        if (obstacle) recordNode(obstaclesByContainer, currentContainerId, node.id, bounds);\n        if (anchorable) recordNode(anchorsByContainer, currentContainerId, node.id, bounds);\n      }\n\n      if (node.children) {\n        const descend = isContainer(bpmn);\n        const newOffsetX = descend ? offsetX + (node.x ?? 0) : offsetX;\n        const newOffsetY = descend ? offsetY + (node.y ?? 0) : offsetY;\n        for (const child of node.children) {\n          collectNodePositions(child, newOffsetX, newOffsetY, currentContainerId);\n        }\n      }\n    };\n    collectNodePositions(graph);\n\n    const processEdges = (\n      node: ElkNode,\n      containerOffsetX: number = 0,\n      containerOffsetY: number = 0,\n      containerId: string = 'root'\n    ) => {\n      const bpmn = (node as unknown as NodeWithBpmn).bpmn;\n      const currentContainerId = isPoolType(bpmn) ? node.id : containerId;\n\n      // Edge waypoints on a container node are stored relative to that\n      // container, so accumulate the container's own x/y before walking into\n      // its edges (which are processed before recursing into children).\n      const descend = isContainer(bpmn);\n      const selfOffsetX = descend ? containerOffsetX + (node.x ?? 0) : containerOffsetX;\n      const selfOffsetY = descend ? containerOffsetY + (node.y ?? 0) : containerOffsetY;\n\n      if (node.edges) {\n        const anchors = anchorsByContainer.get(currentContainerId) ?? new Map();\n        const obstacles = obstaclesByContainer.get(currentContainerId) ?? new Map();\n\n        for (const edge of node.edges) {\n          if (!edge.sections || edge.sections.length === 0) continue;\n          // Boundary-event edges have bespoke routing in diagram-builder;\n          // re-snapping them here would discard that work.\n          const sourceId = edge.sources?.[0];\n          if (sourceId && boundaryEventIds.has(sourceId)) continue;\n          this.snapEdgeEndpointsToNodeBorders(edge, anchors, selfOffsetX, selfOffsetY);\n          this.fixEdgeIfCrossing(edge, anchors, obstacles, selfOffsetX, selfOffsetY);\n        }\n      }\n\n      if (node.children) {\n        for (const child of node.children) {\n          processEdges(child, selfOffsetX, selfOffsetY, currentContainerId);\n        }\n      }\n    };\n    processEdges(graph);\n  }\n\n  private fixEdgeIfCrossing(\n    edge: ElkExtendedEdge,\n    anchors: Map<string, Bounds>,\n    obstacleMap: Map<string, Bounds>,\n    containerOffsetX: number,\n    containerOffsetY: number\n  ): void {\n    const section = edge.sections?.[0];\n    if (!section) return;\n\n    const sourceId = edge.sources?.[0];\n    const targetId = edge.targets?.[0];\n\n    const waypoints: Point[] = [\n      { x: containerOffsetX + section.startPoint.x, y: containerOffsetY + section.startPoint.y },\n    ];\n    if (section.bendPoints) {\n      for (const bp of section.bendPoints) {\n        waypoints.push({ x: containerOffsetX + bp.x, y: containerOffsetY + bp.y });\n      }\n    }\n    waypoints.push({ x: containerOffsetX + section.endPoint.x, y: containerOffsetY + section.endPoint.y });\n\n    const crossedNodes: string[] = [];\n    for (let i = 0; i < waypoints.length - 1; i++) {\n      const p1 = waypoints[i];\n      const p2 = waypoints[i + 1];\n      if (!p1 || !p2) continue;\n\n      for (const [nodeId, pos] of obstacleMap) {\n        if (nodeId === sourceId || nodeId === targetId) continue;\n        if (segmentCrossesNode(p1, p2, pos)) {\n          crossedNodes.push(nodeId);\n        }\n      }\n    }\n\n    const targetPos = targetId ? anchors.get(targetId) : undefined;\n    const sourcePos = sourceId ? anchors.get(sourceId) : undefined;\n\n    if (targetPos && sourcePos && waypoints.length >= 2) {\n      const lastWaypoint = waypoints[waypoints.length - 1];\n      const secondLastWaypoint = waypoints[waypoints.length - 2];\n      const isReturnEdge = targetPos.y + targetPos.height < sourcePos.y;\n\n      if (isReturnEdge && lastWaypoint && secondLastWaypoint) {\n        if (Math.abs(secondLastWaypoint.y - lastWaypoint.y) < 5) {\n          const segY = secondLastWaypoint.y;\n          const segMinX = Math.min(secondLastWaypoint.x, lastWaypoint.x);\n          const segMaxX = Math.max(secondLastWaypoint.x, lastWaypoint.x);\n\n          if (segY > targetPos.y && segY < targetPos.y + targetPos.height) {\n            if (segMinX < targetPos.x + targetPos.width && segMaxX > targetPos.x) {\n              crossedNodes.push(targetId + ' (target)');\n            }\n          }\n        }\n      }\n    }\n\n    if (crossedNodes.length === 0) return;\n\n    if (isDebugEnabled()) {\n      console.log(`[BPMN] Edge ${edge.id} crosses nodes: ${crossedNodes.join(', ')}`);\n    }\n\n    if (!sourcePos || !targetPos) return;\n\n    // Exclude source and target from obstacles. Otherwise the inflated\n    // obstacle margin engulfs the start/end cells, the pathfinder can't\n    // step out, and we fall back to a midpoint Z-shape that still cuts\n    // straight through other nodes.\n    const obstacles: Bounds[] = [];\n    for (const [nodeId, pos] of obstacleMap) {\n      if (nodeId === sourceId || nodeId === targetId) continue;\n      obstacles.push(pos);\n    }\n\n    this.router.setObstacles(obstacles);\n\n    const dx = (targetPos.x + targetPos.width / 2) - (sourcePos.x + sourcePos.width / 2);\n    const dy = (targetPos.y + targetPos.height / 2) - (sourcePos.y + sourcePos.height / 2);\n\n    // Pick the primary axis. When only one axis is cleanly separated, the\n    // route HAS to leave/enter along it. When both are separated (i.e.,\n    // source and target diagonal to each other with an obstacle band between),\n    // pick the axis with the larger separation so the longer leg comes first\n    // and the final segment is short and perpendicular to the target.\n    const horizontallySeparated =\n      targetPos.x >= sourcePos.x + sourcePos.width ||\n      sourcePos.x >= targetPos.x + targetPos.width;\n    const verticallySeparated =\n      targetPos.y >= sourcePos.y + sourcePos.height ||\n      sourcePos.y >= targetPos.y + targetPos.height;\n    let horizontalPrimary: boolean;\n    if (horizontallySeparated && !verticallySeparated) horizontalPrimary = true;\n    else if (verticallySeparated && !horizontallySeparated) horizontalPrimary = false;\n    else horizontalPrimary = Math.abs(dx) >= Math.abs(dy);\n\n    let sourcePort: 'top' | 'bottom' | 'left' | 'right';\n    let targetPort: 'top' | 'bottom' | 'left' | 'right';\n    if (horizontalPrimary) {\n      sourcePort = dx >= 0 ? 'right' : 'left';\n      targetPort = dx >= 0 ? 'left' : 'right';\n    } else {\n      sourcePort = dy >= 0 ? 'bottom' : 'top';\n      targetPort = dy >= 0 ? 'top' : 'bottom';\n    }\n\n    const result = this.router.routeEdge(sourcePos, targetPos, sourcePort, targetPort);\n    // A* on a 10px grid emits a step-by-step path; collapse runs of stairs\n    // into the longest L-shape that still clears every obstacle, otherwise\n    // the diagram fills up with jagged staircases.\n    const path = this.shortcutOrthogonal(result.path, obstacles);\n\n    if (path.length < 2) return;\n\n    // Re-anchor the target endpoint if the final segment's direction doesn't\n    // match the requested side. When the route had to wrap around obstacles,\n    // pathfinder's final L-leg can come in perpendicular to a DIFFERENT side\n    // (e.g., vertical-into-left). Snapping to the matching side avoids\n    // ensurePerpendicularEndpoints later inserting a tiny stub that bpmn.io\n    // renders as an arrow tip pointing the wrong direction.\n    this.alignFinalSegmentToTargetSide(path, targetPos);\n    this.alignFinalSegmentToSourceSide(path, sourcePos);\n\n    const startPoint = path[0];\n    const endPoint = path[path.length - 1];\n    const bendPoints = path.slice(1, -1);\n\n    section.startPoint = {\n      x: startPoint.x - containerOffsetX,\n      y: startPoint.y - containerOffsetY,\n    };\n    section.endPoint = {\n      x: endPoint.x - containerOffsetX,\n      y: endPoint.y - containerOffsetY,\n    };\n    section.bendPoints = bendPoints.length > 0\n      ? bendPoints.map(bp => ({\n          x: bp.x - containerOffsetX,\n          y: bp.y - containerOffsetY,\n        }))\n      : undefined;\n\n    if (isDebugEnabled()) {\n      console.log(`[BPMN] Fixed edge ${edge.id} with ${bendPoints.length} bend points using PathfindingRouter`);\n    }\n  }\n\n  /**\n   * Re-anchor edge start/end points to their source/target node borders.\n   * Post-processing (compactor, lane stacking, etc.) often moves nodes after\n   * ELK ran, leaving edge endpoints pointing at stale positions. Without this\n   * pass, an edge can appear to continue past its target into empty space.\n   *\n   * The strategy is deliberately simple: snap endpoints to the natural border\n   * for the source→target direction (horizontal-primary unless the nodes are\n   * nearly column-aligned), and keep any bend points along the way intact.\n   */\n  private snapEdgeEndpointsToNodeBorders(\n    edge: ElkExtendedEdge,\n    nodePositions: Map<string, Bounds>,\n    containerOffsetX: number,\n    containerOffsetY: number\n  ): void {\n    const section = edge.sections?.[0];\n    if (!section) return;\n\n    const sourceId = edge.sources?.[0];\n    const targetId = edge.targets?.[0];\n    if (!sourceId || !targetId) return;\n\n    const sourcePos = nodePositions.get(sourceId);\n    const targetPos = nodePositions.get(targetId);\n    if (!sourcePos || !targetPos) return;\n\n    const srcCx = sourcePos.x + sourcePos.width / 2;\n    const srcCy = sourcePos.y + sourcePos.height / 2;\n    const dstCx = targetPos.x + targetPos.width / 2;\n    const dstCy = targetPos.y + targetPos.height / 2;\n    const dx = dstCx - srcCx;\n    const dy = dstCy - srcCy;\n    // If source and target are completely separated on one axis (one's far edge ≤\n    // the other's near edge), the edge HAS to leave/enter via that axis — picking\n    // the other axis sends the connector along the side of the source/target\n    // bounding box and the perpendicular bend then often slices through whatever\n    // node sits between them on the same layer. So whenever an axis is cleanly\n    // separated, force that as the primary; only fall back to magnitude when both\n    // axes overlap.\n    const horizontallySeparated =\n      targetPos.x >= sourcePos.x + sourcePos.width ||\n      sourcePos.x >= targetPos.x + targetPos.width;\n    const verticallySeparated =\n      targetPos.y >= sourcePos.y + sourcePos.height ||\n      sourcePos.y >= targetPos.y + targetPos.height;\n    let horizontalPrimary: boolean;\n    if (horizontallySeparated) horizontalPrimary = true;\n    else if (verticallySeparated) horizontalPrimary = false;\n    else horizontalPrimary = Math.abs(dx) >= Math.abs(dy);\n\n    let startAbsX: number, startAbsY: number, endAbsX: number, endAbsY: number;\n    if (horizontalPrimary) {\n      startAbsY = srcCy;\n      endAbsY = dstCy;\n      if (dx >= 0) {\n        startAbsX = sourcePos.x + sourcePos.width;\n        endAbsX = targetPos.x;\n      } else {\n        startAbsX = sourcePos.x;\n        endAbsX = targetPos.x + targetPos.width;\n      }\n    } else {\n      startAbsX = srcCx;\n      endAbsX = dstCx;\n      if (dy >= 0) {\n        startAbsY = sourcePos.y + sourcePos.height;\n        endAbsY = targetPos.y;\n      } else {\n        startAbsY = sourcePos.y;\n        endAbsY = targetPos.y + targetPos.height;\n      }\n    }\n\n    // Emit a Z-shape so the downstream crossing check (which only inspects\n    // axis-aligned segments) can see the actual route. A bare diagonal would\n    // be invisible to the check, and diagram-builder would later orthogonalize\n    // it straight through whatever node sits between source and target.\n    const path = createOrthogonalPath(\n      { x: startAbsX, y: startAbsY },\n      { x: endAbsX, y: endAbsY },\n      horizontalPrimary ? 'horizontal' : 'vertical'\n    );\n    const first = path[0];\n    const last = path[path.length - 1];\n    section.startPoint = {\n      x: first.x - containerOffsetX,\n      y: first.y - containerOffsetY,\n    };\n    section.endPoint = {\n      x: last.x - containerOffsetX,\n      y: last.y - containerOffsetY,\n    };\n    section.bendPoints = path.length > 2\n      ? path.slice(1, -1).map((p) => ({\n          x: p.x - containerOffsetX,\n          y: p.y - containerOffsetY,\n        }))\n      : undefined;\n  }\n\n  // When the final segment is vertical but the endpoint sits on the target's\n  // left/right edge (or horizontal but on top/bottom), swap the endpoint to\n  // the side that matches the segment's direction. Keeps the route a clean L\n  // instead of producing a stubby corner.\n  private alignFinalSegmentToTargetSide(path: Point[], targetPos: Bounds): void {\n    if (path.length < 2) return;\n    const end = path[path.length - 1];\n    const prev = path[path.length - 2];\n    const segHorizontal = Math.abs(end.y - prev.y) < 1;\n    const segVertical = Math.abs(end.x - prev.x) < 1;\n    if (!segHorizontal && !segVertical) return;\n\n    const left = targetPos.x;\n    const right = targetPos.x + targetPos.width;\n    const top = targetPos.y;\n    const bottom = targetPos.y + targetPos.height;\n    const cx = targetPos.x + targetPos.width / 2;\n    const cy = targetPos.y + targetPos.height / 2;\n    const onLeft = Math.abs(end.x - left) < 3;\n    const onRight = Math.abs(end.x - right) < 3;\n    const onTop = Math.abs(end.y - top) < 3;\n    const onBottom = Math.abs(end.y - bottom) < 3;\n\n    if (segVertical && (onLeft || onRight)) {\n      const approachFromBelow = prev.y > end.y;\n      end.x = cx;\n      end.y = approachFromBelow ? bottom : top;\n      prev.x = cx;\n    } else if (segHorizontal && (onTop || onBottom)) {\n      const approachFromRight = prev.x > end.x;\n      end.y = cy;\n      end.x = approachFromRight ? right : left;\n      prev.y = cy;\n    }\n  }\n\n  private alignFinalSegmentToSourceSide(path: Point[], sourcePos: Bounds): void {\n    if (path.length < 2) return;\n    const start = path[0];\n    const next = path[1];\n    const segHorizontal = Math.abs(start.y - next.y) < 1;\n    const segVertical = Math.abs(start.x - next.x) < 1;\n    if (!segHorizontal && !segVertical) return;\n\n    const left = sourcePos.x;\n    const right = sourcePos.x + sourcePos.width;\n    const top = sourcePos.y;\n    const bottom = sourcePos.y + sourcePos.height;\n    const cx = sourcePos.x + sourcePos.width / 2;\n    const cy = sourcePos.y + sourcePos.height / 2;\n    const onLeft = Math.abs(start.x - left) < 3;\n    const onRight = Math.abs(start.x - right) < 3;\n    const onTop = Math.abs(start.y - top) < 3;\n    const onBottom = Math.abs(start.y - bottom) < 3;\n\n    if (segVertical && (onLeft || onRight)) {\n      const departsUp = next.y < start.y;\n      start.x = cx;\n      start.y = departsUp ? top : bottom;\n      next.x = cx;\n    } else if (segHorizontal && (onTop || onBottom)) {\n      const departsLeft = next.x < start.x;\n      start.y = cy;\n      start.x = departsLeft ? left : right;\n      next.y = cy;\n    }\n  }\n\n  // Greedy orthogonal \"string pulling\" — A* on a 10px grid emits step-by-step\n  // staircases; for each anchor, jump to the farthest path point still reachable\n  // via a single L-shape (or straight segment) that clears every obstacle.\n  private shortcutOrthogonal(path: Point[], obstacles: Bounds[]): Point[] {\n    if (path.length <= 2) return path;\n\n    const segmentClear = (p1: Point, p2: Point): boolean => {\n      for (const obs of obstacles) {\n        if (segmentCrossesNode(p1, p2, obs)) return false;\n      }\n      return true;\n    };\n\n    // Try to connect a→b via a single L (or straight). Push the bend (if any)\n    // and the endpoint to `out`; return false when no clearance is possible.\n    const pushLShape = (a: Point, b: Point, out: Point[]): boolean => {\n      if (Math.abs(a.x - b.x) < 1 || Math.abs(a.y - b.y) < 1) {\n        if (!segmentClear(a, b)) return false;\n        out.push(b);\n        return true;\n      }\n      const hThenV = { x: b.x, y: a.y };\n      if (segmentClear(a, hThenV) && segmentClear(hThenV, b)) {\n        out.push(hThenV, b);\n        return true;\n      }\n      const vThenH = { x: a.x, y: b.y };\n      if (segmentClear(a, vThenH) && segmentClear(vThenH, b)) {\n        out.push(vThenH, b);\n        return true;\n      }\n      return false;\n    };\n\n    const result: Point[] = [path[0]];\n    let i = 0;\n    while (i < path.length - 1) {\n      // Try the farthest jump first; A* only emits walkable steps so the\n      // i→i+1 fallback is always reachable.\n      for (let j = path.length - 1; j > i; j--) {\n        if (j === i + 1 || pushLShape(path[i], path[j], result)) {\n          if (j === i + 1) result.push(path[j]);\n          i = j;\n          break;\n        }\n      }\n    }\n    return result;\n  }\n}\n","/**\n * Gateway Endpoint Adjuster\n * Handles the calculation of edge endpoint positions for gateway diamond shapes.\n * Gateways in BPMN are rendered as diamonds, so edge endpoints need to be adjusted\n * to connect to the diamond edges rather than the rectangular bounding box.\n */\n\nimport type { Point, Bounds } from '../../types/internal';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Adjust an edge endpoint to connect to a gateway's diamond shape.\n * Gateway diamonds have 4 corners: left, top, right, bottom (at midpoints of bounding box edges).\n *\n * @param endpoint - The current endpoint position\n * @param adjacentPoint - The adjacent point on the edge (used to determine approach direction)\n * @param gatewayBounds - The bounding box of the gateway\n * @param isSource - Whether this endpoint is the source (true) or target (false) of the edge\n * @returns The adjusted endpoint position on the diamond edge\n */\nexport function adjustGatewayEndpoint(\n  endpoint: Point,\n  adjacentPoint: Point,\n  gatewayBounds: Bounds,\n  isSource: boolean\n): Point {\n  const gatewayCenterX = gatewayBounds.x + gatewayBounds.width / 2;\n  const gatewayCenterY = gatewayBounds.y + gatewayBounds.height / 2;\n  const tolerance = 1; // Tolerance for corner detection\n\n  if (isDebugEnabled()) {\n    console.log(`[BPMN] adjustGatewayEndpoint: isSource=${isSource}`);\n    console.log(`  endpoint: (${endpoint.x}, ${endpoint.y})`);\n    console.log(`  gatewayBounds: x=${gatewayBounds.x}, y=${gatewayBounds.y}, w=${gatewayBounds.width}, h=${gatewayBounds.height}`);\n    console.log(`  gatewayCenter: (${gatewayCenterX}, ${gatewayCenterY})`);\n    console.log(`  right edge x: ${gatewayBounds.x + gatewayBounds.width}`);\n  }\n\n  // Diamond corners (at midpoints of bounding box edges)\n  const leftCorner = { x: gatewayBounds.x, y: gatewayCenterY };\n  const rightCorner = { x: gatewayBounds.x + gatewayBounds.width, y: gatewayCenterY };\n  const topCorner = { x: gatewayCenterX, y: gatewayBounds.y };\n  const bottomCorner = { x: gatewayCenterX, y: gatewayBounds.y + gatewayBounds.height };\n\n  // Check if endpoint is already at a diamond corner (no adjustment needed)\n  // Left corner: x at left edge AND y at center\n  if (Math.abs(endpoint.x - gatewayBounds.x) < tolerance &&\n      Math.abs(endpoint.y - gatewayCenterY) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at LEFT corner, no adjustment`);\n    return endpoint;\n  }\n  // Right corner: x at right edge AND y at center\n  if (Math.abs(endpoint.x - (gatewayBounds.x + gatewayBounds.width)) < tolerance &&\n      Math.abs(endpoint.y - gatewayCenterY) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at RIGHT corner, no adjustment`);\n    return endpoint;\n  }\n  // Top corner: y at top edge AND x at center\n  if (Math.abs(endpoint.y - gatewayBounds.y) < tolerance &&\n      Math.abs(endpoint.x - gatewayCenterX) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at TOP corner, no adjustment`);\n    return endpoint;\n  }\n  // Bottom corner: y at bottom edge AND x at center\n  if (Math.abs(endpoint.y - (gatewayBounds.y + gatewayBounds.height)) < tolerance &&\n      Math.abs(endpoint.x - gatewayCenterX) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at BOTTOM corner, no adjustment`);\n    return endpoint;\n  }\n\n  if (isDebugEnabled()) {\n    console.log(`  -> NOT at corner, will adjust`);\n  }\n\n  // Endpoint is NOT at a corner - calculate intersection with diamond edge\n  const result = calculateDiamondIntersection(\n    endpoint,\n    gatewayBounds,\n    gatewayCenterX,\n    gatewayCenterY,\n    isSource,\n    adjacentPoint\n  );\n  if (isDebugEnabled()) {\n    console.log(`  -> Adjusted to: (${result.x}, ${result.y})`);\n  }\n  return result;\n}\n\n/**\n * Calculate the intersection point with the diamond edge.\n * The diamond is defined by connecting the midpoints of the bounding box edges.\n *\n * @param endpoint - The current endpoint position\n * @param gatewayBounds - The bounding box of the gateway\n * @param gatewayCenterX - X coordinate of gateway center\n * @param gatewayCenterY - Y coordinate of gateway center\n * @param isSource - Whether this endpoint is the source of the edge\n * @param adjacentPoint - The adjacent point on the edge\n * @returns The intersection point on the diamond edge\n */\nexport function calculateDiamondIntersection(\n  endpoint: Point,\n  gatewayBounds: Bounds,\n  gatewayCenterX: number,\n  gatewayCenterY: number,\n  isSource: boolean,\n  adjacentPoint: Point\n): Point {\n  const tolerance = 1;\n\n  const leftCorner = { x: gatewayBounds.x, y: gatewayCenterY };\n  const rightCorner = { x: gatewayBounds.x + gatewayBounds.width, y: gatewayCenterY };\n  const topCorner = { x: gatewayCenterX, y: gatewayBounds.y };\n  const bottomCorner = { x: gatewayCenterX, y: gatewayBounds.y + gatewayBounds.height };\n\n  // Determine which side based on endpoint position relative to gateway\n  const isOnLeftEdge = Math.abs(endpoint.x - gatewayBounds.x) < tolerance;\n  const isOnRightEdge = Math.abs(endpoint.x - (gatewayBounds.x + gatewayBounds.width)) < tolerance;\n  const isOnTopEdge = Math.abs(endpoint.y - gatewayBounds.y) < tolerance;\n  const isOnBottomEdge = Math.abs(endpoint.y - (gatewayBounds.y + gatewayBounds.height)) < tolerance;\n\n  const halfWidth = gatewayBounds.width / 2;\n  const halfHeight = gatewayBounds.height / 2;\n\n  if (isOnLeftEdge || isOnRightEdge) {\n    // Endpoint is on left or right edge of bounding box but not at corner\n    // Calculate diamond edge intersection at this Y position\n    const yDistFromCenter = Math.abs(endpoint.y - gatewayCenterY);\n\n    if (yDistFromCenter >= halfHeight) {\n      // Outside diamond vertically - snap to corner\n      return isOnLeftEdge ? leftCorner : rightCorner;\n    }\n\n    // Diamond edge equation: |x - centerX| / halfWidth + |y - centerY| / halfHeight = 1\n    const xOffsetFromCenter = halfWidth * (1 - yDistFromCenter / halfHeight);\n    const intersectX = isOnLeftEdge\n      ? gatewayCenterX - xOffsetFromCenter\n      : gatewayCenterX + xOffsetFromCenter;\n\n    return { x: intersectX, y: endpoint.y };\n  }\n\n  if (isOnTopEdge || isOnBottomEdge) {\n    // Endpoint is on top or bottom edge of bounding box but not at corner\n    // Calculate diamond edge intersection at this X position\n    const xDistFromCenter = Math.abs(endpoint.x - gatewayCenterX);\n\n    if (xDistFromCenter >= halfWidth) {\n      // Outside diamond horizontally - snap to corner\n      return isOnTopEdge ? topCorner : bottomCorner;\n    }\n\n    const yOffsetFromCenter = halfHeight * (1 - xDistFromCenter / halfWidth);\n    const intersectY = isOnTopEdge\n      ? gatewayCenterY - yOffsetFromCenter\n      : gatewayCenterY + yOffsetFromCenter;\n\n    return { x: endpoint.x, y: intersectY };\n  }\n\n  // Endpoint is not on any edge - use approach direction to determine corner\n  const dx = isSource ? adjacentPoint.x - endpoint.x : endpoint.x - adjacentPoint.x;\n  const dy = isSource ? adjacentPoint.y - endpoint.y : endpoint.y - adjacentPoint.y;\n\n  if (Math.abs(dx) > Math.abs(dy)) {\n    // Horizontal approach\n    if (isSource) {\n      return dx > 0 ? rightCorner : leftCorner;\n    } else {\n      return dx > 0 ? leftCorner : rightCorner;\n    }\n  } else {\n    // Vertical approach\n    if (isSource) {\n      return dy > 0 ? bottomCorner : topCorner;\n    } else {\n      return dy > 0 ? topCorner : bottomCorner;\n    }\n  }\n}\n\n/**\n * Get the four corner points of a gateway diamond.\n *\n * @param gatewayBounds - The bounding box of the gateway\n * @returns Object containing all four corner points\n */\nexport function getDiamondCorners(gatewayBounds: Bounds): {\n  left: Point;\n  right: Point;\n  top: Point;\n  bottom: Point;\n} {\n  const centerX = gatewayBounds.x + gatewayBounds.width / 2;\n  const centerY = gatewayBounds.y + gatewayBounds.height / 2;\n\n  return {\n    left: { x: gatewayBounds.x, y: centerY },\n    right: { x: gatewayBounds.x + gatewayBounds.width, y: centerY },\n    top: { x: centerX, y: gatewayBounds.y },\n    bottom: { x: centerX, y: gatewayBounds.y + gatewayBounds.height },\n  };\n}\n\n/**\n * Check if a point is on the diamond edge (within tolerance).\n *\n * @param point - The point to check\n * @param gatewayBounds - The bounding box of the gateway\n * @param tolerance - Distance tolerance for edge detection\n * @returns True if the point is on the diamond edge\n */\nexport function isPointOnDiamondEdge(\n  point: Point,\n  gatewayBounds: Bounds,\n  tolerance: number = 2\n): boolean {\n  const centerX = gatewayBounds.x + gatewayBounds.width / 2;\n  const centerY = gatewayBounds.y + gatewayBounds.height / 2;\n  const halfWidth = gatewayBounds.width / 2;\n  const halfHeight = gatewayBounds.height / 2;\n\n  // Diamond edge equation: |x - centerX| / halfWidth + |y - centerY| / halfHeight = 1\n  // Check if point satisfies this equation within tolerance\n  const normalizedX = Math.abs(point.x - centerX) / halfWidth;\n  const normalizedY = Math.abs(point.y - centerY) / halfHeight;\n  const edgeValue = normalizedX + normalizedY;\n\n  return Math.abs(edgeValue - 1) < tolerance / Math.min(halfWidth, halfHeight);\n}\n","/**\n * Default ELK Layout Options\n * Optimized for BPMN diagram layout\n */\n\nimport type { ElkLayoutOptions } from '../types';\n\nexport const DEFAULT_ELK_OPTIONS: ElkLayoutOptions = {\n  // === Basic Configuration ===\n  'elk.algorithm': 'layered',\n  'elk.direction': 'RIGHT',\n\n  // === Layer Assignment ===\n  // NETWORK_SIMPLEX provides better layer distribution than LONGEST_PATH\n  'elk.layered.layering.strategy': 'NETWORK_SIMPLEX',\n\n  // === Crossing Minimization ===\n  'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',\n  // TWO_SIDED greedy switch improves crossing reduction\n  'elk.layered.crossingMinimization.greedySwitch.type': 'TWO_SIDED',\n\n  // === Node Placement ===\n  // BRANDES_KOEPF provides better vertical alignment than NETWORK_SIMPLEX\n  'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF',\n  // Use BALANCED alignment for symmetric layouts\n  'elk.layered.nodePlacement.bk.fixedAlignment': 'BALANCED',\n\n  // === Edge Routing ===\n  'elk.edgeRouting': 'ORTHOGONAL',\n  // Distribute self-loops evenly\n  'elk.layered.edgeRouting.selfLoopDistribution': 'EQUALLY',\n\n  // === Edge Labels ===\n  // Place edge labels at the center of the edge\n  'elk.edgeLabels.placement': 'CENTER',\n  // Ensure labels don't overlap with nodes or other labels\n  'elk.spacing.labelLabel': 5,\n  'elk.spacing.labelNode': 10,\n  'elk.spacing.edgeLabel': 10,\n\n  // === Spacing (increased for better readability) ===\n  'elk.spacing.nodeNode': 60,\n  'elk.spacing.edgeNode': 40,\n  'elk.spacing.edgeEdge': 25,\n  'elk.layered.spacing.nodeNodeBetweenLayers': 100,\n  'elk.layered.spacing.edgeNodeBetweenLayers': 40,\n  'elk.layered.spacing.edgeEdgeBetweenLayers': 25,\n  // Disconnected components (e.g. event-only test fixtures, ad-hoc islands)\n  // need their own breathing room or they collapse on top of one another.\n  'elk.spacing.componentComponent': 50,\n\n  // === Hierarchy Handling ===\n  'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n\n  // === Model Order ===\n  // Consider both node and edge order from the input model\n  'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES',\n\n  // === Compaction ===\n  // Compact connected components together\n  'elk.layered.compaction.connectedComponents': true,\n\n  // === Alignment ===\n  // Center alignment for cleaner appearance\n  'elk.alignment': 'CENTER',\n};\n\n/**\n * Merge user options with default options\n */\nexport function mergeElkOptions(\n  userOptions?: ElkLayoutOptions,\n  graphOptions?: ElkLayoutOptions\n): ElkLayoutOptions {\n  return {\n    ...DEFAULT_ELK_OPTIONS,\n    ...graphOptions,\n    ...userOptions,\n  };\n}\n","/**\n * ELK Graph Preparer\n * Prepares BPMN graphs for ELK layout by:\n * - Merging layout options\n * - Converting to ELK-compatible format\n * - Flattening pool/lane structures when needed for cross-pool edges\n * - Handling boundary events as siblings for proper edge routing\n * - Identifying main flow nodes for layout priority\n */\n\nimport type { ElkNode, ElkExtendedEdge, LayoutOptions } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, BoundaryEventInfo } from '../../types/internal';\nimport { mergeElkOptions } from '../default-options';\nimport { SizeCalculator } from '../size-calculator';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Handler for preparing graphs for ELK layout\n */\nexport class ElkGraphPreparer {\n  private sizeCalculator: SizeCalculator;\n\n  constructor() {\n    this.sizeCalculator = new SizeCalculator();\n  }\n\n  /**\n   * Prepare the graph for ELK layout\n   */\n  prepare(\n    graph: ElkBpmnGraph,\n    userOptions: Record<string, unknown> = {},\n    boundaryEventTargetIds: Set<string> = new Set()\n  ): ElkNode {\n    let layoutOptions = mergeElkOptions(userOptions as Record<string, string | number | boolean | undefined>, graph.layoutOptions);\n\n    // Check if this graph contains a cross-pool collaboration\n    // If so, force RIGHT direction for better horizontal layout\n    if (this.hasCrossPoolCollaboration(graph)) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.direction': 'RIGHT',\n      };\n    }\n\n    // Identify main flow nodes to give them layout priority\n    const mainFlowNodes = this.identifyMainFlowNodes(graph, boundaryEventTargetIds);\n\n    const root: ElkNode = {\n      id: graph.id ?? 'root',\n      layoutOptions: layoutOptions as LayoutOptions,\n      children: this.prepareChildrenForElk(graph.children, boundaryEventTargetIds, mainFlowNodes),\n    };\n\n    // BPMN link events are paired by `linkEventDefinition.name` and act like\n    // gotos: a throw exits the visible flow and a catch with the same name\n    // resumes it elsewhere. ELK has no way to know about this relationship,\n    // so without help it scatters the disconnected events. Add invisible\n    // edges between paired throw/catch events to bring them close together.\n    // The edges are stripped from the BPMN output by the result merger.\n    this.addLinkEventPairingEdges(root);\n\n    return root;\n  }\n\n  /**\n   * Walk all processes / containers and add invisible ELK edges between\n   * link-throw and link-catch events that share the same linkEventDefinition\n   * name. Each edge is marked with `_isLinkPair: true` so the BPMN merger\n   * can drop it before serialization.\n   */\n  private addLinkEventPairingEdges(root: ElkNode): void {\n    const throwsByLinkName = new Map<string, string[]>();\n    const catchesByLinkName = new Map<string, string[]>();\n    let containerWithLinks: ElkNode | undefined;\n\n    const walk = (node: ElkNode, parent: ElkNode | undefined) => {\n      const bpmn = (node as ElkNode & { bpmn?: { type?: string; eventDefinitionType?: string; linkEventDefinition?: { name?: string } } }).bpmn;\n      if (bpmn?.eventDefinitionType === 'link') {\n        const linkName = bpmn.linkEventDefinition?.name;\n        if (linkName && parent) {\n          containerWithLinks ??= parent;\n          if (bpmn.type === 'intermediateThrowEvent') {\n            (throwsByLinkName.get(linkName) ?? throwsByLinkName.set(linkName, []).get(linkName)!).push(node.id);\n          } else if (bpmn.type === 'intermediateCatchEvent') {\n            (catchesByLinkName.get(linkName) ?? catchesByLinkName.set(linkName, []).get(linkName)!).push(node.id);\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) walk(child, node);\n      }\n    };\n    walk(root, undefined);\n\n    if (!containerWithLinks || throwsByLinkName.size === 0) return;\n\n    containerWithLinks.edges ??= [];\n    let pairCounter = 0;\n    for (const [linkName, throws] of throwsByLinkName) {\n      const catches = catchesByLinkName.get(linkName) ?? [];\n      for (const throwId of throws) {\n        for (const catchId of catches) {\n          const edge: ElkExtendedEdge & { _isLinkPair?: boolean } = {\n            id: `_link_pair_${pairCounter++}_${throwId}_${catchId}`,\n            sources: [throwId],\n            targets: [catchId],\n            _isLinkPair: true,\n          };\n          containerWithLinks.edges.push(edge);\n        }\n      }\n    }\n  }\n\n  /**\n   * Check if the graph contains a collaboration with cross-pool sequence flows\n   */\n  hasCrossPoolCollaboration(graph: ElkBpmnGraph): boolean {\n    if (!graph.children) return false;\n\n    for (const child of graph.children) {\n      const node = child as unknown as NodeWithBpmn;\n      if (node.bpmn?.type !== 'collaboration') continue;\n\n      // Check if collaboration has multiple pools\n      const pools = (node.children as NodeWithBpmn[] | undefined)?.filter(\n        c => c.bpmn?.type === 'participant'\n      ) ?? [];\n      if (pools.length <= 1) continue;\n\n      // Check if collaboration has cross-pool sequence flows\n      const hasCrossPoolFlows = node.edges?.some(\n        edge => edge.bpmn?.type === 'sequenceFlow' ||\n                edge.bpmn?.type === 'dataInputAssociation' ||\n                edge.bpmn?.type === 'dataOutputAssociation'\n      );\n\n      if (hasCrossPoolFlows) return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Collect all boundary event target IDs from boundary event info\n   */\n  collectBoundaryEventTargetIds(boundaryEventInfo: Map<string, BoundaryEventInfo>): Set<string> {\n    const targetIds = new Set<string>();\n    for (const [_beId, info] of boundaryEventInfo) {\n      for (const targetId of info.targets) {\n        targetIds.add(targetId);\n      }\n    }\n    return targetIds;\n  }\n\n  /**\n   * Collect all boundary event IDs and their target nodes from edges\n   */\n  collectBoundaryEventTargets(node: NodeWithBpmn): Set<string> {\n    const boundaryEventIds = new Set<string>();\n    const targetNodeIds = new Set<string>();\n\n    // Collect boundary event IDs from this node and children\n    const collectBoundaryEventIds = (n: NodeWithBpmn) => {\n      if (n.boundaryEvents) {\n        for (const be of n.boundaryEvents) {\n          boundaryEventIds.add(be.id);\n        }\n      }\n      if (n.children) {\n        for (const child of n.children) {\n          collectBoundaryEventIds(child as NodeWithBpmn);\n        }\n      }\n    };\n    collectBoundaryEventIds(node);\n\n    // Find edges where source is a boundary event\n    const findTargets = (n: NodeWithBpmn) => {\n      if (n.edges) {\n        for (const edge of n.edges) {\n          const sourceId = edge.sources[0];\n          if (boundaryEventIds.has(sourceId)) {\n            targetNodeIds.add(edge.targets[0]);\n          }\n        }\n      }\n      if (n.children) {\n        for (const child of n.children) {\n          findTargets(child as NodeWithBpmn);\n        }\n      }\n    };\n    findTargets(node);\n\n    return targetNodeIds;\n  }\n\n  /**\n   * Identify main flow nodes - nodes that are in the primary path from start to end,\n   * not including boundary event branches.\n   * Main flow nodes should be prioritized in layout to stay at the top.\n   */\n  identifyMainFlowNodes(graph: ElkBpmnGraph, boundaryEventTargetIds: Set<string>): Set<string> {\n    const mainFlowNodes = new Set<string>();\n    const edgeMap = new Map<string, string[]>(); // source -> targets\n    const boundaryEventIds = new Set<string>();\n\n    // Collect all boundary event IDs and edges\n    const collectInfo = (node: NodeWithBpmn) => {\n      if (node.boundaryEvents) {\n        for (const be of node.boundaryEvents) {\n          boundaryEventIds.add(be.id);\n        }\n      }\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const source = edge.sources?.[0];\n          const target = edge.targets?.[0];\n          if (source && target) {\n            if (!edgeMap.has(source)) {\n              edgeMap.set(source, []);\n            }\n            edgeMap.get(source)!.push(target);\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          collectInfo(child as NodeWithBpmn);\n        }\n      }\n    };\n\n    // Find start events\n    const findStartEvents = (node: NodeWithBpmn): string[] => {\n      const starts: string[] = [];\n      if (node.bpmn?.type === 'startEvent') {\n        starts.push(node.id);\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          starts.push(...findStartEvents(child as NodeWithBpmn));\n        }\n      }\n      return starts;\n    };\n\n    // Traverse from start events, following only non-boundary-event edges\n    const traverseMainFlow = (nodeId: string) => {\n      if (mainFlowNodes.has(nodeId)) return;\n      // Don't include boundary event targets as main flow\n      if (boundaryEventTargetIds.has(nodeId)) return;\n      // Don't include boundary events themselves\n      if (boundaryEventIds.has(nodeId)) return;\n\n      mainFlowNodes.add(nodeId);\n\n      const targets = edgeMap.get(nodeId) || [];\n      for (const targetId of targets) {\n        // Skip if this edge originates from a boundary event\n        if (!boundaryEventIds.has(nodeId)) {\n          traverseMainFlow(targetId);\n        }\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      collectInfo(child as NodeWithBpmn);\n    }\n\n    const startEvents = findStartEvents({ children: graph.children } as NodeWithBpmn);\n    for (const startId of startEvents) {\n      traverseMainFlow(startId);\n    }\n\n    if (isDebugEnabled()) {\n      console.log(`[BPMN] Main flow nodes: ${Array.from(mainFlowNodes).join(', ')}`);\n    }\n\n    return mainFlowNodes;\n  }\n\n  /**\n   * Prepare children for ELK layout\n   */\n  private prepareChildrenForElk(\n    nodes: ElkBpmnGraph['children'],\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): ElkNode[] {\n    if (!nodes) return [];\n\n    const result: ElkNode[] = [];\n\n    for (const child of nodes) {\n      const node = child as unknown as NodeWithBpmn;\n      result.push(this.prepareNodeForElk(node, boundaryEventTargetIds, mainFlowNodes));\n\n      // Add boundary events as sibling nodes (not children of the task)\n      // This allows ELK to route edges from boundary events correctly\n      if (node.boundaryEvents && node.boundaryEvents.length > 0) {\n        for (const be of node.boundaryEvents) {\n          result.push({\n            id: be.id,\n            width: be.width ?? 36,\n            height: be.height ?? 36,\n          });\n        }\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Prepare a single node for ELK layout\n   */\n  private prepareNodeForElk(\n    node: NodeWithBpmn,\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): ElkNode {\n    let layoutOptions = node.layoutOptions as LayoutOptions | undefined;\n\n    // Add ELK layer constraints for start/end events to ensure proper flow direction\n    // startEvent should be in the first layer (leftmost in RIGHT direction)\n    // endEvent should be in the last layer (rightmost in RIGHT direction)\n    const nodeType = node.bpmn?.type;\n    if (nodeType === 'startEvent') {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.layered.layering.layerConstraint': 'FIRST',\n      } as LayoutOptions;\n    } else if (nodeType === 'endEvent') {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.layered.layering.layerConstraint': 'LAST',\n      } as LayoutOptions;\n    }\n\n    // Calculate extra height for nodes with ioSpecification to reserve space for data objects\n    // These constants must match the values in diagram-builder.ts buildIoSpecificationShapes()\n    const ioSpec = node.bpmn?.ioSpecification;\n    let ioSpecExtraHeight = 0;\n    if (ioSpec) {\n      const dataInputs = ioSpec.dataInputs ?? [];\n      const dataOutputs = ioSpec.dataOutputs ?? [];\n      const maxCount = Math.max(dataInputs.length, dataOutputs.length);\n\n      if (maxCount > 0) {\n        // Constants matching diagram-builder.ts\n        const dataHeight = 50;\n        const gapBelow = 20;\n        const verticalSpacing = 24;\n        const labelHeight = 14;\n\n        // Calculate required extra height for ELK layout:\n        // gapBelow + maxCount * (dataHeight + verticalSpacing) + labelHeight\n        ioSpecExtraHeight = gapBelow + maxCount * (dataHeight + verticalSpacing) + labelHeight;\n\n        if (isDebugEnabled()) {\n          console.log(`[BPMN] Adding extra height ${ioSpecExtraHeight} for node ${node.id} with ioSpecification`);\n        }\n      }\n    }\n\n    // Give main flow nodes higher priority so ELK keeps them aligned\n    if (mainFlowNodes.has(node.id) && !boundaryEventTargetIds.has(node.id)) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.priority': '10',\n      } as LayoutOptions;\n    }\n\n    // Give boundary event targets lower priority\n    // Actual positioning below main flow is done in post-processing\n    if (boundaryEventTargetIds.has(node.id)) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.priority': '1',\n      } as LayoutOptions;\n    }\n\n\n\n    // For expanded subprocesses, add top padding for the label header\n    const isExpandedSubprocess = node.bpmn?.isExpanded === true &&\n      (node.bpmn?.type === 'subProcess' || node.bpmn?.type === 'transaction' ||\n       node.bpmn?.type === 'adHocSubProcess' || node.bpmn?.type === 'eventSubProcess');\n\n    // Save user-specified padding to preserve it\n    const userPadding = layoutOptions?.['elk.padding'];\n\n    if (isExpandedSubprocess) {\n      layoutOptions = {\n        'elk.padding': '[top=30,left=12,bottom=30,right=12]',\n        ...layoutOptions,\n      } as LayoutOptions;\n      // Restore user padding if specified (it takes precedence)\n      if (userPadding) {\n        layoutOptions['elk.padding'] = userPadding;\n      }\n    }\n\n    // Ad-hoc subprocess: its children are tasks that may execute in any\n    // order (BPMN semantic). They typically have no sequence flows between\n    // them, so the default `layered` algorithm stacks them in a single\n    // column, which looks wrong. Pack them in a grid instead.\n    if (node.bpmn?.type === 'adHocSubProcess' && node.bpmn?.isExpanded) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'rectpacking',\n        'elk.padding': '[top=30,left=12,bottom=12,right=12]',\n        'elk.spacing.nodeNode': 30,\n        'elk.aspectRatio': '2.0',\n      } as LayoutOptions;\n    }\n\n    // Check if this is a collaboration with multiple pools and cross-pool sequence flow edges\n    // Only flatten nodes when there are actual sequenceFlow edges crossing pools\n    // (messageFlow edges are normal for collaborations and don't require flattening)\n    const isCollaboration = node.bpmn?.type === 'collaboration';\n    const hasMultiplePools = isCollaboration &&\n      ((node.children as NodeWithBpmn[] | undefined)?.filter((c) => c.bpmn?.type === 'participant').length ?? 0) > 1;\n\n    // Check if any collaboration-level edges are sequenceFlow (cross-pool flow)\n    const hasCrossPoolSequenceFlows = isCollaboration && node.edges?.some(\n      (edge) => edge.bpmn?.type === 'sequenceFlow' ||\n                edge.bpmn?.type === 'dataInputAssociation' ||\n                edge.bpmn?.type === 'dataOutputAssociation'\n    );\n\n    if (isCollaboration && hasCrossPoolSequenceFlows && hasMultiplePools) {\n      // For collaborations with cross-pool edges, flatten all pool contents\n      // to collaboration level for unified layout\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'layered',\n        'elk.direction': 'RIGHT',\n        'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n        'elk.padding': '[top=12,left=12,bottom=12,right=12]',\n      } as LayoutOptions;\n\n      const elkNode: ElkNode & { bpmn?: NodeWithBpmn['bpmn'] } = {\n        id: node.id,\n        width: node.width,\n        height: node.height,\n        layoutOptions,\n        bpmn: node.bpmn,\n      };\n\n      // Flatten all pool contents to collaboration level\n      const childNodes: ElkNode[] = [];\n      this.extractNodesFromPools(node.children as NodeWithBpmn[], childNodes, boundaryEventTargetIds, mainFlowNodes);\n      elkNode.children = childNodes;\n\n      // Copy edges to ELK format\n      if (node.edges && node.edges.length > 0) {\n        elkNode.edges = this.prepareEdges(node.edges);\n      }\n\n      return elkNode;\n    }\n\n    // Check if this is a pool (participant)\n    const isPool = node.bpmn?.type === 'participant';\n    const hasLanes = isPool &&\n      (node.children as NodeWithBpmn[] | undefined)?.some((c) => c.bpmn?.type === 'lane');\n\n    if (hasLanes) {\n      // For pools with lanes, use a different layout strategy:\n      // - Use partitioning to create horizontal swim lanes (rows, not columns)\n      // - Set direction to RIGHT for flow within lanes\n      // - Use 'elk.partitioning.activate' with vertical partitions\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'layered',\n        'elk.direction': 'RIGHT',\n        // Remove partitioning - we'll handle lane stacking differently\n        'elk.partitioning.activate': 'false',\n        // Add padding for lane header (left side)\n        'elk.padding': '[top=12,left=30,bottom=12,right=12]',\n        'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n      } as LayoutOptions;\n    } else if (isPool) {\n      // For pools without lanes, still add left padding for pool label\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'layered',\n        'elk.direction': 'RIGHT',\n        // Add padding for pool header (left side) - 55px to accommodate vertical label\n        'elk.padding': '[top=12,left=55,bottom=12,right=12]',\n      } as LayoutOptions;\n    }\n\n    // Check if this is a lane\n    const isLane = node.bpmn?.type === 'lane';\n    if (isLane) {\n      // For lanes, don't set separate layout algorithm - let parent pool handle layout\n      // Just set padding for content spacing\n      layoutOptions = {\n        'elk.padding': '[top=12,left=12,bottom=12,right=12]',\n      } as LayoutOptions;\n    }\n\n    // For nodes with ioSpecification, increase height for ELK layout to reserve space\n    // Store original height in bpmn metadata for rendering\n    const originalHeight = node.height ?? 80;\n\n    // Events render their label BELOW the icon. ELK doesn't know that, so\n    // two stacked event-only columns get cramped — each event's label\n    // nearly touches the next event's icon. Inflate the ELK-seen height to\n    // reserve the label area; diagram-builder still draws a 36×36 shape via\n    // _visualHeight.\n    let eventLabelExtra = 0;\n    const isEventType = nodeType === 'startEvent' || nodeType === 'endEvent' ||\n      nodeType === 'intermediateThrowEvent' || nodeType === 'intermediateCatchEvent' ||\n      nodeType === 'boundaryEvent';\n    const hasEventLabel = !!(node.bpmn?.name || node.labels?.[0]?.text);\n    if (isEventType && hasEventLabel) {\n      eventLabelExtra = 18; // 4 px gap + ~14 px label line\n    }\n\n    const elkHeight = originalHeight + ioSpecExtraHeight + eventLabelExtra;\n\n    // For gateways with a long label, inflate the ELK-seen width so ELK\n    // spaces neighbors far enough apart that labels don't collide. The\n    // diamond keeps its true visual width; diagram-builder centers it\n    // within the inflated bounds using _visualWidth.\n    const originalWidth = node.width ?? 100;\n    let elkWidth = originalWidth;\n    let visualWidth: number | undefined;\n    if (nodeType?.includes('Gateway')) {\n      const labelText = node.bpmn?.name ?? node.labels?.[0]?.text ?? '';\n      if (labelText) {\n        const labelWidth = this.sizeCalculator.estimateLabelWidth(labelText);\n        const required = labelWidth + 16; // small breathing room\n        if (required > originalWidth) {\n          elkWidth = required;\n          visualWidth = originalWidth;\n        }\n      }\n    }\n\n    const needsVisualHeight = ioSpecExtraHeight > 0 || eventLabelExtra > 0;\n    const bpmnWithVisualHeight = (needsVisualHeight || visualWidth !== undefined)\n      ? {\n          ...node.bpmn,\n          ...(needsVisualHeight ? { _visualHeight: originalHeight } : {}),\n          ...(visualWidth !== undefined ? { _visualWidth: visualWidth } : {}),\n        }\n      : node.bpmn;\n\n    const elkNode: ElkNode & { bpmn?: NodeWithBpmn['bpmn'] } = {\n      id: node.id,\n      width: elkWidth,\n      height: elkHeight,\n      layoutOptions,\n      bpmn: bpmnWithVisualHeight,\n    };\n\n    // Process children (including boundary events as siblings)\n    if (node.children && node.children.length > 0) {\n      const childNodes: ElkNode[] = [];\n\n      // For pools with lanes, flatten all lane contents to pool level for unified layout\n      // This allows ELK to consider cross-lane edges when positioning nodes\n      if (hasLanes) {\n        // Recursively extract all flow nodes from lanes (including nested lanes)\n        this.extractNodesFromLanes(node.children as NodeWithBpmn[], childNodes, boundaryEventTargetIds, mainFlowNodes);\n      } else {\n        // Normal processing for non-lane containers\n        for (const child of node.children) {\n          const childNode = child as NodeWithBpmn;\n          childNodes.push(this.prepareNodeForElk(childNode, boundaryEventTargetIds, mainFlowNodes));\n\n          // Add boundary events as siblings\n          if (childNode.boundaryEvents && childNode.boundaryEvents.length > 0) {\n            for (const be of childNode.boundaryEvents) {\n              childNodes.push({\n                id: be.id,\n                width: be.width ?? 36,\n                height: be.height ?? 36,\n                bpmn: be.bpmn,\n              } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n            }\n          }\n        }\n      }\n      elkNode.children = childNodes;\n    }\n\n    // Process edges\n    if (node.edges && node.edges.length > 0) {\n      elkNode.edges = this.prepareEdges(node.edges);\n    }\n\n    // Process labels - ensure all labels have dimensions (ELK requires this)\n    if (node.labels && node.labels.length > 0) {\n      elkNode.labels = node.labels.map((l) => ({\n        text: l.text,\n        width: l.width ?? this.sizeCalculator.estimateLabelWidth(l.text),\n        height: l.height ?? 14,\n      }));\n    }\n\n    // Process ports\n    if (node.ports && node.ports.length > 0) {\n      elkNode.ports = node.ports.map((p) => ({\n        id: p.id,\n        width: p.width ?? 10,\n        height: p.height ?? 10,\n      }));\n    }\n\n    return elkNode;\n  }\n\n  /**\n   * Prepare edges for ELK format\n   */\n  private prepareEdges(edges: NodeWithBpmn['edges']): ElkExtendedEdge[] {\n    if (!edges) return [];\n\n    return edges.map((edge) => ({\n      id: edge.id,\n      sources: edge.sources,\n      targets: edge.targets,\n      layoutOptions: edge.layoutOptions as LayoutOptions | undefined,\n      labels: edge.labels?.map((l) => ({\n        text: l.text,\n        width: l.width ?? 50,\n        height: l.height ?? 14,\n      })),\n    })) as ElkExtendedEdge[];\n  }\n\n  /**\n   * Extract all flow nodes from pools to flatten them for unified layout\n   * This is used for collaborations with cross-pool edges\n   */\n  private extractNodesFromPools(\n    children: NodeWithBpmn[],\n    result: ElkNode[],\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): void {\n    for (const child of children) {\n      if (child.bpmn?.type === 'participant') {\n        // Check if this is an empty/black box pool\n        const isEmpty = !child.children || child.children.length === 0;\n\n        if (isEmpty) {\n          // Add the pool itself as a node (for message flows targeting the pool)\n          result.push({\n            id: child.id,\n            width: child.width ?? 680,\n            height: child.height ?? 60,\n            bpmn: child.bpmn,\n          } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n        } else {\n          // Extract nodes from this pool\n          // Check if pool has lanes\n          const hasLanes = child.children!.some((c) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n          if (hasLanes) {\n            this.extractNodesFromLanes(child.children! as NodeWithBpmn[], result, boundaryEventTargetIds, mainFlowNodes);\n          } else {\n            // Direct children of pool (no lanes)\n            for (const poolChild of child.children!) {\n              const node = poolChild as NodeWithBpmn;\n              result.push(this.prepareNodeForElk(node, boundaryEventTargetIds, mainFlowNodes));\n\n              // Add boundary events as siblings\n              if (node.boundaryEvents && node.boundaryEvents.length > 0) {\n                for (const be of node.boundaryEvents) {\n                  result.push({\n                    id: be.id,\n                    width: be.width ?? 36,\n                    height: be.height ?? 36,\n                    bpmn: be.bpmn,\n                  } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Recursively extract all flow nodes from lanes (including nested lanes)\n   * and add them to the result array for unified ELK layout\n   */\n  private extractNodesFromLanes(\n    children: NodeWithBpmn[],\n    result: ElkNode[],\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): void {\n    for (const child of children) {\n      if (child.bpmn?.type === 'lane') {\n        // Recursively extract from nested lanes\n        if (child.children) {\n          this.extractNodesFromLanes(child.children as NodeWithBpmn[], result, boundaryEventTargetIds, mainFlowNodes);\n        }\n      } else {\n        // Non-lane node - add to result\n        result.push(this.prepareNodeForElk(child, boundaryEventTargetIds, mainFlowNodes));\n\n        // Add boundary events as siblings\n        if (child.boundaryEvents && child.boundaryEvents.length > 0) {\n          for (const be of child.boundaryEvents) {\n            result.push({\n              id: be.id,\n              width: be.width ?? 36,\n              height: be.height ?? 36,\n              bpmn: be.bpmn,\n            } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n          }\n        }\n      }\n    }\n  }\n}\n","/**\n * Result Merger\n * Merges ELK layout results back with original BPMN metadata.\n * Preserves BPMN-specific properties while applying layout coordinates.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph, LayoutedGraph } from '../../types';\nimport type { NodeWithBpmn } from '../../types/internal';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Handler for merging layout results with original BPMN data\n */\nexport class ResultMerger {\n  /**\n   * Merge ELK layout results back with original BPMN metadata\n   */\n  merge(original: ElkBpmnGraph, layouted: ElkNode): LayoutedGraph {\n    const result: LayoutedGraph = {\n      ...original,\n      x: layouted.x,\n      y: layouted.y,\n      width: layouted.width,\n      height: layouted.height,\n      children: [],\n    };\n\n    // Merge children by ID\n    if (original.children && layouted.children) {\n      const layoutedChildMap = new Map(layouted.children.map((c) => [c.id, c]));\n\n      result.children = original.children.map((origChild) => {\n        const layoutedChild = layoutedChildMap.get(origChild.id);\n        if (layoutedChild) {\n          return this.mergeNodeResults(\n            origChild as unknown as NodeWithBpmn,\n            layoutedChild\n          );\n        }\n        return origChild as unknown as LayoutedGraph['children'][number];\n      }) as LayoutedGraph['children'];\n    }\n\n    return result;\n  }\n\n  /**\n   * Merge a single node's layout results with original BPMN data\n   */\n  private mergeNodeResults(original: NodeWithBpmn, layouted: ElkNode): NodeWithBpmn {\n    // Propagate visual-size hints (set by elk-graph-preparer when ELK is\n    // given an inflated width/height to reserve label/data-object space).\n    // Without these, diagram-builder renders the inflated bounds and shapes\n    // like gateway diamonds stretch into wide flat rectangles.\n    const layoutedBpmn = (layouted as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] }).bpmn;\n    const visualHeight = layoutedBpmn?._visualHeight;\n    const visualWidth = layoutedBpmn?._visualWidth;\n    let mergedBpmn = original.bpmn;\n    if (visualHeight !== undefined || visualWidth !== undefined) {\n      mergedBpmn = { ...original.bpmn };\n      if (visualHeight !== undefined) mergedBpmn._visualHeight = visualHeight;\n      if (visualWidth !== undefined) mergedBpmn._visualWidth = visualWidth;\n    }\n\n    const result: NodeWithBpmn = {\n      ...original,\n      x: layouted.x ?? 0,\n      y: layouted.y ?? 0,\n      width: layouted.width ?? original.width,\n      height: layouted.height ?? original.height,\n      bpmn: mergedBpmn,\n    };\n\n    // Merge children\n    if (original.children && layouted.children) {\n      const layoutedChildMap = new Map(layouted.children.map((c) => [c.id, c]));\n\n      result.children = original.children.map((origChild) => {\n        const layoutedChild = layoutedChildMap.get((origChild as NodeWithBpmn).id);\n        if (layoutedChild) {\n          return this.mergeNodeResults(origChild as NodeWithBpmn, layoutedChild);\n        }\n        return origChild;\n      });\n    }\n\n    // Keep boundary events as-is (their positions are calculated in model-builder.ts)\n    if (original.boundaryEvents) {\n      result.boundaryEvents = original.boundaryEvents;\n    }\n\n    // Merge edges\n    if (original.edges && layouted.edges) {\n      result.edges = this.mergeEdges(original.edges, layouted.edges);\n    }\n\n    // Merge labels\n    if (original.labels && layouted.labels) {\n      result.labels = original.labels.map((label, idx) => {\n        const layoutedLabel = layouted.labels?.[idx];\n        if (layoutedLabel) {\n          return {\n            ...label,\n            x: layoutedLabel.x ?? 0,\n            y: layoutedLabel.y ?? 0,\n            width: layoutedLabel.width ?? label.width,\n            height: layoutedLabel.height ?? label.height,\n          };\n        }\n        return label;\n      });\n    }\n\n    return result;\n  }\n\n  /**\n   * Merge edge layout results\n   */\n  private mergeEdges(\n    originalEdges: NodeWithBpmn['edges'],\n    layoutedEdges: ElkExtendedEdge[]\n  ): NodeWithBpmn['edges'] {\n    if (!originalEdges) return undefined;\n\n    const layoutedEdgeMap = new Map(layoutedEdges.map((e) => [e.id, e]));\n\n    return originalEdges.map((origEdge) => {\n      const layoutedEdge = layoutedEdgeMap.get(origEdge.id);\n      if (layoutedEdge) {\n        if (isDebugEnabled() && layoutedEdge.sections?.[0]?.bendPoints?.length) {\n          console.log(`[BPMN] Merge ${origEdge.id}: bendPoints=${JSON.stringify(layoutedEdge.sections[0].bendPoints)}`);\n        }\n\n        const mergedEdge: typeof origEdge & { _absoluteCoords?: boolean; _poolRelativeCoords?: boolean } = {\n          ...origEdge,\n          sections: layoutedEdge.sections ?? [],\n          labels: origEdge.labels?.map((label, idx) => {\n            const layoutedLabel = layoutedEdge.labels?.[idx];\n            if (layoutedLabel) {\n              return {\n                ...label,\n                x: layoutedLabel.x ?? 0,\n                y: layoutedLabel.y ?? 0,\n                width: layoutedLabel.width ?? label.width ?? 50,\n                height: layoutedLabel.height ?? label.height ?? 14,\n              };\n            }\n            return label;\n          }),\n        };\n\n        // Preserve the _absoluteCoords flag for message flows\n        if ((layoutedEdge as { _absoluteCoords?: boolean })._absoluteCoords) {\n          mergedEdge._absoluteCoords = true;\n        }\n\n        // Preserve the _poolRelativeCoords flag for pool edges\n        if ((layoutedEdge as { _poolRelativeCoords?: boolean })._poolRelativeCoords) {\n          mergedEdge._poolRelativeCoords = true;\n        }\n\n        return mergedEdge;\n      }\n      return origEdge;\n    });\n  }\n}\n","/**\n * Reference Resolver\n * Builds incoming/outgoing references for BPMN flow nodes\n */\n\nimport type { LayoutedGraph } from '../types/elk-output';\n\ninterface EdgeInfo {\n  id: string;\n  sourceRef: string;\n  targetRef: string;\n  type: 'sequenceFlow' | 'messageFlow' | 'dataInputAssociation' | 'dataOutputAssociation' | 'association';\n}\n\ninterface NodeInfo {\n  id: string;\n  type: string;\n  parentId?: string;\n}\n\nexport class ReferenceResolver {\n  private nodeMap: Map<string, NodeInfo> = new Map();\n  private edgesBySource: Map<string, EdgeInfo[]> = new Map();\n  private edgesByTarget: Map<string, EdgeInfo[]> = new Map();\n  private allEdges: EdgeInfo[] = [];\n\n  /**\n   * Resolve all references in the graph\n   */\n  resolve(graph: LayoutedGraph): void {\n    this.clear();\n    this.indexGraph(graph);\n  }\n\n  /**\n   * Clear all cached data\n   */\n  clear(): void {\n    this.nodeMap.clear();\n    this.edgesBySource.clear();\n    this.edgesByTarget.clear();\n    this.allEdges = [];\n  }\n\n  /**\n   * Get incoming edge IDs for a node\n   */\n  getIncoming(nodeId: string): string[] {\n    const edges = this.edgesByTarget.get(nodeId);\n    return edges?.map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get outgoing edge IDs for a node\n   */\n  getOutgoing(nodeId: string): string[] {\n    const edges = this.edgesBySource.get(nodeId);\n    return edges?.map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get incoming sequence flows for a node\n   */\n  getIncomingSequenceFlows(nodeId: string): string[] {\n    const edges = this.edgesByTarget.get(nodeId);\n    return edges?.filter((e) => e.type === 'sequenceFlow').map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get outgoing sequence flows for a node\n   */\n  getOutgoingSequenceFlows(nodeId: string): string[] {\n    const edges = this.edgesBySource.get(nodeId);\n    return edges?.filter((e) => e.type === 'sequenceFlow').map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get all edges\n   */\n  getAllEdges(): EdgeInfo[] {\n    return this.allEdges;\n  }\n\n  /**\n   * Get node by ID\n   */\n  getNode(nodeId: string): NodeInfo | undefined {\n    return this.nodeMap.get(nodeId);\n  }\n\n  /**\n   * Get all nodes\n   */\n  getAllNodes(): Map<string, NodeInfo> {\n    return this.nodeMap;\n  }\n\n  /**\n   * Check if a node exists\n   */\n  hasNode(nodeId: string): boolean {\n    return this.nodeMap.has(nodeId);\n  }\n\n  /**\n   * Index the entire graph\n   */\n  private indexGraph(graph: LayoutedGraph): void {\n    for (const child of graph.children) {\n      this.indexNode(child as unknown as GraphNode);\n    }\n  }\n\n  /**\n   * Recursively index a node and its children\n   */\n  private indexNode(node: GraphNode, parentId?: string): void {\n    // Index the node itself (skip containers like collaboration)\n    if (node.bpmn && node.bpmn.type !== 'collaboration') {\n      this.nodeMap.set(node.id, {\n        id: node.id,\n        type: node.bpmn.type,\n        parentId,\n      });\n    }\n\n    // Index children\n    if (node.children) {\n      for (const child of node.children) {\n        this.indexNode(child as GraphNode, node.id);\n      }\n    }\n\n    // Index boundary events\n    if (node.boundaryEvents) {\n      for (const be of node.boundaryEvents) {\n        this.nodeMap.set(be.id, {\n          id: be.id,\n          type: 'boundaryEvent',\n          parentId: node.id,\n        });\n      }\n    }\n\n    // Index edges\n    if (node.edges) {\n      for (const edge of node.edges) {\n        this.indexEdge(edge);\n      }\n    }\n  }\n\n  /**\n   * Index an edge\n   */\n  private indexEdge(edge: GraphEdge): void {\n    const sourceRef = edge.sources[0];\n    const targetRef = edge.targets[0];\n\n    if (!sourceRef || !targetRef) return;\n\n    const edgeType = edge.bpmn?.type;\n    const validTypes = ['sequenceFlow', 'messageFlow', 'dataInputAssociation', 'dataOutputAssociation', 'association'] as const;\n    const edgeInfo: EdgeInfo = {\n      id: edge.id,\n      sourceRef,\n      targetRef,\n      type: (validTypes.includes(edgeType as typeof validTypes[number]) ? edgeType : 'sequenceFlow') as EdgeInfo['type'],\n    };\n\n    this.allEdges.push(edgeInfo);\n\n    // Index by source\n    if (!this.edgesBySource.has(sourceRef)) {\n      this.edgesBySource.set(sourceRef, []);\n    }\n    this.edgesBySource.get(sourceRef)!.push(edgeInfo);\n\n    // Index by target\n    if (!this.edgesByTarget.has(targetRef)) {\n      this.edgesByTarget.set(targetRef, []);\n    }\n    this.edgesByTarget.get(targetRef)!.push(edgeInfo);\n  }\n}\n\n// Internal types\ninterface GraphNode {\n  id: string;\n  bpmn?: { type: string };\n  children?: GraphNode[];\n  edges?: GraphEdge[];\n  boundaryEvents?: Array<{ id: string; bpmn: { type: string } }>;\n}\n\ninterface GraphEdge {\n  id: string;\n  sources: string[];\n  targets: string[];\n  bpmn?: { type: string };\n}\n","/**\n * Lane Resolver\n * Builds flowNodeRef arrays for BPMN lanes\n */\n\nexport interface LaneInfo {\n  id: string;\n  name?: string;\n  flowNodeRefs: string[];\n  childLaneSet?: LaneSetInfo;\n}\n\nexport interface LaneSetInfo {\n  id: string;\n  lanes: LaneInfo[];\n}\n\nexport class LaneResolver {\n  private laneIdCounter = 0;\n\n  /**\n   * Resolve lanes from a participant or process\n   */\n  resolve(container: ContainerNode): LaneSetInfo | undefined {\n    const lanes = this.findLanes(container.children);\n\n    if (lanes.length === 0) {\n      return undefined;\n    }\n\n    return {\n      id: this.generateLaneSetId(),\n      lanes: lanes.map((lane) => this.processLane(lane)),\n    };\n  }\n\n  /**\n   * Find all lanes in children\n   */\n  private findLanes(children?: ChildNode[]): LaneNode[] {\n    if (!children) return [];\n    return children.filter((c): c is LaneNode => c.bpmn?.type === 'lane');\n  }\n\n  /**\n   * Process a lane and collect all flow node refs\n   */\n  private processLane(lane: LaneNode): LaneInfo {\n    const flowNodeRefs = this.collectFlowNodeRefs(lane.children);\n    const nestedLanes = this.findLanes(lane.children);\n\n    const result: LaneInfo = {\n      id: lane.id,\n      name: lane.bpmn?.name,\n      flowNodeRefs,\n    };\n\n    // Handle nested lanes\n    if (nestedLanes.length > 0) {\n      result.childLaneSet = {\n        id: this.generateLaneSetId(),\n        lanes: nestedLanes.map((l) => this.processLane(l)),\n      };\n    }\n\n    return result;\n  }\n\n  /**\n   * Collect all flow node IDs within a lane (excluding nested lanes)\n   */\n  private collectFlowNodeRefs(children?: ChildNode[]): string[] {\n    if (!children) return [];\n\n    const refs: string[] = [];\n\n    for (const child of children) {\n      // Skip lanes - their content belongs to them\n      if (child.bpmn?.type === 'lane') {\n        continue;\n      }\n\n      // Add this node's ID\n      refs.push(child.id);\n\n      // For subprocesses, don't traverse children - they're internal\n      // Boundary events are still part of the lane though\n      if (child.boundaryEvents) {\n        for (const be of child.boundaryEvents) {\n          refs.push(be.id);\n        }\n      }\n    }\n\n    return refs;\n  }\n\n  /**\n   * Generate a unique lane set ID\n   */\n  private generateLaneSetId(): string {\n    return `LaneSet_${++this.laneIdCounter}`;\n  }\n\n  /**\n   * Reset the ID counter\n   */\n  reset(): void {\n    this.laneIdCounter = 0;\n  }\n}\n\n// Internal types\ninterface ChildNode {\n  id: string;\n  bpmn?: { type: string; name?: string };\n  children?: ChildNode[];\n  boundaryEvents?: Array<{ id: string }>;\n}\n\ninterface LaneNode extends ChildNode {\n  bpmn: { type: 'lane'; name?: string };\n}\n\ninterface ContainerNode {\n  id: string;\n  children?: ChildNode[];\n}\n","/**\n * Diagram Builder\n * Handles building the visual diagram (shapes and edges) from a layouted graph.\n * This module is responsible for converting layouted node positions into\n * BPMN DI (Diagram Interchange) format.\n */\n\nimport type { LayoutedGraph } from '../types/elk-output';\nimport type { IoSpecification } from '../types/elk-bpmn';\nimport { SUBPROCESS_TYPES } from '../types/bpmn-constants';\nimport type {\n  DiagramModel,\n  ShapeModel,\n  EdgeModel,\n  PointModel,\n  DefinitionsModel,\n  LayoutedNode,\n  LayoutedEdge,\n  NodePosition,\n  NodeOffset,\n  NodeBpmnInfo,\n} from './model-types';\nimport { isDebugEnabled } from '../utils/debug';\nimport {\n  adjustGatewayEndpoint,\n  distance,\n  calculatePathLength,\n} from '../layout/edge-routing';\n\n// ============================================================================\n// Diagram Builder\n// ============================================================================\n\nexport class DiagramBuilder {\n  // Map to track boundary event positions: id -> { x, y, width, height }\n  private boundaryEventPositions: Map<string, NodePosition> = new Map();\n  // Map to track all node positions for edge routing: id -> { x, y, width, height }\n  private nodePositions: Map<string, NodePosition> = new Map();\n  // Map to track the offset used for each node (for edge coordinate transformation)\n  private nodeOffsets: Map<string, NodeOffset> = new Map();\n  // Map to track node BPMN metadata for gateway detection\n  private nodeBpmn: Map<string, NodeBpmnInfo> = new Map();\n  // ioSpecification data objects: dataObjectId -> owner task id. Used so we\n  // know which data shapes belong to which task when routing edges, since data\n  // objects synthesized for a task should NOT be treated as obstacles for\n  // edges whose source/target is that same task.\n  private dataObjectOwners: Map<string, string> = new Map();\n  // List of already placed edge labels for collision detection\n  private placedEdgeLabels: Array<{ x: number; y: number; width: number; height: number }> = [];\n\n  /**\n   * Build the diagram model from a layouted graph\n   */\n  build(graph: LayoutedGraph, definitions: DefinitionsModel): DiagramModel {\n    // Reset placed edge labels for each build\n    this.placedEdgeLabels = [];\n    // Reset all maps\n    this.boundaryEventPositions.clear();\n    this.nodePositions.clear();\n    this.nodeOffsets.clear();\n    this.dataObjectOwners.clear();\n    this.nodeBpmn.clear();\n\n    const shapes: ShapeModel[] = [];\n    const edges: EdgeModel[] = [];\n\n    // Find the main bpmn element for the plane\n    const mainElement = definitions.rootElements[0];\n    if (!mainElement) {\n      throw new Error('Cannot create BPMN diagram: definitions.rootElements is empty. The graph must contain at least one process or collaboration.');\n    }\n    const planeElement = mainElement.type === 'collaboration' ? mainElement.id : mainElement.id;\n\n    // Build shapes and edges\n    for (const child of graph.children) {\n      this.collectShapesAndEdges(child as LayoutedNode, shapes, edges);\n    }\n\n    return {\n      id: `BPMNDiagram_${graph.id}`,\n      name: 'BPMNDiagram',\n      plane: {\n        id: `BPMNPlane_${graph.id}`,\n        bpmnElement: planeElement,\n        shapes,\n        edges,\n      },\n    };\n  }\n\n  /**\n   * Get stored node positions (for external access if needed)\n   */\n  getNodePositions(): Map<string, NodePosition> {\n    return this.nodePositions;\n  }\n\n  /**\n   * Collect shapes and edges recursively\n   * @param offsetX - Parent container's absolute X offset\n   * @param offsetY - Parent container's absolute Y offset\n   * @param insideParticipant - Whether we are inside a participant container\n   */\n  private collectShapesAndEdges(\n    node: LayoutedNode,\n    shapes: ShapeModel[],\n    edges: EdgeModel[],\n    offsetX: number = 0,\n    offsetY: number = 0,\n    insideParticipant: boolean = false\n  ): void {\n    // Add shape for this node (if it has coordinates)\n    if (node.x !== undefined && node.y !== undefined) {\n      const absoluteX = offsetX + node.x;\n      const absoluteY = offsetY + node.y;\n      const elkWidth = node.width ?? 100;\n      // Use visual dimensions when ELK was given an inflated size to reserve\n      // label or data-object space (ioSpecification, long gateway label).\n      const bpmnAny = node.bpmn as { _visualHeight?: number; _visualWidth?: number } | undefined;\n      const nodeHeight = bpmnAny?._visualHeight ?? node.height ?? 80;\n      const visualWidth = bpmnAny?._visualWidth ?? elkWidth;\n      // The visual shape is centered horizontally inside the inflated ELK bounds.\n      const visualX = absoluteX + (elkWidth - visualWidth) / 2;\n\n      // Store node position for edge routing\n      // For events, include the label area below the node in the bounds\n      // to help edge labels avoid overlapping with node labels\n      let effectiveHeight = nodeHeight;\n      if (this.isEventType(node.bpmn?.type) && node.labels && node.labels.length > 0) {\n        // Events have labels below them - extend the effective height\n        const labelHeight = node.labels[0]?.height ?? 14;\n        effectiveHeight = nodeHeight + 4 + labelHeight; // 4px gap + label height\n      }\n\n      // Store visualHeight when node has ioSpecification (ELK layout uses larger height for spacing)\n      // This is used by buildEdge to adjust edge endpoints to connect to the visual node border\n      const nodePosition: NodePosition = {\n        x: visualX,\n        y: absoluteY,\n        width: visualWidth,\n        height: effectiveHeight,\n      };\n      if (bpmnAny?._visualHeight !== undefined) {\n        nodePosition.visualHeight = bpmnAny._visualHeight;\n      }\n      this.nodePositions.set(node.id, nodePosition);\n\n      // Store node BPMN metadata for gateway detection\n      if (node.bpmn) {\n        this.storeNodeBpmn(node.id, { type: node.bpmn.type, isExpanded: node.bpmn.isExpanded });\n      }\n\n      // Store the offset used for this node (needed for edge coordinate transformation)\n      this.nodeOffsets.set(node.id, { x: offsetX, y: offsetY });\n\n      shapes.push(this.buildShape(node, offsetX, offsetY));\n\n      // Process ioSpecification dataInput/dataOutput shapes for tasks/activities only\n      // These are visual representations of task inputs/outputs positioned around the task\n      // Skip for process-level ioSpecification (process type should not have visual data shapes)\n      const nodeType = node.bpmn?.type;\n      const isTaskOrActivity = nodeType && (\n        nodeType.includes('Task') ||\n        nodeType === 'task' ||\n        nodeType === 'callActivity' ||\n        nodeType === 'subProcess' ||\n        nodeType === 'transaction' ||\n        nodeType === 'adHocSubProcess'\n      );\n\n      if (isTaskOrActivity) {\n        const ioSpec = (node.bpmn as { ioSpecification?: IoSpecification } | undefined)?.ioSpecification;\n        if (ioSpec) {\n          this.buildIoSpecificationShapes(node, ioSpec, shapes, edges, absoluteX, absoluteY, elkWidth, nodeHeight);\n        }\n      }\n    }\n\n    // Calculate offset for children\n    // Containers that offset their children: pools (participants), lanes, and expanded subprocesses\n    const isExpandedSubprocess = node.bpmn?.isExpanded === true &&\n      (node.bpmn?.type === 'subProcess' || node.bpmn?.type === 'transaction' ||\n       node.bpmn?.type === 'adHocSubProcess' || node.bpmn?.type === 'eventSubProcess' ||\n       (node.bpmn as { triggeredByEvent?: boolean })?.triggeredByEvent === true);\n\n    const isPoolOrLane = node.bpmn?.type === 'participant' || node.bpmn?.type === 'lane';\n\n    // Process nested inside participant also acts as a container for coordinate offsets\n    const isNestedProcess = node.bpmn?.type === 'process' && insideParticipant;\n\n    const isContainer = isExpandedSubprocess || isPoolOrLane || isNestedProcess;\n\n    const childOffsetX = isContainer ? offsetX + (node.x ?? 0) : offsetX;\n    const childOffsetY = isContainer ? offsetY + (node.y ?? 0) : offsetY;\n\n    // Track if we're entering a participant\n    const childInsideParticipant = insideParticipant || node.bpmn?.type === 'participant';\n\n    // Process children\n    if (node.children) {\n      for (const child of node.children) {\n        this.collectShapesAndEdges(child as LayoutedNode, shapes, edges, childOffsetX, childOffsetY, childInsideParticipant);\n      }\n    }\n\n    // Process boundary events - position them on the bottom edge of the task\n    if (node.boundaryEvents) {\n      const nodeX = offsetX + (node.x ?? 0);\n      const nodeY = offsetY + (node.y ?? 0);\n      const nodeWidth = node.width ?? 100;\n      const nodeHeight = node.height ?? 80;\n      const beCount = node.boundaryEvents.length;\n\n      node.boundaryEvents.forEach((be, index) => {\n        const beWidth = be.width ?? 36;\n        const beHeight = be.height ?? 36;\n\n        // Calculate position on the bottom edge of the task\n        // Distribute multiple boundary events evenly along the bottom\n        const spacing = nodeWidth / (beCount + 1);\n        const beX = nodeX + spacing * (index + 1) - beWidth / 2;\n        const beY = nodeY + nodeHeight - beHeight / 2; // Half inside, half outside\n\n        // Store boundary event position for edge routing\n        this.boundaryEventPositions.set(be.id, {\n          x: beX,\n          y: beY,\n          width: beWidth,\n          height: beHeight,\n        });\n\n        // When several boundary events share the same parent task, bpmn.io's\n        // default label position (centered below the event) leaves all their\n        // labels piled on top of each other because the events themselves are\n        // packed tighter than the label widths. Stagger label Y by index so the\n        // labels stack vertically instead of overlapping side-by-side.\n        const labelText = be.bpmn?.name ?? '';\n        const labelHeight = 14;\n        // ~12px per CJK char, 7px per ASCII char; padding 6.\n        let estimatedTextWidth = 6;\n        for (const ch of labelText) {\n          estimatedTextWidth += /[一-鿿]/.test(ch) ? 12 : 7;\n        }\n        if (estimatedTextWidth < 24) estimatedTextWidth = 24;\n        const labelX = beX + beWidth / 2 - estimatedTextWidth / 2;\n        const labelY = beY + beHeight + 4 + (beCount > 1 ? index * (labelHeight + 2) : 0);\n\n        shapes.push({\n          id: `${be.id}_di`,\n          bpmnElement: be.id,\n          bounds: {\n            x: beX,\n            y: beY,\n            width: beWidth,\n            height: beHeight,\n          },\n          label: labelText\n            ? {\n                bounds: {\n                  x: labelX,\n                  y: labelY,\n                  width: estimatedTextWidth,\n                  height: labelHeight,\n                },\n              }\n            : undefined,\n        });\n      });\n    }\n\n    // Process edges\n    // Edge waypoints from ELK are relative to the source node's parent container,\n    // not necessarily the edge's container. We use the source node's stored offset.\n    if (node.edges) {\n      for (const edge of node.edges) {\n        if (edge.sections && edge.sections.length > 0) {\n          // Check if edge has absolute coordinates (set by rearrangePools for message flows)\n          const hasAbsoluteCoords = (edge as { _absoluteCoords?: boolean })._absoluteCoords === true;\n          // Check if edge has pool-relative coordinates (set by recalculatePoolEdges for pool edges with lanes)\n          const hasPoolRelativeCoords = (edge as { _poolRelativeCoords?: boolean })._poolRelativeCoords === true;\n\n          if (hasAbsoluteCoords) {\n            // Edge already has absolute coordinates - don't add offset\n            edges.push(this.buildEdge(edge, 0, 0));\n          } else if (hasPoolRelativeCoords) {\n            // Edge waypoints are relative to pool (already include lane offsets within pool)\n            // Use container's offset (pool's offset), not source node's offset\n            edges.push(this.buildEdge(edge, offsetX + (node.x ?? 0), offsetY + (node.y ?? 0)));\n          } else {\n            const sourceId = edge.sources?.[0];\n            // Use the source node's offset if available, otherwise fall back to childOffset\n            const sourceOffset = sourceId ? this.nodeOffsets.get(sourceId) : undefined;\n            const edgeOffsetX = sourceOffset?.x ?? childOffsetX;\n            const edgeOffsetY = sourceOffset?.y ?? childOffsetY;\n            edges.push(this.buildEdge(edge, edgeOffsetX, edgeOffsetY));\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Check if a node type is an event type\n   */\n  private isEventType(type?: string): boolean {\n    if (!type) return false;\n    return type.includes('Event') || type === 'startEvent' || type === 'endEvent' ||\n           type === 'intermediateThrowEvent' || type === 'intermediateCatchEvent';\n  }\n\n  /**\n   * Check if a node type is a gateway type\n   */\n  private isGatewayType(type?: string): boolean {\n    if (!type) return false;\n    return type.includes('Gateway');\n  }\n\n  /**\n   * Store node BPMN metadata for later gateway detection\n   */\n  private storeNodeBpmn(nodeId: string, bpmn: NodeBpmnInfo): void {\n    this.nodeBpmn.set(nodeId, bpmn);\n  }\n\n  /**\n   * Build shapes for ioSpecification dataInputs and dataOutputs\n   * Positions: dataInputs below-left of the task (stacked vertically),\n   *            dataOutputs below-right of the task (stacked vertically)\n   * Only the topmost item in each stack has a dashed association edge to the task\n   */\n  private buildIoSpecificationShapes(\n    node: LayoutedNode,\n    ioSpec: IoSpecification,\n    shapes: ShapeModel[],\n    edges: EdgeModel[],\n    taskX: number,\n    taskY: number,\n    taskWidth: number,\n    taskHeight: number\n  ): void {\n    // Data object dimensions (same as dataObjectReference)\n    const dataWidth = 36;\n    const dataHeight = 50;\n    const gapBelow = 20; // Gap between task and first data object (vertical)\n    const verticalSpacing = 24; // Spacing between stacked data objects (includes label space)\n    const labelHeight = 14;\n\n    // Position dataInputs below the task, aligned to the left side, stacked vertically\n    const dataInputs = ioSpec.dataInputs ?? [];\n    const inputStartX = taskX; // Start from task's left edge\n\n    dataInputs.forEach((dataInput, index) => {\n      const inputId = dataInput.id ?? `${node.id}_input_${index}`;\n      const inputX = inputStartX;\n      const inputY = taskY + taskHeight + gapBelow + index * (dataHeight + verticalSpacing);\n\n      this.dataObjectOwners.set(inputId, node.id);\n\n      // Store position for edge routing\n      this.nodePositions.set(inputId, {\n        x: inputX,\n        y: inputY,\n        width: dataWidth,\n        height: dataHeight,\n      });\n\n      const shape: ShapeModel = {\n        id: `${inputId}_di`,\n        bpmnElement: inputId,\n        bounds: {\n          x: inputX,\n          y: inputY,\n          width: dataWidth,\n          height: dataHeight,\n        },\n      };\n\n      // Add label below the data object\n      if (dataInput.name) {\n        const labelWidth = Math.max(dataWidth, this.estimateTextWidth(dataInput.name));\n        shape.label = {\n          bounds: {\n            x: inputX + (dataWidth - labelWidth) / 2,\n            y: inputY + dataHeight + 4,\n            width: labelWidth,\n            height: labelHeight,\n          },\n        };\n      }\n\n      shapes.push(shape);\n\n      // Only the first (topmost) dataInput gets an edge to the task\n      if (index === 0) {\n        // Create dashed edge from dataInput to task (arrow pointing to task)\n        // bpmnElement references the auto-generated dataInputAssociation\n        const assocId = `${inputId}_assoc`;\n        const inputCenterX = inputX + dataWidth / 2;\n        const inputTopY = inputY;\n        const taskBottomY = taskY + taskHeight;\n\n        // Simple vertical connection from data object top to task bottom\n        edges.push({\n          id: `${assocId}_di`,\n          bpmnElement: assocId,\n          waypoints: [\n            { x: inputCenterX, y: inputTopY },\n            { x: inputCenterX, y: taskBottomY },\n          ],\n        });\n      }\n    });\n\n    // Position dataOutputs below the task, aligned to the right side, stacked vertically\n    const dataOutputs = ioSpec.dataOutputs ?? [];\n    const outputStartX = taskX + taskWidth - dataWidth; // Align to right edge\n\n    dataOutputs.forEach((dataOutput, index) => {\n      const outputId = dataOutput.id ?? `${node.id}_output_${index}`;\n      const outputX = outputStartX;\n      const outputY = taskY + taskHeight + gapBelow + index * (dataHeight + verticalSpacing);\n\n      this.dataObjectOwners.set(outputId, node.id);\n\n      // Store position for edge routing\n      this.nodePositions.set(outputId, {\n        x: outputX,\n        y: outputY,\n        width: dataWidth,\n        height: dataHeight,\n      });\n\n      const shape: ShapeModel = {\n        id: `${outputId}_di`,\n        bpmnElement: outputId,\n        bounds: {\n          x: outputX,\n          y: outputY,\n          width: dataWidth,\n          height: dataHeight,\n        },\n      };\n\n      // Add label below the data object\n      if (dataOutput.name) {\n        const labelWidth = Math.max(dataWidth, this.estimateTextWidth(dataOutput.name));\n        shape.label = {\n          bounds: {\n            x: outputX + (dataWidth - labelWidth) / 2,\n            y: outputY + dataHeight + 4,\n            width: labelWidth,\n            height: labelHeight,\n          },\n        };\n      }\n\n      shapes.push(shape);\n\n      // Only the first (topmost) dataOutput gets an edge from the task\n      if (index === 0) {\n        // Create dashed edge from task to dataOutput (arrow pointing to dataOutput)\n        // bpmnElement references the auto-generated dataOutputAssociation\n        const assocId = `${outputId}_assoc`;\n        const outputCenterX = outputX + dataWidth / 2;\n        const outputTopY = outputY;\n        const taskBottomY = taskY + taskHeight;\n\n        // Simple vertical connection from task bottom to data object top\n        edges.push({\n          id: `${assocId}_di`,\n          bpmnElement: assocId,\n          waypoints: [\n            { x: outputCenterX, y: taskBottomY },\n            { x: outputCenterX, y: outputTopY },\n          ],\n        });\n      }\n    });\n  }\n\n  /**\n   * Estimate text width for label sizing (simplified)\n   */\n  private estimateTextWidth(text: string): number {\n    let width = 0;\n    for (const char of text) {\n      // CJK characters are wider\n      if (char.charCodeAt(0) > 255) {\n        width += 14;\n      } else {\n        width += 7;\n      }\n    }\n    return Math.max(36, Math.min(width, 150));\n  }\n\n  /**\n   * Find node BPMN metadata by id\n   */\n  private findNodeBpmn(nodeId: string): NodeBpmnInfo | undefined {\n    return this.nodeBpmn.get(nodeId);\n  }\n\n  /**\n   * Estimate number of lines needed for a label based on text and width\n   * Uses approximate character width of 14px for CJK and 7px for ASCII\n   */\n  private estimateLabelLines(text: string, maxWidth: number): number {\n    if (!text || maxWidth <= 0) return 1;\n\n    let currentLineWidth = 0;\n    let lines = 1;\n\n    for (const char of text) {\n      // CJK characters are wider\n      const charWidth = char.charCodeAt(0) > 255 ? 14 : 7;\n\n      if (currentLineWidth + charWidth > maxWidth) {\n        lines++;\n        currentLineWidth = charWidth;\n      } else {\n        currentLineWidth += charWidth;\n      }\n    }\n\n    return lines;\n  }\n\n  /**\n   * Build a shape model\n   */\n  private buildShape(node: LayoutedNode, offsetX: number = 0, offsetY: number = 0): ShapeModel {\n    const absoluteX = offsetX + (node.x ?? 0);\n    const absoluteY = offsetY + (node.y ?? 0);\n    // Use visual dimensions when ELK was given an inflated size to reserve\n    // label or data-object space (ioSpecification, long gateway label).\n    const bpmnAny = node.bpmn as { _visualHeight?: number; _visualWidth?: number } | undefined;\n    const elkWidth = node.width ?? 100;\n    const visualHeight = bpmnAny?._visualHeight ?? node.height ?? 80;\n    const visualWidth = bpmnAny?._visualWidth ?? elkWidth;\n    // Center the shape horizontally inside the inflated ELK width.\n    const xCentered = absoluteX + (elkWidth - visualWidth) / 2;\n\n    const shape: ShapeModel = {\n      id: `${node.id}_di`,\n      bpmnElement: node.id,\n      bounds: {\n        x: xCentered,\n        y: absoluteY,\n        width: visualWidth,\n        height: visualHeight,\n      },\n    };\n\n    // Add isExpanded for subprocesses\n    if (node.bpmn?.isExpanded !== undefined) {\n      shape.isExpanded = node.bpmn.isExpanded;\n    }\n\n    // Add isHorizontal for pools/lanes\n    if (node.bpmn?.type === 'participant' || node.bpmn?.type === 'lane') {\n      shape.isHorizontal = true;\n    }\n\n    // Add label positioning for elements that need external labels\n    // Priority: use explicit labels data if present, otherwise generate from bpmn.name\n    const nodeWidth = node.width ?? 36;\n    const nodeHeight = bpmnAny?._visualHeight ?? node.height ?? 36;\n    const label = node.labels?.[0];\n    const labelText = node.bpmn?.name ?? label?.text ?? '';\n\n    if (this.isEventType(node.bpmn?.type) && labelText) {\n      // For events (circles), position the label below the shape (bpmn-js default behavior)\n      const labelWidth = label?.width ?? 100;\n      const labelHeight = label?.height ?? 14;\n\n      // Position label below the event circle, horizontally centered (using absolute coords)\n      shape.label = {\n        bounds: {\n          x: absoluteX + (nodeWidth - labelWidth) / 2,\n          y: absoluteY + nodeHeight + 4, // 4px gap below the circle\n          width: labelWidth,\n          height: labelHeight,\n        },\n      };\n    } else if (this.isGatewayType(node.bpmn?.type) && labelText) {\n      // For gateways (diamonds), position the label above the shape to avoid overlap with nodes below\n      const labelWidth = label?.width ?? 100;\n      // Calculate label height based on text content (may need multiple lines)\n      const estimatedLines = this.estimateLabelLines(labelText, labelWidth);\n      const labelHeight = estimatedLines * 14; // 14px per line\n\n      // Position label above the gateway diamond, horizontally centered\n      // Adjust Y position upward based on label height\n      shape.label = {\n        bounds: {\n          x: absoluteX + (nodeWidth - labelWidth) / 2,\n          y: absoluteY - labelHeight - 4, // 4px gap above the diamond\n          width: labelWidth,\n          height: labelHeight,\n        },\n      };\n    } else if (label?.x !== undefined && label?.y !== undefined) {\n      // For other elements with explicit label positioning, use ELK-calculated position\n      shape.label = {\n        bounds: {\n          x: absoluteX + label.x,\n          y: absoluteY + label.y,\n          width: label?.width ?? 100,\n          height: label?.height ?? 20,\n        },\n      };\n    }\n\n    return shape;\n  }\n\n  /**\n   * Build an edge model\n   */\n  private buildEdge(edge: LayoutedEdge, offsetX: number = 0, offsetY: number = 0): EdgeModel {\n    const sourceId = edge.sources?.[0];\n    const targetId = edge.targets?.[0];\n\n    // Check if source is a boundary event\n    const bePosition = sourceId ? this.boundaryEventPositions.get(sourceId) : undefined;\n    const targetPosition = targetId ? this.nodePositions.get(targetId) : undefined;\n\n    // Check if source or target is a gateway (for diamond shape adjustment)\n    const sourceNode = sourceId ? this.findNodeBpmn(sourceId) : undefined;\n    const targetNode = targetId ? this.findNodeBpmn(targetId) : undefined;\n    const sourceIsGateway = this.isGatewayType(sourceNode?.type);\n    const targetIsGateway = this.isGatewayType(targetNode?.type);\n\n    let waypoints: PointModel[] = [];\n\n    // Check if edge has pre-calculated sections with bendPoints (from obstacle avoidance)\n    const hasPreCalculatedSections = edge.sections &&\n      edge.sections.length > 0 &&\n      edge.sections[0]?.bendPoints &&\n      edge.sections[0].bendPoints.length > 0;\n\n    if (isDebugEnabled() && bePosition) {\n      console.log(`[BPMN] buildEdge ${edge.id}: preCalculated=${hasPreCalculatedSections}`);\n    }\n\n    // Boundary-event edges: always reroute from the diagram-builder's recomputed\n    // boundary position. ELK's sections are based on positions before\n    // boundary/mover post-processing, so reusing them leaves the endpoint\n    // floating outside the actual target (e.g. 17-subprocess-transaction's\n    // cancel edge landing past task_cancel_handler).\n    if (bePosition && targetPosition) {\n      // Source is a boundary event without pre-calculated routing - calculate simple waypoints\n      // Start from bottom center of boundary event\n      const startX = bePosition.x + bePosition.width / 2;\n      const startY = bePosition.y + bePosition.height;\n\n      // End at left center of target (or top center if target is below)\n      let endX: number;\n      let endY: number;\n\n      // Determine connection point based on relative position\n      if (targetPosition.y > bePosition.y + bePosition.height) {\n        // Target is below - connect to top center\n        endX = targetPosition.x + targetPosition.width / 2;\n        endY = targetPosition.y;\n      } else if (targetPosition.x > bePosition.x + bePosition.width) {\n        // Target is to the right - connect to left center\n        endX = targetPosition.x;\n        endY = targetPosition.y + targetPosition.height / 2;\n      } else if (targetPosition.x + targetPosition.width < bePosition.x) {\n        // Target is to the left - connect to right center\n        endX = targetPosition.x + targetPosition.width;\n        endY = targetPosition.y + targetPosition.height / 2;\n      } else {\n        // Target is above - connect to bottom center\n        endX = targetPosition.x + targetPosition.width / 2;\n        endY = targetPosition.y + targetPosition.height;\n      }\n\n      waypoints.push({ x: startX, y: startY });\n\n      // Add bend point if needed for orthogonal routing\n      if (Math.abs(startX - endX) > 10 && Math.abs(startY - endY) > 10) {\n        // Go down first, then turn\n        const midY = startY + 20;\n        waypoints.push({ x: startX, y: midY });\n        waypoints.push({ x: endX, y: midY });\n      }\n\n      waypoints.push({ x: endX, y: endY });\n    } else {\n      // Normal edge - use ELK calculated waypoints\n      for (const section of edge.sections) {\n        // Start point\n        waypoints.push({ x: offsetX + section.startPoint.x, y: offsetY + section.startPoint.y });\n\n        // Bend points\n        if (section.bendPoints) {\n          for (const bp of section.bendPoints) {\n            waypoints.push({ x: offsetX + bp.x, y: offsetY + bp.y });\n          }\n        }\n\n        // End point\n        waypoints.push({ x: offsetX + section.endPoint.x, y: offsetY + section.endPoint.y });\n      }\n\n      // Adjust endpoints for gateway diamond shapes\n      // This calculates the actual intersection with the diamond edge to maintain\n      // visual separation when multiple edges connect to the same gateway side\n      if (waypoints.length >= 2) {\n        // Adjust start point if source is a gateway\n        if (sourceIsGateway && sourceId) {\n          const sourcePos = this.nodePositions.get(sourceId);\n          if (sourcePos) {\n            const wp0 = waypoints[0];\n            const wp1 = waypoints[1];\n            if (wp0 && wp1) {\n              waypoints[0] = adjustGatewayEndpoint(\n                wp0,\n                wp1,\n                sourcePos,\n                true // isSource\n              );\n              // No adjacent point adjustment needed - the intersection calculation\n              // preserves the original Y (or X) coordinate, maintaining orthogonality\n            }\n          }\n        }\n\n        // Adjust end point if target is a gateway\n        if (targetIsGateway && targetId) {\n          const targetPos = this.nodePositions.get(targetId);\n          if (targetPos) {\n            const lastIdx = waypoints.length - 1;\n            const prevIdx = lastIdx - 1;\n            const wpLast = waypoints[lastIdx];\n            const wpPrev = waypoints[prevIdx];\n            if (wpLast && wpPrev) {\n              waypoints[lastIdx] = adjustGatewayEndpoint(\n                wpLast,\n                wpPrev,\n                targetPos,\n                false // isSource\n              );\n              // No adjacent point adjustment needed - the intersection calculation\n              // preserves the original Y (or X) coordinate, maintaining orthogonality\n            }\n          }\n        }\n      }\n\n      // Adjust endpoints for nodes with ioSpecification (visualHeight)\n      // ELK calculates waypoints based on the enlarged layout height (which includes space for data objects),\n      // but we need to connect to the visual node border, not the layout center\n      this.adjustEndpointsForVisualHeight(waypoints, sourceId, targetId);\n    }\n\n    // Ensure all waypoint segments are orthogonal (no diagonal lines)\n    // Insert bend points where needed to convert diagonals to L-shaped routes\n    this.ensureOrthogonalWaypoints(waypoints);\n\n    // Ensure endpoints connect perpendicular to node borders\n    // This adds bend points if the last/first segment isn't perpendicular\n    this.ensurePerpendicularEndpoints(\n      waypoints,\n      sourceId,\n      targetId,\n      sourceIsGateway,\n      targetIsGateway\n    );\n\n    // Re-route around obstacles ELK's edge-fixer can't see — data shapes\n    // and foreign flow nodes that a boundary L-shape or post-alignment\n    // shift may have routed through.\n    const detoured = this.routeAroundLocalObstacles(waypoints, sourceId, targetId);\n\n    // Detours can leave the last/first segment running parallel to the\n    // node border instead of perpendicular to it. Re-apply perpendicular\n    // enforcement so the connector still meets the node at a clean angle.\n    if (detoured) {\n      this.ensurePerpendicularEndpoints(\n        waypoints,\n        sourceId,\n        targetId,\n        sourceIsGateway,\n        targetIsGateway\n      );\n    }\n\n    const edgeModel: EdgeModel = {\n      id: `${edge.id}_di`,\n      bpmnElement: edge.id,\n      waypoints,\n    };\n\n    // Add label if present - use smart positioning on longest segment\n    if (edge.labels && edge.labels.length > 0) {\n      const label = edge.labels[0];\n      const labelWidth = label?.width ?? 50;\n      const labelHeight = label?.height ?? 14;\n\n      // Always use our smart label positioning (ELK's positions are often poor)\n      const labelPos = this.calculateSmartLabelPosition(\n        waypoints,\n        labelWidth,\n        labelHeight,\n        sourceId,\n        targetId\n      );\n\n      // Register this label position for collision detection with other edge labels\n      this.placedEdgeLabels.push({\n        x: labelPos.x,\n        y: labelPos.y,\n        width: labelWidth,\n        height: labelHeight,\n      });\n\n      edgeModel.label = {\n        bounds: {\n          x: labelPos.x,\n          y: labelPos.y,\n          width: labelWidth,\n          height: labelHeight,\n        },\n      };\n    }\n\n    return edgeModel;\n  }\n\n  /**\n   * Adjust edge endpoints for nodes with ioSpecification (visualHeight)\n   *\n   * When a node has ioSpecification, ELK uses an enlarged height for layout (to make space for data objects).\n   * However, the edge endpoints should connect to the visual node border, not based on the layout height.\n   *\n   * This method adjusts endpoint Y coordinates and also adjusts adjacent waypoints if they were\n   * on the same horizontal line, to maintain horizontal segments without introducing extra bends.\n   */\n  private adjustEndpointsForVisualHeight(\n    waypoints: PointModel[],\n    sourceId?: string,\n    targetId?: string\n  ): void {\n    if (waypoints.length < 2) return;\n\n    const tolerance = 5;\n\n    // Adjust source endpoint if source has visualHeight\n    if (sourceId) {\n      const sourcePos = this.nodePositions.get(sourceId);\n      if (sourcePos?.visualHeight !== undefined) {\n        const firstWp = waypoints[0];\n        const secondWp = waypoints[1];\n        if (firstWp && secondWp) {\n          const nodeRight = sourcePos.x + sourcePos.width;\n          const nodeLeft = sourcePos.x;\n          const visualBottom = sourcePos.y + sourcePos.visualHeight;\n          const visualCenterY = sourcePos.y + sourcePos.visualHeight / 2;\n\n          // Check if leaving from left or right side (horizontal connection)\n          if (Math.abs(firstWp.x - nodeRight) < tolerance || Math.abs(firstWp.x - nodeLeft) < tolerance) {\n            const oldY = firstWp.y;\n            const newY = visualCenterY;\n            // Horizontal exit - adjust Y to visual center\n            firstWp.y = newY;\n            // If second waypoint was on the same horizontal line, adjust it too to maintain horizontal segment\n            // BUT only if second waypoint is NOT the last waypoint (i.e., not connecting directly to target)\n            if (Math.abs(secondWp.y - oldY) < tolerance && waypoints.length > 2) {\n              secondWp.y = newY;\n            }\n          } else if (firstWp.y > visualBottom) {\n            // Leaving from below visual bottom - clamp to visual bottom\n            firstWp.y = visualBottom;\n          }\n        }\n      }\n    }\n\n    // Adjust target endpoint if target has visualHeight\n    if (targetId) {\n      const targetPos = this.nodePositions.get(targetId);\n      if (targetPos?.visualHeight !== undefined) {\n        const lastIdx = waypoints.length - 1;\n        const lastWp = waypoints[lastIdx];\n        const prevWp = waypoints[lastIdx - 1];\n        if (lastWp && prevWp) {\n          const nodeLeft = targetPos.x;\n          const nodeRight = targetPos.x + targetPos.width;\n          const visualBottom = targetPos.y + targetPos.visualHeight;\n          const visualCenterY = targetPos.y + targetPos.visualHeight / 2;\n\n          // Check if entering from left or right side (horizontal connection)\n          if (Math.abs(lastWp.x - nodeLeft) < tolerance || Math.abs(lastWp.x - nodeRight) < tolerance) {\n            const oldY = lastWp.y;\n            const newY = visualCenterY;\n            // Horizontal entry - adjust Y to visual center\n            lastWp.y = newY;\n            // If previous waypoint was on the same horizontal line, adjust it too to maintain horizontal segment\n            // BUT only if previous waypoint is NOT the first waypoint (i.e., not connecting directly from source)\n            if (Math.abs(prevWp.y - oldY) < tolerance && waypoints.length > 2) {\n              prevWp.y = newY;\n            }\n          } else if (lastWp.y > visualBottom) {\n            // Entering from below visual bottom - clamp to visual bottom\n            lastWp.y = visualBottom;\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Calculate smart label position on the edge\n   * Strategy:\n   * 1. Find the longest segment of the edge (best visibility)\n   * 2. Place label at the midpoint of that segment\n   * 3. Offset based on segment direction, avoiding overlap with source/target nodes\n   */\n  private calculateSmartLabelPosition(\n    waypoints: PointModel[],\n    labelWidth: number,\n    labelHeight: number,\n    sourceId?: string,\n    targetId?: string\n  ): { x: number; y: number } {\n    if (waypoints.length < 2) {\n      return { x: 0, y: 0 };\n    }\n\n    // Get source and target node positions for collision avoidance\n    const sourcePos = sourceId ? this.nodePositions.get(sourceId) : undefined;\n    const targetPos = targetId ? this.nodePositions.get(targetId) : undefined;\n\n    // Find the longest segment that is not too close to source/target\n    let bestSegmentIndex = -1;\n    let bestSegmentLength = 0;\n\n    for (let i = 0; i < waypoints.length - 1; i++) {\n      const wpCurrent = waypoints[i];\n      const wpNext = waypoints[i + 1];\n      if (!wpCurrent || !wpNext) continue;\n\n      const segmentLength = distance(wpCurrent, wpNext);\n\n      // Skip very short segments\n      if (segmentLength < 30) continue;\n\n      // Calculate segment midpoint\n      const midX = (wpCurrent.x + wpNext.x) / 2;\n      const midY = (wpCurrent.y + wpNext.y) / 2;\n\n      // Check if midpoint is too close to source or target node\n      const tooCloseToSource = sourcePos && this.isPointNearNode(midX, midY, sourcePos, 20);\n      const tooCloseToTarget = targetPos && this.isPointNearNode(midX, midY, targetPos, 20);\n\n      if (!tooCloseToSource && !tooCloseToTarget && segmentLength > bestSegmentLength) {\n        bestSegmentLength = segmentLength;\n        bestSegmentIndex = i;\n      }\n    }\n\n    // If no good segment found, fall back to longest segment\n    if (bestSegmentIndex < 0) {\n      for (let i = 0; i < waypoints.length - 1; i++) {\n        const wpCurrent = waypoints[i];\n        const wpNext = waypoints[i + 1];\n        if (!wpCurrent || !wpNext) continue;\n\n        const segmentLength = distance(wpCurrent, wpNext);\n        if (segmentLength > bestSegmentLength) {\n          bestSegmentLength = segmentLength;\n          bestSegmentIndex = i;\n        }\n      }\n    }\n\n    if (bestSegmentIndex < 0) {\n      bestSegmentIndex = 0;\n    }\n\n    const wpStart = waypoints[bestSegmentIndex];\n    const wpEnd = waypoints[bestSegmentIndex + 1];\n\n    if (!wpStart || !wpEnd) {\n      return { x: 0, y: 0 };\n    }\n\n    // Calculate midpoint of the chosen segment\n    const midX = (wpStart.x + wpEnd.x) / 2;\n    const midY = (wpStart.y + wpEnd.y) / 2;\n\n    // Determine segment direction\n    const dx = wpEnd.x - wpStart.x;\n    const dy = wpEnd.y - wpStart.y;\n    const isHorizontal = Math.abs(dx) > Math.abs(dy);\n    const segmentLength = Math.sqrt(dx * dx + dy * dy);\n\n    // Label offset from the edge line\n    const offset = 5;\n\n    if (isHorizontal) {\n      // Horizontal segment - place label above the line by default. When several\n      // edges share the same horizontal stub (typical gateway-fan with multiple\n      // outgoing flows), the natural midpoint collides — so try increasing\n      // vertical offsets and both sides before giving up.\n      const labelX = midX - labelWidth / 2;\n      const baseAbove = midY - labelHeight - offset;\n      const baseBelow = midY + offset;\n\n      const tryPositions: { x: number; y: number }[] = [];\n      for (let step = 0; step <= 5; step++) {\n        const delta = step * (labelHeight + 4);\n        tryPositions.push({ x: labelX, y: baseAbove - delta });\n        tryPositions.push({ x: labelX, y: baseBelow + delta });\n      }\n\n      let fallback = tryPositions[0]!;\n      for (const pos of tryPositions) {\n        const bounds = { x: pos.x, y: pos.y, width: labelWidth, height: labelHeight };\n        const overlapsNode = this.labelOverlapsAnyNode(bounds);\n        const overlapsLabel = this.labelOverlapsAnyEdgeLabel(bounds);\n        if (!overlapsNode && !overlapsLabel) {\n          return pos;\n        }\n        // Prefer at least non-node-overlap as the fallback choice.\n        if (!overlapsNode) {\n          fallback = pos;\n        }\n      }\n      return fallback;\n    } else {\n      // Vertical segment - for long vertical segments (like message flows),\n      // place label at various positions to avoid overlap with nodes AND other edge labels\n\n      // For long segments (like message flows), try multiple positions\n      // to find one that doesn't overlap with nodes or other labels\n      const positions = segmentLength > 80\n        ? [0.35, 0.5, 0.65, 0.2, 0.8, 0.15, 0.85]\n        : [0.5];\n\n      // Try each position with both right and left placement\n      for (const ratio of positions) {\n        const testY = wpStart.y + (wpEnd.y - wpStart.y) * ratio - labelHeight / 2;\n\n        // Try right side\n        const boundsRight = { x: midX + offset, y: testY, width: labelWidth, height: labelHeight };\n        if (!this.labelOverlapsAnyNode(boundsRight) && !this.labelOverlapsAnyEdgeLabel(boundsRight)) {\n          return { x: midX + offset, y: testY };\n        }\n\n        // Try left side\n        const boundsLeft = { x: midX - labelWidth - offset, y: testY, width: labelWidth, height: labelHeight };\n        if (!this.labelOverlapsAnyNode(boundsLeft) && !this.labelOverlapsAnyEdgeLabel(boundsLeft)) {\n          return { x: midX - labelWidth - offset, y: testY };\n        }\n      }\n\n      // Fallback: use midpoint, but offset Y if overlapping with other labels\n      let labelX = midX + offset;\n      let labelY = midY - labelHeight / 2;\n\n      // If overlapping with existing label, try different Y offsets\n      for (let yOffset = 0; yOffset <= 100; yOffset += 20) {\n        for (const side of [1, -1]) { // right side, then left side\n          for (const yDir of [0, 1, -1]) { // no offset, down, up\n            const testX = side === 1 ? midX + offset : midX - labelWidth - offset;\n            const testY = labelY + yDir * yOffset;\n            const testBounds = { x: testX, y: testY, width: labelWidth, height: labelHeight };\n\n            if (!this.labelOverlapsAnyEdgeLabel(testBounds)) {\n              // Found a position that doesn't overlap with other labels\n              // Check node overlap is secondary - we prefer no label overlap\n              if (!this.labelOverlapsAnyNode(testBounds)) {\n                return { x: testX, y: testY };\n              }\n              // Even if overlapping node, use this if no label overlap\n              labelX = testX;\n              labelY = testY;\n            }\n          }\n        }\n      }\n\n      return { x: labelX, y: labelY };\n    }\n  }\n\n  /**\n   * Check if a point is near a node (within padding distance)\n   */\n  private isPointNearNode(\n    x: number,\n    y: number,\n    nodePos: NodePosition,\n    padding: number\n  ): boolean {\n    return (\n      x >= nodePos.x - padding &&\n      x <= nodePos.x + nodePos.width + padding &&\n      y >= nodePos.y - padding &&\n      y <= nodePos.y + nodePos.height + padding\n    );\n  }\n\n  /**\n   * Check if a label bounds overlaps with any node\n   */\n  private labelOverlapsAnyNode(labelBounds: { x: number; y: number; width: number; height: number }): boolean {\n    for (const nodePos of this.nodePositions.values()) {\n      if (this.boundsOverlap(labelBounds, nodePos)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Check if a label bounds overlaps with any already placed edge label\n   */\n  private labelOverlapsAnyEdgeLabel(labelBounds: { x: number; y: number; width: number; height: number }): boolean {\n    for (const placedLabel of this.placedEdgeLabels) {\n      if (this.boundsOverlap(labelBounds, placedLabel)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Check if two rectangles overlap\n   */\n  private boundsOverlap(\n    a: { x: number; y: number; width: number; height: number },\n    b: { x: number; y: number; width: number; height: number }\n  ): boolean {\n    return !(\n      a.x + a.width < b.x ||\n      b.x + b.width < a.x ||\n      a.y + a.height < b.y ||\n      b.y + b.height < a.y\n    );\n  }\n\n  /**\n   * Ensure all waypoint segments are orthogonal (horizontal or vertical)\n   * If a diagonal segment is found, insert intermediate bend points to create\n   * an L-shaped orthogonal path.\n   *\n   * Strategy: For diagonal segments, we use \"horizontal first\" - go horizontally\n   * to the target X, then vertically to the target Y.\n   */\n  private ensureOrthogonalWaypoints(waypoints: PointModel[]): void {\n    if (waypoints.length < 2) return;\n\n    const tolerance = 1; // Allow 1px tolerance for floating point errors\n    let i = 0;\n\n    while (i < waypoints.length - 1) {\n      const current = waypoints[i];\n      const next = waypoints[i + 1];\n      if (!current || !next) {\n        i++;\n        continue;\n      }\n\n      const dx = Math.abs(next.x - current.x);\n      const dy = Math.abs(next.y - current.y);\n\n      // Check if this segment is diagonal (both dx and dy are significant)\n      if (dx > tolerance && dy > tolerance) {\n        // Insert a bend point to make it orthogonal\n        // Use \"horizontal first\" strategy: go to next.x first, then to next.y\n        const bendPoint: PointModel = { x: next.x, y: current.y };\n        waypoints.splice(i + 1, 0, bendPoint);\n        // Don't increment i - we need to check the newly created segment\n        // But the next iteration will check (current -> bendPoint) which is horizontal\n        // So we can safely increment to check the next pair\n        i++;\n      } else {\n        i++;\n      }\n    }\n  }\n\n  /**\n   * Detect which side of a node a point is connected to.\n   * Returns 'top', 'bottom', 'left', 'right', or 'unknown'.\n   *\n   * First tries exact match with tolerance, then falls back to closest edge detection.\n   */\n  private detectConnectionSide(\n    point: PointModel,\n    nodeBounds: NodePosition,\n    _isGateway: boolean = false\n  ): 'top' | 'bottom' | 'left' | 'right' | 'unknown' {\n    const exactTolerance = 3;\n    const maxTolerance = 15; // Maximum distance to consider for closest edge\n\n    const nodeTop = nodeBounds.y;\n    const nodeBottom = nodeBounds.y + nodeBounds.height;\n    const nodeLeft = nodeBounds.x;\n    const nodeRight = nodeBounds.x + nodeBounds.width;\n\n    // For regular nodes, check rectangular edges\n    // First, try exact match with small tolerance\n    if (Math.abs(point.y - nodeTop) <= exactTolerance) return 'top';\n    if (Math.abs(point.y - nodeBottom) <= exactTolerance) return 'bottom';\n    if (Math.abs(point.x - nodeLeft) <= exactTolerance) return 'left';\n    if (Math.abs(point.x - nodeRight) <= exactTolerance) return 'right';\n\n    // If no exact match, find the closest edge\n    const distToTop = Math.abs(point.y - nodeTop);\n    const distToBottom = Math.abs(point.y - nodeBottom);\n    const distToLeft = Math.abs(point.x - nodeLeft);\n    const distToRight = Math.abs(point.x - nodeRight);\n\n    const minDist = Math.min(distToTop, distToBottom, distToLeft, distToRight);\n\n    // Only use closest edge if it's within reasonable distance\n    if (minDist > maxTolerance) return 'unknown';\n\n    // Return the closest edge\n    if (minDist === distToTop) return 'top';\n    if (minDist === distToBottom) return 'bottom';\n    if (minDist === distToLeft) return 'left';\n    return 'right';\n  }\n\n  /**\n   * Detect connection side for gateway based on edge direction.\n   * When point is on a diagonal edge of the diamond, use the adjacent point to determine direction.\n   */\n  private detectGatewayConnectionSide(\n    point: PointModel,\n    adjacentPoint: PointModel,\n    nodeBounds: NodePosition,\n    isSource: boolean\n  ): 'top' | 'bottom' | 'left' | 'right' {\n    const centerX = nodeBounds.x + nodeBounds.width / 2;\n    const centerY = nodeBounds.y + nodeBounds.height / 2;\n    const nodeTop = nodeBounds.y;\n    const nodeBottom = nodeBounds.y + nodeBounds.height;\n    const nodeLeft = nodeBounds.x;\n    const nodeRight = nodeBounds.x + nodeBounds.width;\n\n    // Calculate distances to each diamond corner\n    const distToTopCorner = Math.abs(point.x - centerX) + Math.abs(point.y - nodeTop);\n    const distToBottomCorner = Math.abs(point.x - centerX) + Math.abs(point.y - nodeBottom);\n    const distToLeftCorner = Math.abs(point.x - nodeLeft) + Math.abs(point.y - centerY);\n    const distToRightCorner = Math.abs(point.x - nodeRight) + Math.abs(point.y - centerY);\n\n    const minDist = Math.min(distToTopCorner, distToBottomCorner, distToLeftCorner, distToRightCorner);\n\n    // If clearly closest to one corner, use that\n    const tolerance = 5;\n    if (distToTopCorner <= minDist + tolerance && distToTopCorner < distToBottomCorner - tolerance &&\n        distToTopCorner < distToLeftCorner - tolerance && distToTopCorner < distToRightCorner - tolerance) {\n      return 'top';\n    }\n    if (distToBottomCorner <= minDist + tolerance && distToBottomCorner < distToTopCorner - tolerance &&\n        distToBottomCorner < distToLeftCorner - tolerance && distToBottomCorner < distToRightCorner - tolerance) {\n      return 'bottom';\n    }\n    if (distToLeftCorner <= minDist + tolerance && distToLeftCorner < distToTopCorner - tolerance &&\n        distToLeftCorner < distToBottomCorner - tolerance && distToLeftCorner < distToRightCorner - tolerance) {\n      return 'left';\n    }\n    if (distToRightCorner <= minDist + tolerance && distToRightCorner < distToTopCorner - tolerance &&\n        distToRightCorner < distToBottomCorner - tolerance && distToRightCorner < distToLeftCorner - tolerance) {\n      return 'right';\n    }\n\n    // Ambiguous case: use edge direction to decide\n    // For source: look at direction TO adjacentPoint\n    // For target: look at direction FROM adjacentPoint\n    const dx = isSource ? (adjacentPoint.x - point.x) : (point.x - adjacentPoint.x);\n    const dy = isSource ? (adjacentPoint.y - point.y) : (point.y - adjacentPoint.y);\n\n    // If edge is more horizontal, prefer left/right connection\n    // If edge is more vertical, prefer top/bottom connection\n    if (Math.abs(dx) > Math.abs(dy)) {\n      // Horizontal direction - use left or right\n      return dx > 0 ? 'right' : 'left';\n    } else {\n      // Vertical direction - use top or bottom\n      return dy > 0 ? 'bottom' : 'top';\n    }\n  }\n\n  /**\n   * Ensure edge endpoints connect perpendicular to node borders.\n   * - Connection to top/bottom: last segment must be vertical (same x)\n   * - Connection to left/right: last segment must be horizontal (same y)\n   *\n   * When inserting bend points, we also update the previous waypoint to maintain\n   * orthogonality (no diagonal lines).\n   */\n  private ensurePerpendicularEndpoints(\n    waypoints: PointModel[],\n    sourceId: string | undefined,\n    targetId: string | undefined,\n    sourceIsGateway: boolean = false,\n    targetIsGateway: boolean = false\n  ): void {\n    if (waypoints.length < 2) return;\n\n    const tolerance = 2;\n    const minBendOffset = 15; // Minimum distance for bend point from endpoint\n\n    // Process target endpoint (end of edge)\n    if (targetId) {\n      const targetPos = this.nodePositions.get(targetId);\n      if (targetPos) {\n        const lastIdx = waypoints.length - 1;\n        const endPoint = waypoints[lastIdx];\n        const prevPoint = waypoints[lastIdx - 1];\n\n        if (endPoint && prevPoint) {\n          const side = targetIsGateway\n            ? this.detectGatewayConnectionSide(endPoint, prevPoint, targetPos, false)\n            : this.detectConnectionSide(endPoint, targetPos, false);\n\n          if (side === 'top' || side === 'bottom') {\n            // Vertical edge - last segment must be vertical (x should be same)\n            if (Math.abs(endPoint.x - prevPoint.x) > tolerance) {\n              // Need to insert a bend point to make it vertical\n              // Calculate bend point Y position\n              const bendY = side === 'top'\n                ? endPoint.y - minBendOffset\n                : endPoint.y + minBendOffset;\n\n              // Insert bend point and update previous point to maintain orthogonality\n              // Path: ... -> prevPoint -> bendPoint -> endPoint\n              // bendPoint.x = endPoint.x (vertical final segment)\n              // bendPoint.y = bendY\n              // prevPoint needs to have y = bendY to make prevPoint->bendPoint horizontal\n              const bendPoint: PointModel = { x: endPoint.x, y: bendY };\n              waypoints.splice(lastIdx, 0, bendPoint);\n\n              // Update prevPoint's y to match bendY for orthogonality\n              prevPoint.y = bendY;\n            }\n          } else if (side === 'left' || side === 'right') {\n            // Horizontal edge - last segment must be horizontal (y should be same)\n            if (Math.abs(endPoint.y - prevPoint.y) > tolerance) {\n              // Need to insert a bend point to make it horizontal\n              const bendX = side === 'left'\n                ? endPoint.x - minBendOffset\n                : endPoint.x + minBendOffset;\n\n              const bendPoint: PointModel = { x: bendX, y: endPoint.y };\n              waypoints.splice(lastIdx, 0, bendPoint);\n\n              // Update prevPoint's x to match bendX for orthogonality\n              prevPoint.x = bendX;\n            }\n          }\n        }\n      }\n    }\n\n    // Process source endpoint (start of edge)\n    if (sourceId) {\n      // Check both nodePositions and boundaryEventPositions for source\n      const sourcePos = this.nodePositions.get(sourceId) ?? this.boundaryEventPositions.get(sourceId);\n      if (sourcePos) {\n        const startPoint = waypoints[0];\n        const nextPoint = waypoints[1];\n\n        if (startPoint && nextPoint) {\n          const side = sourceIsGateway\n            ? this.detectGatewayConnectionSide(startPoint, nextPoint, sourcePos, true)\n            : this.detectConnectionSide(startPoint, sourcePos, false);\n\n          if (side === 'top' || side === 'bottom') {\n            // Vertical edge - first segment must be vertical (x should be same)\n            if (Math.abs(startPoint.x - nextPoint.x) > tolerance) {\n              // Need to insert a bend point to make it vertical\n              const bendY = side === 'top'\n                ? startPoint.y - minBendOffset\n                : startPoint.y + minBendOffset;\n\n              const bendPoint: PointModel = { x: startPoint.x, y: bendY };\n              waypoints.splice(1, 0, bendPoint);\n\n              // Update nextPoint's y to match bendY for orthogonality\n              nextPoint.y = bendY;\n            }\n          } else if (side === 'left' || side === 'right') {\n            // Horizontal edge - first segment must be horizontal (y should be same)\n            if (Math.abs(startPoint.y - nextPoint.y) > tolerance) {\n              // Need to insert a bend point to make it horizontal\n              const bendX = side === 'left'\n                ? startPoint.x - minBendOffset\n                : startPoint.x + minBendOffset;\n\n              const bendPoint: PointModel = { x: bendX, y: startPoint.y };\n              waypoints.splice(1, 0, bendPoint);\n\n              // Update nextPoint's x to match bendX for orthogonality\n              nextPoint.x = bendX;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Re-route any axis-aligned segment that crosses a non-endpoint node.\n   *\n   * For each blocked segment we slide it perpendicular until it clears ALL\n   * obstacles in its band — picking just past the directly crossed one can\n   * land the segment inside a different node sitting at the new coordinate.\n   * The scan repeats until no segment moves, since a slide can introduce a\n   * new crossing on a neighboring segment.\n   */\n  private routeAroundLocalObstacles(\n    waypoints: PointModel[],\n    sourceId?: string,\n    targetId?: string\n  ): boolean {\n    if (waypoints.length < 2) return false;\n    const margin = 10;\n\n    const obstacles = this.collectEdgeObstacles(sourceId, targetId);\n    if (obstacles.length === 0) return false;\n\n    // Slide `preferred` along one axis past every interval in `intervals`\n    // that contains it. Intervals are sorted and merged so a single sweep\n    // jumps to the first gap in the chosen direction.\n    const findClearance = (\n      preferred: number,\n      direction: 1 | -1,\n      intervals: Array<{ lo: number; hi: number }>\n    ): number => {\n      const merged = mergeIntervals(intervals, margin);\n      if (direction === 1) {\n        for (const iv of merged) {\n          if (preferred >= iv.hi) continue;\n          if (preferred <= iv.lo) return preferred;\n          preferred = iv.hi;\n        }\n        return preferred;\n      }\n      for (let i = merged.length - 1; i >= 0; i--) {\n        const iv = merged[i];\n        if (preferred <= iv.lo) continue;\n        if (preferred >= iv.hi) return preferred;\n        preferred = iv.lo;\n      }\n      return preferred;\n    };\n\n    const trySlide = (i: number, axis: 'x' | 'y'): boolean => {\n      const a = waypoints[i];\n      const b = waypoints[i + 1];\n      if (!a || !b) return false;\n      // The slide axis is the one the segment is *constant* on. For a\n      // horizontal segment (constant y) we slide y; perpendicular span is x.\n      const slide = axis;\n      const span = axis === 'y' ? 'x' : 'y';\n      const dim = axis === 'y' ? 'height' : 'width';\n      const perpDim = span === 'y' ? 'height' : 'width';\n\n      const segSlide = a[slide];\n      const segMin = Math.min(a[span], b[span]);\n      const segMax = Math.max(a[span], b[span]);\n\n      const band: Array<{ lo: number; hi: number }> = [];\n      let crosses = false;\n      for (const obs of obstacles) {\n        const oSpan = obs[span];\n        const oSpanHi = oSpan + obs[perpDim];\n        if (segMax <= oSpan + 1 || segMin >= oSpanHi - 1) continue;\n        const oSlide = obs[slide];\n        const oSlideHi = oSlide + obs[dim];\n        band.push({ lo: oSlide, hi: oSlideHi });\n        if (segSlide > oSlide + 1 && segSlide < oSlideHi - 1) crosses = true;\n      }\n      if (!crosses) return false;\n\n      const lower = findClearance(segSlide, -1, band);\n      const upper = findClearance(segSlide, 1, band);\n      const distLower = lower > 0 ? segSlide - lower : Infinity;\n      const distUpper = upper - segSlide;\n      const newVal = distLower <= distUpper ? lower : upper;\n\n      const isFirst = i === 0;\n      const isLast = i === waypoints.length - 2;\n      if (isFirst && isLast) return false;\n      if (isFirst) {\n        const bend = { x: a.x, y: a.y, [slide]: newVal } as PointModel;\n        bend[span] = a[span];\n        waypoints.splice(i + 1, 0, bend);\n        b[slide] = newVal;\n      } else if (isLast) {\n        a[slide] = newVal;\n        const bend = { x: b.x, y: b.y, [slide]: newVal } as PointModel;\n        bend[span] = b[span];\n        waypoints.splice(i + 1, 0, bend);\n      } else {\n        a[slide] = newVal;\n        b[slide] = newVal;\n      }\n      return true;\n    };\n\n    let changed = false;\n    // Bounded outer loop: a slide on one segment can push a neighbor into a\n    // new obstacle. 8 iterations is well above the diameter of any path we\n    // produce; hitting the cap means the route can't be cleared and the\n    // hard \"no crossings\" constraint is violated — surface in tests.\n    const MAX_ITERS = 8;\n    for (let iter = 0; iter < MAX_ITERS; iter++) {\n      let changedThisIter = false;\n      for (let i = waypoints.length - 2; i >= 0; i--) {\n        const a = waypoints[i];\n        const b = waypoints[i + 1];\n        if (!a || !b) continue;\n        const dxAbs = Math.abs(a.x - b.x);\n        const dyAbs = Math.abs(a.y - b.y);\n        const moved =\n          (dyAbs <= 1 && dxAbs > 1 && trySlide(i, 'y')) ||\n          (dxAbs <= 1 && dyAbs > 1 && trySlide(i, 'x'));\n        if (moved) {\n          changed = true;\n          changedThisIter = true;\n        }\n      }\n      if (!changedThisIter) break;\n      if (iter === MAX_ITERS - 1 && isDebugEnabled()) {\n        console.log('[BPMN] routeAroundLocalObstacles: hit MAX_ITERS, some crossings may remain');\n      }\n    }\n\n    return changed;\n  }\n\n  private collectEdgeObstacles(\n    sourceId: string | undefined,\n    targetId: string | undefined\n  ): NodePosition[] {\n    const out: NodePosition[] = [];\n    for (const [id, pos] of this.nodePositions) {\n      if (id === sourceId || id === targetId) continue;\n      const dataOwner = this.dataObjectOwners.get(id);\n      if (dataOwner !== undefined) {\n        if (dataOwner !== sourceId && dataOwner !== targetId) out.push(pos);\n        continue;\n      }\n      if (this.isObstacleNode(id)) out.push(pos);\n    }\n    return out;\n  }\n\n  private isObstacleNode(id: string): boolean {\n    const info = this.nodeBpmn.get(id);\n    if (!info?.type) return false;\n    const t = info.type;\n    if (t === 'dataObject' || t === 'dataObjectReference' ||\n        t === 'dataInput' || t === 'dataOutput' ||\n        t === 'dataStoreReference' || t === 'textAnnotation' ||\n        t === 'group' || t === 'lane' || t === 'participant' ||\n        t === 'process' || t === 'collaboration') {\n      return false;\n    }\n    // Expanded subprocesses host the edge's coordinate space — sliding around\n    // them would push the route out of its own container.\n    if (info.isExpanded === true && (SUBPROCESS_TYPES as readonly string[]).includes(t)) {\n      return false;\n    }\n    return true;\n  }\n}\n\nfunction mergeIntervals(\n  intervals: Array<{ lo: number; hi: number }>,\n  margin: number\n): Array<{ lo: number; hi: number }> {\n  if (intervals.length === 0) return intervals;\n  const sorted = intervals\n    .map((iv) => ({ lo: iv.lo - margin, hi: iv.hi + margin }))\n    .sort((a, b) => a.lo - b.lo);\n  const merged: Array<{ lo: number; hi: number }> = [sorted[0]];\n  for (let i = 1; i < sorted.length; i++) {\n    const last = merged[merged.length - 1];\n    const cur = sorted[i];\n    if (cur.lo <= last.hi) {\n      if (cur.hi > last.hi) last.hi = cur.hi;\n    } else {\n      merged.push(cur);\n    }\n  }\n  return merged;\n}\n","/**\n * Model Builder\n * Builds the intermediate BPMN model from layouted ELK-BPMN graph.\n * This module focuses on building the BPMN process/collaboration structure,\n * while DiagramBuilder handles the visual diagram (shapes and edges).\n */\n\nimport type { LayoutedGraph } from '../types/elk-output';\nimport type {\n  MessageDefinition,\n  SignalDefinition,\n  ErrorDefinition,\n  EscalationDefinition,\n} from '../types';\nimport { ReferenceResolver } from './reference-resolver';\nimport { LaneResolver, type LaneSetInfo } from './lane-resolver';\nimport { DiagramBuilder } from './diagram-builder';\nimport type {\n  BpmnModel,\n  DefinitionsModel,\n  CollaborationModel,\n  ProcessModel,\n  FlowElementModel,\n  ArtifactModel,\n  DiagramModel,\n  CollaborationNode,\n  ParticipantNode,\n  ProcessNode,\n  ChildNode,\n  BoundaryEventNode,\n  EdgeNode,\n  ArtifactNode,\n  IoSpecificationModel,\n} from './model-types';\nimport type { IoSpecification } from '../types/elk-bpmn';\n\n// Re-export types for external consumers\nexport type {\n  BpmnModel,\n  DefinitionsModel,\n  CollaborationModel,\n  ProcessModel,\n  FlowElementModel,\n  ArtifactModel,\n  DiagramModel,\n  ShapeModel,\n  EdgeModel,\n  BoundsModel,\n  PointModel,\n  LabelModel,\n  PlaneModel,\n  ParticipantModel,\n  MessageFlowModel,\n  SequenceFlowModel,\n  DataAssociationModel,\n  RootElement,\n  IoSpecificationModel,\n  DataInputModel,\n  DataOutputModel,\n  InputSetModel,\n  OutputSetModel,\n} from './model-types';\n\n// ============================================================================\n// Model Builder\n// ============================================================================\n\nexport class ModelBuilder {\n  private refResolver: ReferenceResolver;\n  private laneResolver: LaneResolver;\n  private diagramBuilder: DiagramBuilder;\n\n  constructor() {\n    this.refResolver = new ReferenceResolver();\n    this.laneResolver = new LaneResolver();\n    this.diagramBuilder = new DiagramBuilder();\n  }\n\n  /**\n   * Build the complete BPMN model from a layouted graph\n   */\n  build(graph: LayoutedGraph): BpmnModel {\n    // Reset resolvers\n    this.laneResolver.reset();\n\n    // Resolve references first\n    this.refResolver.resolve(graph);\n\n    // Build definitions model\n    const definitions = this.buildDefinitions(graph);\n\n    // Build diagram model using DiagramBuilder\n    const diagram = this.diagramBuilder.build(graph, definitions);\n\n    return { definitions, diagram };\n  }\n\n  /**\n   * Get the reference resolver\n   */\n  getRefResolver(): ReferenceResolver {\n    return this.refResolver;\n  }\n\n  /**\n   * Build definitions model\n   */\n  private buildDefinitions(graph: LayoutedGraph): DefinitionsModel {\n    const definitions: DefinitionsModel = {\n      id: graph.id,\n      targetNamespace: graph.bpmn?.targetNamespace ?? 'http://bpmn.io/schema/bpmn',\n      exporter: graph.bpmn?.exporter ?? 'bpmn-elk-layout',\n      exporterVersion: graph.bpmn?.exporterVersion ?? '1.0.0',\n      messages: graph.messages ?? [],\n      signals: graph.signals ?? [],\n      errors: graph.errors ?? [],\n      escalations: graph.escalations ?? [],\n      rootElements: [],\n    };\n\n    // Process top-level children\n    for (const child of graph.children) {\n      const bpmnType = (child as { bpmn: { type: string } }).bpmn?.type;\n\n      if (!bpmnType) {\n        throw new Error(`Invalid graph child: missing bpmn.type property for node ${(child as any).id}`);\n      }\n\n      if (bpmnType === 'collaboration') {\n        definitions.rootElements.push(this.buildCollaboration(child as CollaborationNode));\n\n        // Also add processes for each non-black-box participant\n        const collab = child as CollaborationNode;\n        for (const participant of collab.children ?? []) {\n          if (!participant.bpmn?.isBlackBox) {\n            const processId = participant.bpmn?.processRef ?? `Process_${participant.id}`;\n            definitions.rootElements.push(\n              this.buildProcessFromParticipant(participant, processId)\n            );\n          }\n        }\n      } else if (bpmnType === 'process') {\n        definitions.rootElements.push(this.buildProcess(child as ProcessNode));\n      } else {\n        throw new Error(`Invalid top-level element type: \"${bpmnType}\". Only \"process\" or \"collaboration\" are allowed at the top level.`);\n      }\n    }\n\n    if (definitions.rootElements.length === 0) {\n      throw new Error('Cannot create BPMN definitions: no valid process or collaboration found in the graph.');\n    }\n\n    return definitions;\n  }\n\n  /**\n   * Build collaboration model\n   */\n  private buildCollaboration(collab: CollaborationNode): CollaborationModel {\n    return {\n      type: 'collaboration',\n      id: collab.id,\n      name: collab.bpmn?.name,\n      isClosed: collab.bpmn?.isClosed,\n      participants: (collab.children ?? []).map((p) => ({\n        id: p.id,\n        name: p.bpmn?.name,\n        processRef: p.bpmn?.processRef ?? `Process_${p.id}`,\n        isBlackBox: p.bpmn?.isBlackBox,\n        participantMultiplicity: p.bpmn?.participantMultiplicity,\n      })),\n      messageFlows: (collab.edges ?? [])\n        .filter((e): e is typeof e & { sources: [string, ...string[]]; targets: [string, ...string[]] } =>\n          e.sources[0] !== undefined && e.targets[0] !== undefined)\n        .map((e) => ({\n          id: e.id,\n          name: e.bpmn?.name,\n          sourceRef: e.sources[0],\n          targetRef: e.targets[0],\n          messageRef: e.bpmn?.messageRef,\n        })),\n    };\n  }\n\n  /**\n   * Build process model from participant\n   */\n  private buildProcessFromParticipant(\n    participant: ParticipantNode,\n    processId: string\n  ): ProcessModel {\n    const process: ProcessModel = {\n      type: 'process',\n      id: processId,\n      name: participant.bpmn?.name,\n      isExecutable: true,\n      laneSet: this.laneResolver.resolve(participant),\n      flowElements: [],\n      artifacts: [],\n    };\n\n    // Collect all flow elements\n    this.collectFlowElements(participant.children ?? [], process.flowElements);\n\n    // Collect sequence flows\n    this.collectSequenceFlows(participant.edges ?? [], process.flowElements);\n\n    // Collect data associations and attach to flow elements (BPMN spec compliance)\n    this.collectDataAssociations(participant.edges ?? [], process.flowElements);\n\n    return process;\n  }\n\n  /**\n   * Build process model\n   */\n  private buildProcess(processNode: ProcessNode): ProcessModel {\n    const process: ProcessModel = {\n      type: 'process',\n      id: processNode.id,\n      name: processNode.bpmn?.name,\n      isExecutable: processNode.bpmn?.isExecutable ?? true,\n      processType: processNode.bpmn?.processType,\n      isClosed: processNode.bpmn?.isClosed,\n      laneSet: this.laneResolver.resolve(processNode),\n      flowElements: [],\n      artifacts: [],\n    };\n\n    // Collect all flow elements\n    this.collectFlowElements(processNode.children ?? [], process.flowElements);\n\n    // Collect sequence flows\n    this.collectSequenceFlows(processNode.edges ?? [], process.flowElements);\n\n    // Collect artifacts\n    if (processNode.artifacts) {\n      for (const artifact of processNode.artifacts) {\n        process.artifacts.push(this.buildArtifact(artifact));\n      }\n    }\n\n    // Collect associations from edges\n    this.collectAssociations(processNode.edges ?? [], process.artifacts);\n\n    // Collect data associations and attach to flow elements (BPMN spec compliance)\n    this.collectDataAssociations(processNode.edges ?? [], process.flowElements);\n\n    return process;\n  }\n\n  /**\n   * Collect flow elements recursively\n   */\n  private collectFlowElements(children: ChildNode[], elements: FlowElementModel[]): void {\n    for (const child of children) {\n      // Skip lanes - just traverse their children\n      if (child.bpmn?.type === 'lane') {\n        this.collectFlowElements(child.children ?? [], elements);\n        continue;\n      }\n\n      // Skip nested process - traverse its children and edges\n      // This handles the case where participant > children > [process > children: [flowNodes]]\n      if (child.bpmn?.type === 'process') {\n        this.collectFlowElements(child.children ?? [], elements);\n        this.collectSequenceFlows(child.edges ?? [], elements);\n        continue;\n      }\n\n      // Build flow element\n      const flowElement = this.buildFlowElement(child);\n      elements.push(flowElement);\n\n      // For expanded subprocesses, collect nested elements into the subprocess itself\n      if (child.bpmn?.isExpanded && child.children) {\n        flowElement.flowElements = [];\n        flowElement.artifacts = [];\n        this.collectFlowElements(child.children, flowElement.flowElements);\n        // Collect nested sequence flows into subprocess\n        if (child.edges) {\n          this.collectSequenceFlows(child.edges, flowElement.flowElements);\n        }\n      } else if (child.edges) {\n        // Collect nested sequence flows for non-expanded containers\n        this.collectSequenceFlows(child.edges, elements);\n      }\n\n      // Add boundary events (after subprocess content processing)\n      if (child.boundaryEvents) {\n        for (const be of child.boundaryEvents) {\n          elements.push(this.buildBoundaryEvent(be));\n        }\n      }\n    }\n  }\n\n  /**\n   * Build a flow element model\n   */\n  private buildFlowElement(node: ChildNode): FlowElementModel {\n    const incoming = this.refResolver.getIncomingSequenceFlows(node.id);\n    const outgoing = this.refResolver.getOutgoingSequenceFlows(node.id);\n\n    const flowElement: FlowElementModel = {\n      type: node.bpmn?.type ?? 'task',\n      id: node.id,\n      name: node.bpmn?.name,\n      incoming,\n      outgoing,\n      properties: this.extractProperties(node.bpmn ?? {}),\n    };\n\n    // Extract ioSpecification if present (for tasks)\n    const ioSpec = (node.bpmn as { ioSpecification?: IoSpecification } | undefined)?.ioSpecification;\n    if (ioSpec) {\n      flowElement.ioSpecification = this.buildIoSpecification(ioSpec, node.id);\n\n      // Auto-generate dataInputAssociation for only the first dataInput\n      // Only the topmost input in the vertical stack gets a dashed line to the task\n      const dataInputs = ioSpec.dataInputs ?? [];\n      if (dataInputs.length > 0) {\n        const firstInput = dataInputs[0];\n        flowElement.dataInputAssociations = [{\n          id: `${firstInput.id ?? `${node.id}_input_0`}_assoc`,\n          sourceRef: firstInput.id ?? `${node.id}_input_0`,\n          targetRef: node.id,\n        }];\n      }\n\n      // Auto-generate dataOutputAssociation for only the first dataOutput\n      // Only the topmost output in the vertical stack gets a dashed line from the task\n      const dataOutputs = ioSpec.dataOutputs ?? [];\n      if (dataOutputs.length > 0) {\n        const firstOutput = dataOutputs[0];\n        flowElement.dataOutputAssociations = [{\n          id: `${firstOutput.id ?? `${node.id}_output_0`}_assoc`,\n          sourceRef: node.id,\n          targetRef: firstOutput.id ?? `${node.id}_output_0`,\n        }];\n      }\n    }\n\n    return flowElement;\n  }\n\n  /**\n   * Build ioSpecification model from input\n   */\n  private buildIoSpecification(ioSpec: IoSpecification, taskId: string): IoSpecificationModel {\n    const dataInputs = (ioSpec.dataInputs ?? []).map((di, index) => ({\n      id: di.id ?? `${taskId}_input_${index}`,\n      name: di.name,\n      itemSubjectRef: di.itemSubjectRef,\n      isCollection: di.isCollection,\n    }));\n\n    const dataOutputs = (ioSpec.dataOutputs ?? []).map((dout, index) => ({\n      id: dout.id ?? `${taskId}_output_${index}`,\n      name: dout.name,\n      itemSubjectRef: dout.itemSubjectRef,\n      isCollection: dout.isCollection,\n    }));\n\n    // Build inputSets - if not provided, create default one with all inputs\n    const inputSets = (ioSpec.inputSets ?? []).map((is, index) => ({\n      id: is.id ?? `${taskId}_inputSet_${index}`,\n      name: is.name,\n      dataInputRefs: is.dataInputRefs ?? [],\n    }));\n    if (inputSets.length === 0 && dataInputs.length > 0) {\n      inputSets.push({\n        id: `${taskId}_inputSet_0`,\n        name: undefined,\n        dataInputRefs: dataInputs.map(di => di.id),\n      });\n    }\n\n    // Build outputSets - if not provided, create default one with all outputs\n    const outputSets = (ioSpec.outputSets ?? []).map((os, index) => ({\n      id: os.id ?? `${taskId}_outputSet_${index}`,\n      name: os.name,\n      dataOutputRefs: os.dataOutputRefs ?? [],\n    }));\n    if (outputSets.length === 0 && dataOutputs.length > 0) {\n      outputSets.push({\n        id: `${taskId}_outputSet_0`,\n        name: undefined,\n        dataOutputRefs: dataOutputs.map(dout => dout.id),\n      });\n    }\n\n    return {\n      dataInputs,\n      dataOutputs,\n      inputSets,\n      outputSets,\n    };\n  }\n\n  /**\n   * Build a boundary event model\n   */\n  private buildBoundaryEvent(be: BoundaryEventNode): FlowElementModel {\n    const incoming = this.refResolver.getIncomingSequenceFlows(be.id);\n    const outgoing = this.refResolver.getOutgoingSequenceFlows(be.id);\n\n    return {\n      type: 'boundaryEvent',\n      id: be.id,\n      name: be.bpmn?.name,\n      incoming,\n      outgoing,\n      attachedToRef: be.attachedToRef,\n      cancelActivity: be.bpmn?.isInterrupting ?? be.bpmn?.cancelActivity ?? true,\n      properties: this.extractProperties(be.bpmn ?? {}),\n    };\n  }\n\n  /**\n   * Collect sequence flows\n   */\n  private collectSequenceFlows(edges: EdgeNode[], elements: FlowElementModel[]): void {\n    for (const edge of edges) {\n      if (edge.bpmn?.type === 'sequenceFlow') {\n        elements.push({\n          type: 'sequenceFlow',\n          id: edge.id,\n          name: edge.bpmn?.name,\n          incoming: [],\n          outgoing: [],\n          properties: {\n            sourceRef: edge.sources[0],\n            targetRef: edge.targets[0],\n            conditionExpression: edge.bpmn?.conditionExpression,\n            isDefault: edge.bpmn?.isDefault,\n          },\n        });\n      }\n    }\n  }\n\n  /**\n   * Collect associations from edges\n   */\n  private collectAssociations(edges: EdgeNode[], artifacts: ArtifactModel[]): void {\n    for (const edge of edges) {\n      if (edge.bpmn?.type === 'association') {\n        artifacts.push({\n          type: 'association',\n          id: edge.id,\n          name: edge.bpmn?.name,\n          properties: {\n            sourceRef: edge.sources[0],\n            targetRef: edge.targets[0],\n            associationDirection: (edge.bpmn as { associationDirection?: string })?.associationDirection ?? 'None',\n          },\n        });\n      }\n    }\n  }\n\n  /**\n   * Collect data associations from edges and attach them to flow elements\n   * Per BPMN 2.0 spec: dataInputAssociation/dataOutputAssociation are child elements of Activity\n   */\n  private collectDataAssociations(edges: EdgeNode[], elements: FlowElementModel[]): void {\n    // Build a map of element IDs to their models for quick lookup\n    const elementMap = new Map<string, FlowElementModel>();\n    for (const element of elements) {\n      elementMap.set(element.id, element);\n    }\n\n    for (const edge of edges) {\n      const edgeType = edge.bpmn?.type;\n\n      if (edgeType === 'dataInputAssociation') {\n        // dataInputAssociation: data object (source) -> task (target)\n        // The association is a child of the TARGET task\n        const targetId = edge.targets[0];\n        const sourceId = edge.sources[0];\n        if (!targetId || !sourceId) continue;\n        const targetElement = elementMap.get(targetId);\n\n        if (targetElement) {\n          if (!targetElement.dataInputAssociations) {\n            targetElement.dataInputAssociations = [];\n          }\n          targetElement.dataInputAssociations.push({\n            id: edge.id,\n            sourceRef: sourceId,\n          });\n        }\n      } else if (edgeType === 'dataOutputAssociation') {\n        // dataOutputAssociation: task (source) -> data object (target)\n        // The association is a child of the SOURCE task\n        const sourceId = edge.sources[0];\n        const targetId = edge.targets[0];\n        if (!sourceId || !targetId) continue;\n        const sourceElement = elementMap.get(sourceId);\n\n        if (sourceElement) {\n          if (!sourceElement.dataOutputAssociations) {\n            sourceElement.dataOutputAssociations = [];\n          }\n          sourceElement.dataOutputAssociations.push({\n            id: edge.id,\n            sourceRef: sourceId,\n            targetRef: targetId,\n          });\n        }\n      }\n    }\n  }\n\n  /**\n   * Build an artifact model\n   */\n  private buildArtifact(artifact: ArtifactNode): ArtifactModel {\n    return {\n      type: artifact.bpmn?.type ?? 'textAnnotation',\n      id: artifact.id,\n      name: artifact.bpmn?.name,\n      properties: this.extractProperties(artifact.bpmn ?? {}),\n    };\n  }\n\n  /**\n   * Extract properties from bpmn object (excluding type and name)\n   */\n  private extractProperties(bpmn: Record<string, unknown>): Record<string, unknown> {\n    const { type, name, ...rest } = bpmn;\n    return rest;\n  }\n}\n","/**\n * BPMN XML Generator\n * Generates BPMN 2.0 XML from the intermediate model using bpmn-moddle\n */\n\nimport BpmnModdle from 'bpmn-moddle';\nimport type {\n  BpmnModel,\n  DefinitionsModel,\n  DiagramModel,\n  ProcessModel,\n  CollaborationModel,\n  FlowElementModel,\n  ArtifactModel,\n  ShapeModel,\n  EdgeModel,\n  IoSpecificationModel,\n} from '../transform/model-builder';\nimport type { LaneSetInfo, LaneInfo } from '../transform/lane-resolver';\nimport { BPMN_ELEMENT_MAP, EVENT_DEFINITION_MAP } from '../types/bpmn-constants';\n\n// Type definitions for bpmn-moddle elements\ninterface ModdleElement {\n  $type: string;\n  id?: string;\n  [key: string]: unknown;\n}\n\nexport class BpmnXmlGenerator {\n  private moddle: BpmnModdle;\n\n  constructor() {\n    this.moddle = new BpmnModdle();\n  }\n\n  /**\n   * Generate BPMN 2.0 XML from the model\n   */\n  async generate(model: BpmnModel): Promise<string> {\n    // Build the definitions element\n    const definitions = this.buildDefinitions(model.definitions, model.diagram);\n\n    // Serialize to XML\n    const { xml } = await this.moddle.toXML(definitions, {\n      format: true,\n      preamble: true,\n    });\n\n    return xml;\n  }\n\n  /**\n   * Build the root definitions element\n   */\n  private buildDefinitions(def: DefinitionsModel, diagram: DiagramModel): ModdleElement {\n    const definitions = this.moddle.create('bpmn:Definitions', {\n      id: def.id,\n      targetNamespace: def.targetNamespace,\n      exporter: def.exporter,\n      exporterVersion: def.exporterVersion,\n    });\n\n    const rootElements: ModdleElement[] = [];\n\n    // Add global definitions (messages, signals, errors, escalations)\n    for (const msg of def.messages) {\n      rootElements.push(\n        this.moddle.create('bpmn:Message', {\n          id: msg.id,\n          name: msg.name,\n        })\n      );\n    }\n\n    for (const sig of def.signals) {\n      rootElements.push(\n        this.moddle.create('bpmn:Signal', {\n          id: sig.id,\n          name: sig.name,\n        })\n      );\n    }\n\n    for (const err of def.errors) {\n      rootElements.push(\n        this.moddle.create('bpmn:Error', {\n          id: err.id,\n          name: err.name,\n          errorCode: err.errorCode,\n        })\n      );\n    }\n\n    for (const esc of def.escalations) {\n      rootElements.push(\n        this.moddle.create('bpmn:Escalation', {\n          id: esc.id,\n          name: esc.name,\n          escalationCode: esc.escalationCode,\n        })\n      );\n    }\n\n    // Add root elements (collaborations and processes)\n    for (const element of def.rootElements) {\n      if (element.type === 'collaboration') {\n        rootElements.push(this.buildCollaboration(element, def.messages));\n      } else if (element.type === 'process') {\n        rootElements.push(this.buildProcess(element));\n      }\n    }\n\n    definitions.rootElements = rootElements;\n\n    // Add diagram\n    definitions.diagrams = [this.buildDiagram(diagram)];\n\n    return definitions;\n  }\n\n  /**\n   * Build a collaboration element\n   */\n  private buildCollaboration(\n    collab: CollaborationModel,\n    messages: { id: string; name?: string }[] = []\n  ): ModdleElement {\n    const collaboration = this.moddle.create('bpmn:Collaboration', {\n      id: collab.id,\n      name: collab.name,\n      isClosed: collab.isClosed,\n    });\n\n    // Add participants\n    collaboration.participants = collab.participants.map((p) => {\n      const participant = this.moddle.create('bpmn:Participant', {\n        id: p.id,\n        name: p.name,\n        processRef: p.processRef ? { id: p.processRef } : undefined,\n      });\n\n      if (p.participantMultiplicity) {\n        participant.participantMultiplicity = this.moddle.create(\n          'bpmn:ParticipantMultiplicity',\n          {\n            minimum: p.participantMultiplicity.minimum,\n            maximum: p.participantMultiplicity.maximum,\n          }\n        );\n      }\n\n      return participant;\n    });\n\n    // Add message flows.\n    // bpmn.io renders the BPMNLabel (driven by messageFlow.name) AND auto-draws\n    // messageRef.name at the edge midpoint — so when both exist the same label\n    // appears twice (the \"请求/请求消息\" pile-up). Suppress messageFlow.name\n    // whenever a messageRef carries the canonical label; otherwise keep it.\n    const messagesById = new Map(messages.map((m) => [m.id, m]));\n    collaboration.messageFlows = collab.messageFlows.map((mf) => {\n      const refMsg = mf.messageRef ? messagesById.get(mf.messageRef) : undefined;\n      const hideName = refMsg?.name !== undefined && refMsg.name !== '';\n      return this.moddle.create('bpmn:MessageFlow', {\n        id: mf.id,\n        name: hideName ? undefined : mf.name,\n        sourceRef: { id: mf.sourceRef },\n        targetRef: { id: mf.targetRef },\n        messageRef: mf.messageRef ? { id: mf.messageRef } : undefined,\n      });\n    });\n\n    return collaboration;\n  }\n\n  /**\n   * Build a process element\n   */\n  private buildProcess(process: ProcessModel): ModdleElement {\n    const bpmnProcess = this.moddle.create('bpmn:Process', {\n      id: process.id,\n      name: process.name,\n      isExecutable: process.isExecutable ?? true,\n      processType: process.processType,\n      isClosed: process.isClosed,\n    });\n\n    const flowElements: ModdleElement[] = [];\n\n    // Add lane set if present\n    if (process.laneSet) {\n      bpmnProcess.laneSets = [this.buildLaneSet(process.laneSet)];\n    }\n\n    // Add flow elements\n    for (const element of process.flowElements) {\n      flowElements.push(this.buildFlowElement(element));\n    }\n\n    bpmnProcess.flowElements = flowElements;\n\n    // Add artifacts\n    if (process.artifacts.length > 0) {\n      bpmnProcess.artifacts = process.artifacts.map((a) => this.buildArtifact(a));\n    }\n\n    return bpmnProcess;\n  }\n\n  /**\n   * Build a lane set\n   */\n  private buildLaneSet(laneSet: LaneSetInfo): ModdleElement {\n    const bpmnLaneSet = this.moddle.create('bpmn:LaneSet', {\n      id: laneSet.id,\n    });\n\n    bpmnLaneSet.lanes = laneSet.lanes.map((lane) => this.buildLane(lane));\n\n    return bpmnLaneSet;\n  }\n\n  /**\n   * Build a lane\n   */\n  private buildLane(lane: LaneInfo): ModdleElement {\n    const bpmnLane = this.moddle.create('bpmn:Lane', {\n      id: lane.id,\n      name: lane.name,\n    });\n\n    // Add flow node references\n    bpmnLane.flowNodeRef = lane.flowNodeRefs.map((ref) => ({ id: ref }));\n\n    // Add child lane set if present\n    if (lane.childLaneSet) {\n      bpmnLane.childLaneSet = this.buildLaneSet(lane.childLaneSet);\n    }\n\n    return bpmnLane;\n  }\n\n  /**\n   * Build a flow element (event, task, gateway, subprocess, sequence flow)\n   */\n  private buildFlowElement(element: FlowElementModel): ModdleElement {\n    const elementType = BPMN_ELEMENT_MAP[element.type as keyof typeof BPMN_ELEMENT_MAP];\n    if (!elementType) {\n      throw new Error(`Unknown element type: ${element.type}`);\n    }\n\n    // TextAnnotation's text body must be set at creation time so the moddle\n    // serializer emits `<bpmn:text>…</bpmn:text>` correctly. Assigning it\n    // post-creation is silently ignored by the serializer.\n    const createAttrs: Record<string, unknown> = {\n      id: element.id,\n    };\n    if (element.name) {\n      createAttrs.name = element.name;\n    }\n    if (element.type === 'textAnnotation') {\n      const text = element.properties['text'];\n      if (typeof text === 'string' && text.length > 0) {\n        createAttrs.text = text;\n      }\n    }\n    const bpmnElement = this.moddle.create(elementType, createAttrs);\n\n    // Add incoming/outgoing references\n    if (element.incoming.length > 0) {\n      bpmnElement.incoming = element.incoming.map((id) => ({ id }));\n    }\n    if (element.outgoing.length > 0) {\n      bpmnElement.outgoing = element.outgoing.map((id) => ({ id }));\n    }\n\n    // Handle specific element types\n    this.applyElementProperties(bpmnElement, element);\n\n    // Add data associations (BPMN 2.0 spec: child elements of Activity)\n    this.applyDataAssociations(bpmnElement, element);\n\n    return bpmnElement;\n  }\n\n  /**\n   * Apply element-specific properties\n   */\n  private applyElementProperties(bpmnElement: ModdleElement, element: FlowElementModel): void {\n    const props = element.properties;\n\n    // Events\n    if (element.type.includes('Event')) {\n      this.applyEventProperties(bpmnElement, element);\n    }\n\n    // Tasks\n    if (element.type.includes('Task') || element.type === 'task') {\n      this.applyTaskProperties(bpmnElement, props);\n      // Add ioSpecification if present\n      if (element.ioSpecification) {\n        bpmnElement.ioSpecification = this.buildIoSpecification(element.ioSpecification);\n      }\n    }\n\n    // Gateways\n    if (element.type.includes('Gateway')) {\n      this.applyGatewayProperties(bpmnElement, props);\n    }\n\n    // SubProcesses\n    if (element.type === 'subProcess' || element.type === 'transaction' ||\n        element.type === 'adHocSubProcess' || element.type === 'eventSubProcess') {\n      this.applySubProcessProperties(bpmnElement, props);\n\n      // Add nested flow elements for expanded subprocesses\n      if (element.flowElements && element.flowElements.length > 0) {\n        bpmnElement.flowElements = element.flowElements.map((fe) => this.buildFlowElement(fe));\n      }\n      if (element.artifacts && element.artifacts.length > 0) {\n        bpmnElement.artifacts = element.artifacts.map((a) => this.buildArtifact(a));\n      }\n    }\n\n    // Call Activity\n    if (element.type === 'callActivity') {\n      this.applyCallActivityProperties(bpmnElement, props);\n    }\n\n    // Boundary Event\n    if (element.type === 'boundaryEvent') {\n      bpmnElement.attachedToRef = { id: element.attachedToRef };\n      bpmnElement.cancelActivity = element.cancelActivity ?? true;\n    }\n\n    // Sequence Flow\n    if (element.type === 'sequenceFlow') {\n      this.applySequenceFlowProperties(bpmnElement, props);\n    }\n\n    // Loop characteristics\n    if (props.loopCharacteristics) {\n      bpmnElement.loopCharacteristics = this.buildLoopCharacteristics(\n        props.loopCharacteristics as LoopCharacteristicsProps\n      );\n    }\n  }\n\n  /**\n   * Apply event-specific properties\n   */\n  private applyEventProperties(bpmnElement: ModdleElement, element: FlowElementModel): void {\n    const props = element.properties;\n    const eventDefType = props.eventDefinitionType as string | undefined;\n\n    if (!eventDefType || eventDefType === 'none') {\n      return;\n    }\n\n    const eventDefElementType = EVENT_DEFINITION_MAP[eventDefType as keyof typeof EVENT_DEFINITION_MAP];\n    if (!eventDefElementType) {\n      return;\n    }\n\n    const eventDef = this.moddle.create(eventDefElementType, {});\n\n    // Apply event definition specific properties\n    switch (eventDefType) {\n      case 'message':\n        if (props.messageRef) {\n          eventDef.messageRef = { id: props.messageRef as string };\n        }\n        break;\n      case 'signal':\n        if (props.signalRef) {\n          eventDef.signalRef = { id: props.signalRef as string };\n        }\n        break;\n      case 'error':\n        if (props.errorRef) {\n          eventDef.errorRef = { id: props.errorRef as string };\n        }\n        break;\n      case 'escalation':\n        if (props.escalationRef) {\n          eventDef.escalationRef = { id: props.escalationRef as string };\n        }\n        break;\n      case 'timer':\n        if (props.timerEventDefinition) {\n          const timerDef = props.timerEventDefinition as TimerEventDefinitionProps;\n          if (timerDef.timeDate) {\n            eventDef.timeDate = this.moddle.create('bpmn:FormalExpression', {\n              body: timerDef.timeDate,\n            });\n          }\n          if (timerDef.timeDuration) {\n            eventDef.timeDuration = this.moddle.create('bpmn:FormalExpression', {\n              body: timerDef.timeDuration,\n            });\n          }\n          if (timerDef.timeCycle) {\n            eventDef.timeCycle = this.moddle.create('bpmn:FormalExpression', {\n              body: timerDef.timeCycle,\n            });\n          }\n        }\n        break;\n      case 'conditional':\n        if (props.conditionalEventDefinition) {\n          const condDef = props.conditionalEventDefinition as ConditionalEventDefinitionProps;\n          if (condDef.condition) {\n            eventDef.condition = this.moddle.create('bpmn:FormalExpression', {\n              language: condDef.condition.language,\n              body: condDef.condition.body,\n            });\n          }\n        }\n        break;\n      case 'link':\n        if (props.linkEventDefinition) {\n          const linkDef = props.linkEventDefinition as LinkEventDefinitionProps;\n          eventDef.name = linkDef.name;\n          if (linkDef.target) {\n            eventDef.target = { id: linkDef.target };\n          }\n        }\n        break;\n    }\n\n    bpmnElement.eventDefinitions = [eventDef];\n  }\n\n  /**\n   * Apply task-specific properties\n   */\n  private applyTaskProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    // User Task properties (Camunda extensions would go here)\n    // For standard BPMN, we just set the basic properties\n    if (props.implementation) {\n      bpmnElement.implementation = props.implementation;\n    }\n\n    // Script Task\n    if (props.script) {\n      const script = props.script as ScriptProps;\n      bpmnElement.scriptFormat = script.scriptFormat;\n      bpmnElement.script = script.script;\n    }\n\n    // Send/Receive Task\n    if (props.messageRef) {\n      bpmnElement.messageRef = { id: props.messageRef as string };\n    }\n    if (props.instantiate !== undefined) {\n      bpmnElement.instantiate = props.instantiate;\n    }\n  }\n\n  /**\n   * Apply gateway-specific properties\n   */\n  private applyGatewayProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    if (props.gatewayDirection) {\n      bpmnElement.gatewayDirection = props.gatewayDirection;\n    }\n    if (props.default) {\n      bpmnElement.default = { id: props.default as string };\n    }\n    if (props.instantiate !== undefined) {\n      bpmnElement.instantiate = props.instantiate;\n    }\n    if (props.eventGatewayType) {\n      bpmnElement.eventGatewayType = props.eventGatewayType;\n    }\n    if (props.activationCondition) {\n      bpmnElement.activationCondition = this.moddle.create('bpmn:FormalExpression', {\n        body: props.activationCondition as string,\n      });\n    }\n  }\n\n  /**\n   * Apply subprocess-specific properties\n   */\n  private applySubProcessProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    if (props['triggeredByEvent'] !== undefined) {\n      bpmnElement['triggeredByEvent'] = props['triggeredByEvent'];\n    }\n\n    // AdHoc SubProcess\n    if (props['adHocOrdering']) {\n      bpmnElement['ordering'] = props['adHocOrdering'];\n    }\n    if (props['adHocCompletionCondition']) {\n      bpmnElement['completionCondition'] = this.moddle.create('bpmn:FormalExpression', {\n        body: props['adHocCompletionCondition'] as string,\n      });\n    }\n    if (props['cancelRemainingInstances'] !== undefined) {\n      bpmnElement['cancelRemainingInstances'] = props['cancelRemainingInstances'];\n    }\n\n    // Transaction\n    if (props['transactionProtocol']) {\n      bpmnElement['protocol'] = props['transactionProtocol'];\n    }\n  }\n\n  /**\n   * Apply call activity properties\n   */\n  private applyCallActivityProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    if (props['calledElement']) {\n      bpmnElement['calledElement'] = props['calledElement'];\n    }\n  }\n\n  /**\n   * Apply sequence flow properties\n   */\n  private applySequenceFlowProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    bpmnElement['sourceRef'] = { id: props['sourceRef'] as string };\n    bpmnElement['targetRef'] = { id: props['targetRef'] as string };\n\n    if (props['conditionExpression']) {\n      const condExpr = props['conditionExpression'] as ConditionExpressionProps;\n      bpmnElement['conditionExpression'] = this.moddle.create('bpmn:FormalExpression', {\n        language: condExpr.language,\n        body: condExpr.body,\n      });\n    }\n  }\n\n  /**\n   * Build ioSpecification element\n   */\n  private buildIoSpecification(ioSpec: IoSpecificationModel): ModdleElement {\n    const ioSpecElement = this.moddle.create('bpmn:InputOutputSpecification', {});\n\n    // Build dataInputs\n    if (ioSpec.dataInputs.length > 0) {\n      ioSpecElement.dataInputs = ioSpec.dataInputs.map((di) => {\n        return this.moddle.create('bpmn:DataInput', {\n          id: di.id,\n          name: di.name,\n          isCollection: di.isCollection,\n        });\n      });\n    }\n\n    // Build dataOutputs\n    if (ioSpec.dataOutputs.length > 0) {\n      ioSpecElement.dataOutputs = ioSpec.dataOutputs.map((dout) => {\n        return this.moddle.create('bpmn:DataOutput', {\n          id: dout.id,\n          name: dout.name,\n          isCollection: dout.isCollection,\n        });\n      });\n    }\n\n    // Build inputSets\n    if (ioSpec.inputSets.length > 0) {\n      ioSpecElement.inputSets = ioSpec.inputSets.map((is) => {\n        const inputSet = this.moddle.create('bpmn:InputSet', {\n          id: is.id,\n          name: is.name,\n        });\n        if (is.dataInputRefs.length > 0) {\n          inputSet.dataInputRefs = is.dataInputRefs.map((ref) => ({ id: ref }));\n        }\n        return inputSet;\n      });\n    }\n\n    // Build outputSets\n    if (ioSpec.outputSets.length > 0) {\n      ioSpecElement.outputSets = ioSpec.outputSets.map((os) => {\n        const outputSet = this.moddle.create('bpmn:OutputSet', {\n          id: os.id,\n          name: os.name,\n        });\n        if (os.dataOutputRefs.length > 0) {\n          outputSet.dataOutputRefs = os.dataOutputRefs.map((ref) => ({ id: ref }));\n        }\n        return outputSet;\n      });\n    }\n\n    return ioSpecElement;\n  }\n\n  /**\n   * Apply data associations (BPMN 2.0 spec: dataInputAssociation/dataOutputAssociation are child elements of Activity)\n   */\n  private applyDataAssociations(bpmnElement: ModdleElement, element: FlowElementModel): void {\n    // Add dataInputAssociations\n    if (element.dataInputAssociations && element.dataInputAssociations.length > 0) {\n      bpmnElement['dataInputAssociations'] = element.dataInputAssociations.map((assoc) => {\n        const dataInputAssoc = this.moddle.create('bpmn:DataInputAssociation', {\n          id: assoc.id,\n        });\n        // sourceRef is an array of references\n        dataInputAssoc.sourceRef = [{ id: assoc.sourceRef }];\n        return dataInputAssoc;\n      });\n    }\n\n    // Add dataOutputAssociations\n    if (element.dataOutputAssociations && element.dataOutputAssociations.length > 0) {\n      bpmnElement['dataOutputAssociations'] = element.dataOutputAssociations.map((assoc) => {\n        const dataOutputAssoc = this.moddle.create('bpmn:DataOutputAssociation', {\n          id: assoc.id,\n        });\n        // targetRef is a single reference\n        if (assoc.targetRef) {\n          dataOutputAssoc.targetRef = { id: assoc.targetRef };\n        }\n        return dataOutputAssoc;\n      });\n    }\n  }\n\n  /**\n   * Build loop characteristics\n   */\n  private buildLoopCharacteristics(props: LoopCharacteristicsProps): ModdleElement {\n    if (props.loopType === 'standard') {\n      const loop = this.moddle.create('bpmn:StandardLoopCharacteristics', {\n        testBefore: props.testBefore,\n        loopMaximum: props.loopMaximum,\n      });\n      if (props.loopCondition) {\n        loop.loopCondition = this.moddle.create('bpmn:FormalExpression', {\n          body: props.loopCondition,\n        });\n      }\n      return loop;\n    }\n\n    // Multi-instance (default)\n    const multiInstance = this.moddle.create('bpmn:MultiInstanceLoopCharacteristics', {\n      isSequential: props.isSequential ?? false,\n    });\n\n    if (props.loopCardinality) {\n      multiInstance.loopCardinality = this.moddle.create('bpmn:FormalExpression', {\n        body: props.loopCardinality,\n      });\n    }\n    if (props.loopDataInputRef) {\n      multiInstance.loopDataInputRef = { id: props.loopDataInputRef };\n    }\n    if (props.loopDataOutputRef) {\n      multiInstance.loopDataOutputRef = { id: props.loopDataOutputRef };\n    }\n    if (props.completionCondition) {\n      multiInstance.completionCondition = this.moddle.create('bpmn:FormalExpression', {\n        body: props.completionCondition,\n      });\n    }\n\n    return multiInstance;\n  }\n\n  /**\n   * Build an artifact element\n   */\n  private buildArtifact(artifact: ArtifactModel): ModdleElement {\n    const elementType = BPMN_ELEMENT_MAP[artifact.type as keyof typeof BPMN_ELEMENT_MAP];\n    if (!elementType) {\n      throw new Error(`Unknown artifact type: ${artifact.type}`);\n    }\n\n    const props = artifact.properties;\n\n    // For textAnnotation, the text body is a moddle body property — we have\n    // to pass it at create time. Setting `bpmnArtifact['text']` after the\n    // fact does not get picked up by the BPMN moddle serializer.\n    const createAttrs: Record<string, unknown> = {\n      id: artifact.id,\n    };\n    if (artifact.name) {\n      createAttrs.name = artifact.name;\n    }\n    if (artifact.type === 'textAnnotation' && props['text'] !== undefined) {\n      createAttrs.text = props['text'];\n      if (props['textFormat'] !== undefined) {\n        createAttrs.textFormat = props['textFormat'];\n      }\n    }\n    const bpmnArtifact = this.moddle.create(elementType, createAttrs);\n\n    if (artifact.type === 'dataObjectReference' || artifact.type === 'dataObject') {\n      if (props['isCollection'] !== undefined) {\n        bpmnArtifact['isCollection'] = props['isCollection'];\n      }\n      if (props['dataState']) {\n        const state = props['dataState'] as { name?: string };\n        bpmnArtifact['dataState'] = this.moddle.create('bpmn:DataState', {\n          name: state.name,\n        });\n      }\n    }\n\n    if (artifact.type === 'dataStoreReference') {\n      if (props['capacity'] !== undefined) {\n        bpmnArtifact['capacity'] = props['capacity'];\n      }\n      if (props['isUnlimited'] !== undefined) {\n        bpmnArtifact['isUnlimited'] = props['isUnlimited'];\n      }\n    }\n\n    if (artifact.type === 'group') {\n      if (props['categoryValueRef']) {\n        bpmnArtifact['categoryValueRef'] = { id: props['categoryValueRef'] as string };\n      }\n    }\n\n    if (artifact.type === 'association') {\n      if (props['sourceRef']) {\n        bpmnArtifact['sourceRef'] = { id: props['sourceRef'] as string };\n      }\n      if (props['targetRef']) {\n        bpmnArtifact['targetRef'] = { id: props['targetRef'] as string };\n      }\n      if (props['associationDirection']) {\n        bpmnArtifact['associationDirection'] = props['associationDirection'] as string;\n      }\n    }\n\n    return bpmnArtifact;\n  }\n\n  /**\n   * Build the diagram element\n   */\n  private buildDiagram(diagram: DiagramModel): ModdleElement {\n    const bpmnDiagram = this.moddle.create('bpmndi:BPMNDiagram', {\n      id: diagram.id,\n      name: diagram.name,\n    });\n\n    const plane = this.moddle.create('bpmndi:BPMNPlane', {\n      id: diagram.plane.id,\n      bpmnElement: { id: diagram.plane.bpmnElement },\n    });\n\n    const planeElements: ModdleElement[] = [];\n\n    // Add shapes\n    for (const shape of diagram.plane.shapes) {\n      planeElements.push(this.buildShape(shape));\n    }\n\n    // Add edges\n    for (const edge of diagram.plane.edges) {\n      planeElements.push(this.buildEdge(edge));\n    }\n\n    plane.planeElement = planeElements;\n    bpmnDiagram.plane = plane;\n\n    return bpmnDiagram;\n  }\n\n  /**\n   * Build a shape element\n   */\n  private buildShape(shape: ShapeModel): ModdleElement {\n    const bpmnShape = this.moddle.create('bpmndi:BPMNShape', {\n      id: shape.id,\n      bpmnElement: { id: shape.bpmnElement },\n    });\n\n    bpmnShape.bounds = this.moddle.create('dc:Bounds', {\n      x: shape.bounds.x,\n      y: shape.bounds.y,\n      width: shape.bounds.width,\n      height: shape.bounds.height,\n    });\n\n    if (shape.isExpanded !== undefined) {\n      bpmnShape.isExpanded = shape.isExpanded;\n    }\n\n    if (shape.isHorizontal !== undefined) {\n      bpmnShape.isHorizontal = shape.isHorizontal;\n    }\n\n    if (shape.label?.bounds) {\n      bpmnShape.label = this.moddle.create('bpmndi:BPMNLabel', {\n        bounds: this.moddle.create('dc:Bounds', {\n          x: shape.label.bounds.x,\n          y: shape.label.bounds.y,\n          width: shape.label.bounds.width,\n          height: shape.label.bounds.height,\n        }),\n      });\n    }\n\n    return bpmnShape;\n  }\n\n  /**\n   * Build an edge element\n   */\n  private buildEdge(edge: EdgeModel): ModdleElement {\n    const bpmnEdge = this.moddle.create('bpmndi:BPMNEdge', {\n      id: edge.id,\n      bpmnElement: { id: edge.bpmnElement },\n    });\n\n    bpmnEdge.waypoint = edge.waypoints.map((wp) =>\n      this.moddle.create('dc:Point', {\n        x: wp.x,\n        y: wp.y,\n      })\n    );\n\n    if (edge.label?.bounds) {\n      bpmnEdge.label = this.moddle.create('bpmndi:BPMNLabel', {\n        bounds: this.moddle.create('dc:Bounds', {\n          x: edge.label.bounds.x,\n          y: edge.label.bounds.y,\n          width: edge.label.bounds.width,\n          height: edge.label.bounds.height,\n        }),\n      });\n    }\n\n    return bpmnEdge;\n  }\n}\n\n// Property type definitions\ninterface TimerEventDefinitionProps {\n  timeDate?: string;\n  timeDuration?: string;\n  timeCycle?: string;\n}\n\ninterface ConditionalEventDefinitionProps {\n  condition?: {\n    type?: string;\n    language?: string;\n    body?: string;\n  };\n}\n\ninterface LinkEventDefinitionProps {\n  name?: string;\n  source?: string[];\n  target?: string;\n}\n\ninterface ScriptProps {\n  scriptFormat?: string;\n  script?: string;\n  resultVariable?: string;\n}\n\ninterface ConditionExpressionProps {\n  type?: string;\n  language?: string;\n  body?: string;\n}\n\ninterface LoopCharacteristicsProps {\n  loopType?: 'standard' | 'multiInstance';\n  isSequential?: boolean;\n  loopCardinality?: string;\n  loopDataInputRef?: string;\n  loopDataOutputRef?: string;\n  inputDataItem?: string;\n  outputDataItem?: string;\n  completionCondition?: string;\n  loopCondition?: string;\n  loopMaximum?: number;\n  testBefore?: boolean;\n}\n","/**\n * BpmnElkLayout - Main Converter Class\n *\n * Converts ELK-BPMN JSON to:\n * - BPMN 2.0 XML (with diagram interchange)\n * - Layouted ELK-BPMN JSON (with coordinates)\n */\n\nimport type { ElkBpmnGraph, ElkLayoutOptions } from './types';\nimport type { LayoutedGraph } from './types/elk-output';\nimport { ElkLayouter } from './layout';\nimport { ModelBuilder } from './transform';\nimport { BpmnXmlGenerator } from './generators';\n\nexport interface BpmnElkLayoutOptions {\n  /**\n   * ELK layout options to override defaults\n   */\n  elkOptions?: ElkLayoutOptions;\n  /**\n   * Enable layout compaction to reduce unnecessary whitespace\n   * @default true\n   */\n  enableCompaction?: boolean;\n}\n\nexport class BpmnElkLayout {\n  private layouter: ElkLayouter;\n  private modelBuilder: ModelBuilder;\n  private xmlGenerator: BpmnXmlGenerator;\n\n  constructor(options?: BpmnElkLayoutOptions) {\n    this.layouter = new ElkLayouter({\n      elkOptions: options?.elkOptions,\n      enableCompaction: options?.enableCompaction ?? true,\n    });\n    this.modelBuilder = new ModelBuilder();\n    this.xmlGenerator = new BpmnXmlGenerator();\n  }\n\n  /**\n   * Convert ELK-BPMN JSON to BPMN 2.0 XML\n   *\n   * @param input - ELK-BPMN JSON (without coordinates)\n   * @returns BPMN 2.0 XML string with diagram interchange\n   *\n   * @example\n   * ```typescript\n   * const converter = new BpmnElkLayout();\n   * const xml = await converter.to_bpmn(elkBpmnJson);\n   * console.log(xml);\n   * ```\n   */\n  async to_bpmn(input: ElkBpmnGraph): Promise<string> {\n    // Step 1: Run ELK layout to get coordinates\n    const layouted = await this.layouter.layout(input);\n\n    // Step 2: Build intermediate model\n    const model = this.modelBuilder.build(layouted);\n\n    // Step 3: Generate BPMN XML\n    const xml = await this.xmlGenerator.generate(model);\n\n    return xml;\n  }\n\n  /**\n   * Convert ELK-BPMN JSON to layouted JSON with coordinates\n   *\n   * @param input - ELK-BPMN JSON (without coordinates)\n   * @returns ELK-BPMN JSON with x, y coordinates for all nodes and edges\n   *\n   * @example\n   * ```typescript\n   * const converter = new BpmnElkLayout();\n   * const layouted = await converter.to_json(elkBpmnJson);\n   * console.log(layouted.children[0].x, layouted.children[0].y);\n   * ```\n   */\n  async to_json(input: ElkBpmnGraph): Promise<LayoutedGraph> {\n    return this.layouter.layout(input);\n  }\n\n  /**\n   * Create a new instance with different options\n   */\n  static create(options?: BpmnElkLayoutOptions): BpmnElkLayout {\n    return new BpmnElkLayout(options);\n  }\n}\n\n// Re-export types for convenience\nexport type { ElkBpmnGraph, ElkLayoutOptions } from './types';\nexport type { LayoutedGraph } from './types/elk-output';\n","/**\n * Prompt Template Generator for ELK-BPMN JSON\n *\n * Dynamically analyzes test fixtures and schema to generate\n * a comprehensive AI prompt template for ELK-BPMN JSON generation.\n */\n\nimport { readFile, readdir } from 'fs/promises';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n  DEFAULT_SIZES,\n  DEFAULT_ELK_OPTIONS,\n  EVENT_TYPES,\n  TASK_TYPES,\n  GATEWAY_TYPES,\n  SUBPROCESS_TYPES,\n} from './types/bpmn-constants';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PromptGeneratorOptions {\n  /** Path to fixtures directory */\n  fixturesDir?: string;\n  /** Path to ELK-BPMN schema file */\n  schemaPath?: string;\n}\n\ninterface FixtureAnalysis {\n  totalFixtures: number;\n  eventTypes: Set<string>;\n  eventDefinitionTypes: Set<string>;\n  taskTypes: Set<string>;\n  gatewayTypes: Set<string>;\n  subprocessTypes: Set<string>;\n  hasCollaborations: boolean;\n  hasLanes: boolean;\n  hasBoundaryEvents: boolean;\n  hasMessageFlows: boolean;\n  hasConditionExpressions: boolean;\n  hasTimerDefinitions: boolean;\n  hasLoopCharacteristics: boolean;\n  examples: {\n    simpleProcess?: unknown;\n    collaboration?: unknown;\n  };\n}\n\ninterface SchemaInfo {\n  version: string;\n  title: string;\n  eventDefinitionTypes: string[];\n  taskTypes: string[];\n  gatewayTypes: string[];\n  subprocessTypes: string[];\n}\n\n// ============================================================================\n// PromptTemplateGenerator Class\n// ============================================================================\n\nexport class PromptTemplateGenerator {\n  private options: Required<PromptGeneratorOptions>;\n\n  constructor(options: PromptGeneratorOptions = {}) {\n    // Get package root directory\n    // When running from dist/, we need to go up to find test/fixtures\n    const currentDir = dirname(fileURLToPath(import.meta.url));\n\n    // Check if we're in dist/ or src/\n    const isInDist = currentDir.includes('/dist');\n    const packageRoot = isInDist\n      ? join(currentDir, '..', '..')  // dist/bin -> package root\n      : join(currentDir, '..');        // src -> package root\n    const projectRoot = join(packageRoot, '../..');\n\n    this.options = {\n      fixturesDir: options.fixturesDir || join(packageRoot, 'test/fixtures'),\n      schemaPath: options.schemaPath || join(projectRoot, 'elk-bpmn-schema.json'),\n    };\n  }\n\n  /**\n   * Analyze all fixture files to extract patterns and examples\n   */\n  async analyzeFixtures(): Promise<FixtureAnalysis> {\n    const analysis: FixtureAnalysis = {\n      totalFixtures: 0,\n      eventTypes: new Set(),\n      eventDefinitionTypes: new Set(),\n      taskTypes: new Set(),\n      gatewayTypes: new Set(),\n      subprocessTypes: new Set(),\n      hasCollaborations: false,\n      hasLanes: false,\n      hasBoundaryEvents: false,\n      hasMessageFlows: false,\n      hasConditionExpressions: false,\n      hasTimerDefinitions: false,\n      hasLoopCharacteristics: false,\n      examples: {},\n    };\n\n    const files = await readdir(this.options.fixturesDir);\n    const jsonFiles = files.filter((f) => f.endsWith('.json'));\n\n    for (const file of jsonFiles) {\n      const content = await readFile(join(this.options.fixturesDir, file), 'utf-8');\n      const fixture = JSON.parse(content);\n      analysis.totalFixtures++;\n\n      this.analyzeNode(fixture, analysis);\n\n      // Extract example fixtures\n      if (file.includes('simple-process') && !analysis.examples.simpleProcess) {\n        analysis.examples.simpleProcess = fixture;\n      }\n      if (file.includes('collaboration-simple') && !analysis.examples.collaboration) {\n        analysis.examples.collaboration = fixture;\n      }\n    }\n\n    return analysis;\n  }\n\n  /**\n   * Recursively analyze a node and its children\n   */\n  private analyzeNode(node: Record<string, unknown>, analysis: FixtureAnalysis): void {\n    if (!node || typeof node !== 'object') return;\n\n    const bpmn = node['bpmn'] as Record<string, unknown> | undefined;\n    if (bpmn && bpmn['type']) {\n      const type = bpmn['type'] as string;\n\n      // Categorize types\n      if (EVENT_TYPES.includes(type as (typeof EVENT_TYPES)[number])) {\n        analysis.eventTypes.add(type);\n        if (bpmn['eventDefinitionType']) {\n          analysis.eventDefinitionTypes.add(bpmn['eventDefinitionType'] as string);\n        }\n      } else if (TASK_TYPES.includes(type as (typeof TASK_TYPES)[number])) {\n        analysis.taskTypes.add(type);\n      } else if (GATEWAY_TYPES.includes(type as (typeof GATEWAY_TYPES)[number])) {\n        analysis.gatewayTypes.add(type);\n      } else if (SUBPROCESS_TYPES.includes(type as (typeof SUBPROCESS_TYPES)[number])) {\n        analysis.subprocessTypes.add(type);\n      } else if (type === 'collaboration') {\n        analysis.hasCollaborations = true;\n      } else if (type === 'lane') {\n        analysis.hasLanes = true;\n      } else if (type === 'messageFlow') {\n        analysis.hasMessageFlows = true;\n      }\n\n      // Check for specific features\n      if (bpmn['timerEventDefinition']) {\n        analysis.hasTimerDefinitions = true;\n      }\n      if (bpmn['loopCharacteristics']) {\n        analysis.hasLoopCharacteristics = true;\n      }\n      if (bpmn['conditionExpression']) {\n        analysis.hasConditionExpressions = true;\n      }\n    }\n\n    // Check for boundary events\n    const boundaryEvents = node['boundaryEvents'] as unknown[] | undefined;\n    if (Array.isArray(boundaryEvents) && boundaryEvents.length > 0) {\n      analysis.hasBoundaryEvents = true;\n      for (const be of boundaryEvents) {\n        this.analyzeNode(be as Record<string, unknown>, analysis);\n      }\n    }\n\n    // Recurse into children\n    const children = node['children'] as unknown[] | undefined;\n    if (Array.isArray(children)) {\n      for (const child of children) {\n        this.analyzeNode(child as Record<string, unknown>, analysis);\n      }\n    }\n\n    // Recurse into edges\n    const edges = node['edges'] as unknown[] | undefined;\n    if (Array.isArray(edges)) {\n      for (const edge of edges) {\n        this.analyzeNode(edge as Record<string, unknown>, analysis);\n        const edgeBpmn = (edge as Record<string, unknown>)['bpmn'] as Record<string, unknown> | undefined;\n        if (edgeBpmn?.['conditionExpression']) {\n          analysis.hasConditionExpressions = true;\n        }\n      }\n    }\n  }\n\n  /**\n   * Load and parse the schema file\n   */\n  async loadSchema(): Promise<SchemaInfo> {\n    const content = await readFile(this.options.schemaPath, 'utf-8');\n    const schema = JSON.parse(content);\n\n    return {\n      version: schema.version || '2.0.0',\n      title: schema.title || 'ELK-BPMN Extended Schema',\n      eventDefinitionTypes: schema.definitions?.bpmnEvent?.properties?.eventDefinitionType?.enum || [],\n      taskTypes: schema.definitions?.bpmnTask?.properties?.type?.enum || [],\n      gatewayTypes: schema.definitions?.bpmnGateway?.properties?.type?.enum || [],\n      subprocessTypes: schema.definitions?.bpmnSubProcess?.properties?.type?.enum || [],\n    };\n  }\n\n  /**\n   * Generate the complete prompt template\n   */\n  async generate(): Promise<string> {\n    const [analysis, schema] = await Promise.all([this.analyzeFixtures(), this.loadSchema()]);\n\n    return this.buildTemplate(analysis, schema);\n  }\n\n  /**\n   * Build the final template string\n   * Output is a clean system prompt that can be directly copied to AI\n   */\n  private buildTemplate(analysis: FixtureAnalysis, schema: SchemaInfo): string {\n    const sections: string[] = [];\n\n    // System Prompt intro\n    sections.push(this.generateSystemPrompt());\n\n    // Output Format\n    sections.push(this.generateOutputFormat());\n\n    // Standard Dimensions\n    sections.push(this.generateDimensions());\n\n    // Structure Hierarchy\n    sections.push(this.generateStructure());\n\n    // Event Type Guide\n    sections.push(this.generateEventGuide(schema));\n\n    // Task Type Guide\n    sections.push(this.generateTaskGuide(schema));\n\n    // Gateway Rules\n    sections.push(this.generateGatewayRules());\n\n    // ID Naming Conventions\n    sections.push(this.generateNamingConventions());\n\n    // Important Rules\n    sections.push(this.generateImportantRules());\n\n    // User Prompt Template\n    sections.push(this.generateUserPromptTemplate());\n\n    // Example\n    sections.push(this.generateExample(analysis));\n\n    // Self-Check List\n    sections.push(this.generateSelfCheckList());\n\n    // Common Errors\n    sections.push(this.generateCommonErrors());\n\n    return sections.join('\\n\\n');\n  }\n\n  private generateSystemPrompt(): string {\n    return `You are a professional BPMN 2.0 process modeling expert. Your task is to convert user's business process descriptions into ELK-BPMN extended format JSON.\n\nCore capabilities:\n1. Understand complex business processes and convert to standard BPMN elements\n2. Correctly use various events, tasks, gateways, and subprocesses\n3. Handle multi-participant collaborations and message exchanges\n4. Set up conditional branches and exception handling`;\n  }\n\n  private generateOutputFormat(): string {\n    return `Output Format Requirements:\n1. Output must be valid JSON\n2. Follow ELK-BPMN Extended Schema v2.0\n3. Each node must contain id, bpmn, width, height\n4. Edges must contain id, sources, targets, bpmn\n5. Conditional branches must contain conditionExpression`;\n  }\n\n  private generateDimensions(): string {\n    const items = [\n      `- All events: ${DEFAULT_SIZES.EVENT.width}x${DEFAULT_SIZES.EVENT.height}`,\n      `- All tasks: ${DEFAULT_SIZES.TASK.width}x${DEFAULT_SIZES.TASK.height} (can be 120-150 wide for long names)`,\n      `- All gateways: ${DEFAULT_SIZES.GATEWAY.width}x${DEFAULT_SIZES.GATEWAY.height}`,\n      `- Collapsed subprocess: ${DEFAULT_SIZES.SUBPROCESS_COLLAPSED.width}x${DEFAULT_SIZES.SUBPROCESS_COLLAPSED.height}`,\n      `- Expanded subprocess: minimum ${DEFAULT_SIZES.SUBPROCESS_EXPANDED_MIN.width}x${DEFAULT_SIZES.SUBPROCESS_EXPANDED_MIN.height}`,\n      `- Data object: ${DEFAULT_SIZES.DATA_OBJECT.width}x${DEFAULT_SIZES.DATA_OBJECT.height}`,\n      `- Data store: ${DEFAULT_SIZES.DATA_STORE.width}x${DEFAULT_SIZES.DATA_STORE.height}`,\n    ];\n\n    return `Standard Dimensions (Required):\\n${items.join('\\n')}`;\n  }\n\n  private generateStructure(): string {\n    return `Structure Hierarchy:\n\nMulti-Pool Collaboration Structure:\ndefinitions\n└── collaboration\n    ├── participant (Pool 1)\n    │   ├── lane (swimlane)\n    │   │   └── flowNode\n    │   └── edges[] (sequence flows)\n    ├── participant (Pool 2)\n    │   └── ...\n    └── edges[] (message flows, cross-Pool)\n\nSingle Process Structure:\ndefinitions\n└── process\n    ├── flowNode\n    └── edges[] (sequence flows)`;\n  }\n\n  private generateEventGuide(schema: SchemaInfo): string {\n    const rows = [\n      '| Process natural start | startEvent | none |',\n      '| Start on message received | startEvent | message |',\n      '| Start on timer | startEvent | timer |',\n      '| Start on condition | startEvent | conditional |',\n      '| Start on signal | startEvent | signal |',\n      '| Normal process end | endEvent | none |',\n      '| End with message | endEvent | message |',\n      '| End with error | endEvent | error |',\n      '| Terminate all branches | endEvent | terminate |',\n      '| Cancel transaction | endEvent | cancel |',\n      '| Trigger escalation | endEvent | escalation |',\n      '| Trigger compensation | endEvent | compensation |',\n      '| Wait for message | intermediateCatchEvent | message |',\n      '| Wait for time | intermediateCatchEvent | timer |',\n      '| Wait for signal | intermediateCatchEvent | signal |',\n      '| Wait for condition | intermediateCatchEvent | conditional |',\n      '| Link catch | intermediateCatchEvent | link |',\n      '| Send message | intermediateThrowEvent | message |',\n      '| Send signal | intermediateThrowEvent | signal |',\n      '| Link throw | intermediateThrowEvent | link |',\n      '| Activity timeout | boundaryEvent | timer |',\n      '| Activity error | boundaryEvent | error |',\n      '| Activity message | boundaryEvent | message |',\n      '| Activity escalation | boundaryEvent | escalation |',\n    ];\n\n    return `Event Type Selection Guide:\n\n| Scenario | Event Type | eventDefinitionType |\n|-----|---------|-------------------|\n${rows.join('\\n')}`;\n  }\n\n  private generateTaskGuide(schema: SchemaInfo): string {\n    const rows = [\n      '| Requires human action | userTask |',\n      '| Call API/service | serviceTask |',\n      '| Execute script | scriptTask |',\n      '| Send message/notification | sendTask |',\n      '| Wait to receive message | receiveTask |',\n      '| Manual operation outside system | manualTask |',\n      '| Call business rule/DMN | businessRuleTask |',\n      '| Generic task | task |',\n    ];\n\n    return `Task Type Selection Guide:\n\n| Scenario | Task Type |\n|-----|---------|\n${rows.join('\\n')}`;\n  }\n\n  private generateGatewayRules(): string {\n    return `Gateway Usage Rules:\n\n1. Exclusive Gateway (exclusiveGateway)\n   - Must specify default attribute pointing to default outgoing flow\n   - Other outgoing flows must have conditionExpression\n   - Takes only one path (XOR semantics)\n\n2. Parallel Gateway (parallelGateway)\n   - Use for both forking and joining\n   - No conditions needed\n   - Takes all paths (AND semantics)\n\n3. Inclusive Gateway (inclusiveGateway)\n   - Can take one or more paths\n   - Requires condition expressions\n   - Takes at least one path (OR semantics)\n\n4. Event-Based Gateway (eventBasedGateway)\n   - Followed by multiple intermediate catch events\n   - Whichever event occurs first determines the path\n   - Commonly used for message waiting or timeout handling\n\n5. Complex Gateway (complexGateway)\n   - Custom activation condition\n   - Uses activationCondition expression`;\n  }\n\n  private generateNamingConventions(): string {\n    const items = [\n      '- Pool: pool_[department/role]',\n      '- Lane: lane_[role]',\n      '- Start event: start_[description]',\n      '- End event: end_[description]',\n      '- Intermediate catch event: catch_[description]',\n      '- Intermediate throw event: throw_[description]',\n      '- Boundary event: boundary_[trigger_type]_[description]',\n      '- Task: task_[action]',\n      '- Gateway: gateway_[condition]',\n      '- Subprocess: subprocess_[description]',\n      '- Sequence flow: flow_[number] or flow_[description]',\n      '- Message flow: msgflow_[description]',\n      '- Message definition: msg_[description]',\n      '- Signal definition: signal_[description]',\n      '- Error definition: error_[description]',\n    ];\n\n    return `ID Naming Conventions:\\n${items.join('\\n')}`;\n  }\n\n  private generateImportantRules(): string {\n    return `Important Rules:\n\n1. Sequence Flow vs Message Flow\n   - Cross-lane connections (within same Pool) are sequence flows, in participant.edges\n   - Cross-Pool connections are message flows, must be in collaboration.edges\n   - Message flows can only connect elements in different Pools\n\n2. Process Reference\n   - Each Pool must specify processRef\n   - processRef value should uniquely identify the participant's process\n\n3. Condition Expressions\n   - Conditional branches after exclusive/inclusive gateways need conditionExpression (except default)\n   - Conditions use body field to store expression content\n\n4. Event Constraints\n   - Start events have no incoming edges, end events have no outgoing edges\n   - Boundary events defined in boundaryEvents array with attachedToRef\n\n5. Interrupting vs Non-Interrupting\n   - Boundary events are interrupting by default (isInterrupting: true)\n   - Non-interrupting boundary events set isInterrupting: false\n\n6. Timer Configuration\n   - Use timerEventDefinition object\n   - Supports timeDate (fixed time), timeDuration (duration), timeCycle (cycle)\n\n7. Message Reference\n   - Message events should set messageRef to reference global message definition\n   - Global messages defined in root node's messages array`;\n  }\n\n  private generateUserPromptTemplate(): string {\n    return `User Input Format Template:\n\nPlease generate ELK-BPMN format JSON based on the following business process description:\n\n【Process Name】\n{process name}\n\n【Departments/Roles】\n- {Department1}: {Role1}, {Role2}\n- {Department2}: {Role3}\n...\n\n【Process Steps】\n1. {step description}\n2. {step description}\n...\n\n【Conditional Branches】(if any)\n- {condition1}: {handling}\n- {condition2}: {handling}\n\n【Exception Handling】(if any)\n- {exception scenario}: {handling}\n\n【Cross-Department Interactions】(if any)\n- {DepartmentA} → {DepartmentB}: {interaction content}\n\n【Timer/Timeout Requirements】(if any)\n- {timer trigger description}\n- {timeout handling description}\n\nGeneration Requirements:\n1. All participating departments as separate Pools\n2. Roles within each department as Lanes\n3. Correctly set sequence flows and message flows\n4. Include condition expressions\n5. Properly handle exceptions and timeouts`;\n  }\n\n  private generateExample(analysis: FixtureAnalysis): string {\n    const simpleProcess = {\n      id: 'definitions_example',\n      layoutOptions: DEFAULT_ELK_OPTIONS,\n      children: [\n        {\n          id: 'process_example',\n          bpmn: { type: 'process', name: 'Example Process', isExecutable: true },\n          children: [\n            {\n              id: 'start_1',\n              width: 36,\n              height: 36,\n              bpmn: { type: 'startEvent', eventDefinitionType: 'none', name: 'Start' },\n              labels: [{ text: 'Start' }],\n            },\n            {\n              id: 'task_1',\n              width: 100,\n              height: 80,\n              bpmn: { type: 'userTask', name: 'Approval' },\n              labels: [{ text: 'Approval' }],\n            },\n            {\n              id: 'gateway_1',\n              width: 50,\n              height: 50,\n              bpmn: { type: 'exclusiveGateway', name: 'Approved?', default: 'flow_reject' },\n              labels: [{ text: 'Approved?' }],\n            },\n            {\n              id: 'task_2',\n              width: 100,\n              height: 80,\n              bpmn: { type: 'serviceTask', name: 'Execute' },\n              labels: [{ text: 'Execute' }],\n            },\n            {\n              id: 'end_1',\n              width: 36,\n              height: 36,\n              bpmn: { type: 'endEvent', eventDefinitionType: 'none', name: 'Done' },\n              labels: [{ text: 'Done' }],\n            },\n            {\n              id: 'end_2',\n              width: 36,\n              height: 36,\n              bpmn: { type: 'endEvent', eventDefinitionType: 'none', name: 'Rejected' },\n              labels: [{ text: 'Rejected' }],\n            },\n          ],\n          edges: [\n            { id: 'flow_1', sources: ['start_1'], targets: ['task_1'], bpmn: { type: 'sequenceFlow' } },\n            { id: 'flow_2', sources: ['task_1'], targets: ['gateway_1'], bpmn: { type: 'sequenceFlow' } },\n            {\n              id: 'flow_approve',\n              sources: ['gateway_1'],\n              targets: ['task_2'],\n              bpmn: {\n                type: 'sequenceFlow',\n                name: 'Approved',\n                conditionExpression: { type: 'tFormalExpression', body: '${approved}' },\n              },\n              labels: [{ text: 'Approved' }],\n            },\n            {\n              id: 'flow_reject',\n              sources: ['gateway_1'],\n              targets: ['end_2'],\n              bpmn: { type: 'sequenceFlow', name: 'Rejected', isDefault: true },\n              labels: [{ text: 'Rejected' }],\n            },\n            { id: 'flow_3', sources: ['task_2'], targets: ['end_1'], bpmn: { type: 'sequenceFlow' } },\n          ],\n        },\n      ],\n    };\n\n    return `Simple Example:\\n\\n\\`\\`\\`json\\n${JSON.stringify(simpleProcess, null, 2)}\\n\\`\\`\\``;\n  }\n\n  private generateSelfCheckList(): string {\n    const items = [\n      '1. Each Pool has unique processRef',\n      '2. Message flows only in collaboration.edges',\n      '3. Sequence flows only in participant.edges or process.edges',\n      '4. All IDs are unique and follow naming conventions',\n      '5. IDs in sources and targets exist in children',\n      '6. Exclusive/inclusive gateways have default outgoing flow',\n      '7. Non-default outgoing flows have conditionExpression',\n      '8. Start events have no incoming edges, end events have no outgoing edges',\n      '9. All nodes have width and height',\n      '10. Boundary events have attachedToRef',\n      '11. Timer events have timerEventDefinition',\n      '12. Message events have messageRef',\n    ];\n\n    return `Self-Check List (verify after generation):\\n${items.join('\\n')}`;\n  }\n\n  private generateCommonErrors(): string {\n    return `Common Errors:\n\nError 1: Sequence flow in collaboration level\n\"collaboration\": { \"edges\": [{ \"bpmn\": { \"type\": \"sequenceFlow\" } }] }\nCorrect: Sequence flows should be in participant.edges\n\nError 2: Message flow in participant level\n\"participant\": { \"edges\": [{ \"bpmn\": { \"type\": \"messageFlow\" } }] }\nCorrect: Message flows should be in collaboration.edges\n\nError 3: Missing gateway default outgoing flow\n{ \"bpmn\": { \"type\": \"exclusiveGateway\" } }\nCorrect: { \"bpmn\": { \"type\": \"exclusiveGateway\", \"default\": \"flow_default\" } }\n\nError 4: Boundary event missing attachedToRef\n\"boundaryEvents\": [{ \"id\": \"boundary_timer\", \"bpmn\": {...} }]\nCorrect: Must set \"attachedToRef\": \"task_1\"`;\n  }\n}\n\n// ============================================================================\n// Factory function for convenience\n// ============================================================================\n\nexport async function generatePromptTemplate(options?: PromptGeneratorOptions): Promise<string> {\n  const generator = new PromptTemplateGenerator(options);\n  return generator.generate();\n}\n"],"mappings":"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","names":["BranchDestType","buildNodeMap","ARTIFACT_TYPES","result","ARTIFACT_TYPES","isContainer","DEFAULT_OPTIONS","DEFAULT_OPTIONS","DEFAULT_ELK_OPTIONS","elkNode","isContainer","segmentLength","midX","midY","process","process"]}