MCPcopy Create free account
hub / github.com/codag-megalith/codag-visualizer / computeWorkflows

Method computeWorkflows

frontend/src/cache.ts:940–1312  ·  view source on GitHub ↗

* Compute workflows using LLM-assigned workflow names per file, * with hub detection for end-to-end shared service inclusion. * Falls back to connectivity-based grouping if no assignments exist.

(nodes: WorkflowNode[], edges: WorkflowEdge[])

Source from the content-addressed store, hash-verified

938 * Falls back to connectivity-based grouping if no assignments exist.
939 */
940 private computeWorkflows(nodes: WorkflowNode[], edges: WorkflowEdge[]): WorkflowMetadata[] {
941 // Phase 1: Group nodes by stored workflow name (per-node from LLM analysis)
942 const workflowGroups = new Map<string, { id: string; name: string; description?: string; nodeIds: string[] }>();
943 let hasAnyAssignment = false;
944
945 for (const node of nodes) {
946 const file = node.source?.file;
947 if (!file) continue;
948 const normalizedFile = this.toRelativePath(file);
949 const cached = this.files[normalizedFile];
950 const wfAssignment = cached?.nodeWorkflows?.[node.id];
951 if (wfAssignment) {
952 hasAnyAssignment = true;
953 const key = wfAssignment.name;
954 if (!workflowGroups.has(key)) {
955 workflowGroups.set(key, {
956 id: wfAssignment.id || `workflow_${workflowGroups.size}`,
957 name: key,
958 description: this.workflows[wfAssignment.id || '']?.description,
959 nodeIds: []
960 });
961 }
962 workflowGroups.get(key)!.nodeIds.push(node.id);
963 }
964 }
965
966 // Fallback: if no files have workflow assignments, use connectivity-based grouping
967 if (!hasAnyAssignment) {
968 return this.computeWorkflowsByConnectivity(nodes, edges);
969 }
970
971 // Phase 2: Iteratively assign orphan nodes via edges until no more changes
972 // This handles chains like A→B→C where only A is initially assigned
973 const assignedNodes = new Set(
974 [...workflowGroups.values()].flatMap(g => g.nodeIds)
975 );
976
977 let changed = true;
978 let iterations = 0;
979 const maxIterations = 20; // Prevent infinite loops
980
981 while (changed && iterations < maxIterations) {
982 changed = false;
983 iterations++;
984
985 for (const node of nodes) {
986 if (assignedNodes.has(node.id)) continue;
987
988 // Find any edge connecting this node to an assigned node
989 const connectedEdge = edges.find(
990 e => (e.source === node.id && assignedNodes.has(e.target)) ||
991 (e.target === node.id && assignedNodes.has(e.source))
992 );
993
994 if (connectedEdge) {
995 const assignedId = connectedEdge.source === node.id
996 ? connectedEdge.target : connectedEdge.source;
997 for (const wf of workflowGroups.values()) {

Callers 1

getMergedGraphMethod · 0.95

Calls 9

toRelativePathMethod · 0.95
isHttpEdgeFunction · 0.85
setMethod · 0.80
findMethod · 0.80
hasMethod · 0.45
getMethod · 0.45
addMethod · 0.45
updateMethod · 0.45

Tested by

no test coverage detected