@task-mcp/shared 1.0.23 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/dist/algorithms/critical-path.d.ts +47 -0
  2. package/dist/algorithms/critical-path.d.ts.map +1 -0
  3. package/dist/algorithms/critical-path.js +340 -0
  4. package/dist/algorithms/critical-path.js.map +1 -0
  5. package/dist/algorithms/critical-path.test.d.ts +2 -0
  6. package/dist/algorithms/critical-path.test.d.ts.map +1 -0
  7. package/dist/algorithms/critical-path.test.js +184 -0
  8. package/dist/algorithms/critical-path.test.js.map +1 -0
  9. package/dist/algorithms/dependency-integrity.d.ts +81 -0
  10. package/dist/algorithms/dependency-integrity.d.ts.map +1 -0
  11. package/dist/algorithms/dependency-integrity.js +209 -0
  12. package/dist/algorithms/dependency-integrity.js.map +1 -0
  13. package/dist/algorithms/dependency-integrity.test.d.ts +2 -0
  14. package/dist/algorithms/dependency-integrity.test.d.ts.map +1 -0
  15. package/dist/algorithms/dependency-integrity.test.js +296 -0
  16. package/dist/algorithms/dependency-integrity.test.js.map +1 -0
  17. package/dist/algorithms/index.d.ts +5 -0
  18. package/dist/algorithms/index.d.ts.map +1 -0
  19. package/dist/algorithms/index.js +5 -0
  20. package/dist/algorithms/index.js.map +1 -0
  21. package/dist/algorithms/tech-analysis.d.ts +106 -0
  22. package/dist/algorithms/tech-analysis.d.ts.map +1 -0
  23. package/dist/algorithms/tech-analysis.js +351 -0
  24. package/dist/algorithms/tech-analysis.js.map +1 -0
  25. package/dist/algorithms/tech-analysis.test.d.ts +2 -0
  26. package/dist/algorithms/tech-analysis.test.d.ts.map +1 -0
  27. package/dist/algorithms/tech-analysis.test.js +330 -0
  28. package/dist/algorithms/tech-analysis.test.js.map +1 -0
  29. package/dist/algorithms/topological-sort.d.ts +58 -0
  30. package/dist/algorithms/topological-sort.d.ts.map +1 -0
  31. package/dist/algorithms/topological-sort.js +201 -0
  32. package/dist/algorithms/topological-sort.js.map +1 -0
  33. package/dist/algorithms/topological-sort.test.d.ts +2 -0
  34. package/dist/algorithms/topological-sort.test.d.ts.map +1 -0
  35. package/dist/algorithms/topological-sort.test.js +154 -0
  36. package/dist/algorithms/topological-sort.test.js.map +1 -0
  37. package/dist/index.d.ts +4 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +7 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/schemas/inbox.d.ts +55 -0
  42. package/dist/schemas/inbox.d.ts.map +1 -0
  43. package/dist/schemas/inbox.js +25 -0
  44. package/dist/schemas/inbox.js.map +1 -0
  45. package/dist/schemas/index.d.ts +7 -0
  46. package/dist/schemas/index.d.ts.map +1 -0
  47. package/dist/schemas/index.js +17 -0
  48. package/dist/schemas/index.js.map +1 -0
  49. package/dist/schemas/llm-guide.d.ts +147 -0
  50. package/dist/schemas/llm-guide.d.ts.map +1 -0
  51. package/dist/schemas/llm-guide.js +72 -0
  52. package/dist/schemas/llm-guide.js.map +1 -0
  53. package/dist/schemas/project.d.ts +177 -0
  54. package/dist/schemas/project.d.ts.map +1 -0
  55. package/dist/schemas/project.js +56 -0
  56. package/dist/schemas/project.js.map +1 -0
  57. package/dist/schemas/response-format.d.ts +148 -0
  58. package/dist/schemas/response-format.d.ts.map +1 -0
  59. package/dist/schemas/response-format.js +18 -0
  60. package/dist/schemas/response-format.js.map +1 -0
  61. package/dist/schemas/response-schema.d.ts +307 -0
  62. package/dist/schemas/response-schema.d.ts.map +1 -0
  63. package/dist/schemas/response-schema.js +78 -0
  64. package/dist/schemas/response-schema.js.map +1 -0
  65. package/dist/schemas/response-schema.test.d.ts +2 -0
  66. package/dist/schemas/response-schema.test.d.ts.map +1 -0
  67. package/dist/schemas/response-schema.test.js +256 -0
  68. package/dist/schemas/response-schema.test.js.map +1 -0
  69. package/dist/schemas/state.d.ts +17 -0
  70. package/dist/schemas/state.d.ts.map +1 -0
  71. package/dist/schemas/state.js +17 -0
  72. package/dist/schemas/state.js.map +1 -0
  73. package/dist/schemas/task.d.ts +881 -0
  74. package/dist/schemas/task.d.ts.map +1 -0
  75. package/dist/schemas/task.js +177 -0
  76. package/dist/schemas/task.js.map +1 -0
  77. package/dist/schemas/view.d.ts +143 -0
  78. package/dist/schemas/view.d.ts.map +1 -0
  79. package/dist/schemas/view.js +48 -0
  80. package/dist/schemas/view.js.map +1 -0
  81. package/dist/utils/dashboard-renderer.d.ts +93 -0
  82. package/dist/utils/dashboard-renderer.d.ts.map +1 -0
  83. package/dist/utils/dashboard-renderer.js +416 -0
  84. package/dist/utils/dashboard-renderer.js.map +1 -0
  85. package/dist/utils/dashboard-renderer.test.d.ts +2 -0
  86. package/dist/utils/dashboard-renderer.test.d.ts.map +1 -0
  87. package/dist/utils/dashboard-renderer.test.js +772 -0
  88. package/dist/utils/dashboard-renderer.test.js.map +1 -0
  89. package/dist/utils/date.d.ts +94 -0
  90. package/dist/utils/date.d.ts.map +1 -0
  91. package/dist/utils/date.js +323 -0
  92. package/dist/utils/date.js.map +1 -0
  93. package/dist/utils/date.test.d.ts +2 -0
  94. package/dist/utils/date.test.d.ts.map +1 -0
  95. package/dist/utils/date.test.js +276 -0
  96. package/dist/utils/date.test.js.map +1 -0
  97. package/dist/utils/hierarchy.d.ts +102 -0
  98. package/dist/utils/hierarchy.d.ts.map +1 -0
  99. package/dist/utils/hierarchy.js +236 -0
  100. package/dist/utils/hierarchy.js.map +1 -0
  101. package/dist/utils/hierarchy.test.d.ts +2 -0
  102. package/dist/utils/hierarchy.test.d.ts.map +1 -0
  103. package/dist/utils/hierarchy.test.js +423 -0
  104. package/dist/utils/hierarchy.test.js.map +1 -0
  105. package/dist/utils/id.d.ts +60 -0
  106. package/dist/utils/id.d.ts.map +1 -0
  107. package/dist/utils/id.js +118 -0
  108. package/dist/utils/id.js.map +1 -0
  109. package/dist/utils/id.test.d.ts +2 -0
  110. package/dist/utils/id.test.d.ts.map +1 -0
  111. package/dist/utils/id.test.js +193 -0
  112. package/dist/utils/id.test.js.map +1 -0
  113. package/dist/utils/index.d.ts +12 -0
  114. package/dist/utils/index.d.ts.map +1 -0
  115. package/dist/utils/index.js +34 -0
  116. package/dist/utils/index.js.map +1 -0
  117. package/dist/utils/natural-language.d.ts +111 -0
  118. package/dist/utils/natural-language.d.ts.map +1 -0
  119. package/dist/utils/natural-language.js +297 -0
  120. package/dist/utils/natural-language.js.map +1 -0
  121. package/dist/utils/natural-language.test.d.ts +2 -0
  122. package/dist/utils/natural-language.test.d.ts.map +1 -0
  123. package/dist/utils/natural-language.test.js +197 -0
  124. package/dist/utils/natural-language.test.js.map +1 -0
  125. package/dist/utils/priority-queue.d.ts +17 -0
  126. package/dist/utils/priority-queue.d.ts.map +1 -0
  127. package/dist/utils/priority-queue.js +62 -0
  128. package/dist/utils/priority-queue.js.map +1 -0
  129. package/dist/utils/priority-queue.test.d.ts +2 -0
  130. package/dist/utils/priority-queue.test.d.ts.map +1 -0
  131. package/dist/utils/priority-queue.test.js +82 -0
  132. package/dist/utils/priority-queue.test.js.map +1 -0
  133. package/dist/utils/projection.d.ts +65 -0
  134. package/dist/utils/projection.d.ts.map +1 -0
  135. package/dist/utils/projection.js +180 -0
  136. package/dist/utils/projection.js.map +1 -0
  137. package/dist/utils/projection.test.d.ts +2 -0
  138. package/dist/utils/projection.test.d.ts.map +1 -0
  139. package/dist/utils/projection.test.js +341 -0
  140. package/dist/utils/projection.test.js.map +1 -0
  141. package/dist/utils/terminal-ui.d.ts +208 -0
  142. package/dist/utils/terminal-ui.d.ts.map +1 -0
  143. package/dist/utils/terminal-ui.js +614 -0
  144. package/dist/utils/terminal-ui.js.map +1 -0
  145. package/dist/utils/terminal-ui.test.d.ts +2 -0
  146. package/dist/utils/terminal-ui.test.d.ts.map +1 -0
  147. package/dist/utils/terminal-ui.test.js +683 -0
  148. package/dist/utils/terminal-ui.test.js.map +1 -0
  149. package/dist/utils/workspace.d.ts +102 -0
  150. package/dist/utils/workspace.d.ts.map +1 -0
  151. package/dist/utils/workspace.js +183 -0
  152. package/dist/utils/workspace.js.map +1 -0
  153. package/dist/utils/workspace.test.d.ts +2 -0
  154. package/dist/utils/workspace.test.d.ts.map +1 -0
  155. package/dist/utils/workspace.test.js +97 -0
  156. package/dist/utils/workspace.test.js.map +1 -0
  157. package/package.json +5 -1
  158. package/src/algorithms/critical-path.test.ts +227 -0
  159. package/src/algorithms/dependency-integrity.test.ts +335 -0
  160. package/src/algorithms/tech-analysis.test.ts +405 -0
  161. package/src/algorithms/topological-sort.test.ts +182 -0
  162. package/src/schemas/response-schema.test.ts +314 -0
  163. package/src/utils/dashboard-renderer.test.ts +976 -0
  164. package/src/utils/date.test.ts +329 -0
  165. package/src/utils/hierarchy.test.ts +488 -0
  166. package/src/utils/id.test.ts +235 -0
  167. package/src/utils/natural-language.test.ts +234 -0
  168. package/src/utils/priority-queue.test.ts +103 -0
  169. package/src/utils/projection.test.ts +430 -0
  170. package/src/utils/terminal-ui.test.ts +831 -0
  171. package/src/utils/workspace.test.ts +125 -0
@@ -0,0 +1,47 @@
1
+ import type { Task } from "../schemas/task.js";
2
+ /**
3
+ * Task with computed CPM (Critical Path Method) values
4
+ */
5
+ export interface CPMTask extends Task {
6
+ earliestStart: number;
7
+ earliestFinish: number;
8
+ latestStart: number;
9
+ latestFinish: number;
10
+ slack: number;
11
+ isCritical: boolean;
12
+ dependentCount: number;
13
+ }
14
+ /**
15
+ * Result of critical path analysis
16
+ */
17
+ export interface CPMResult {
18
+ tasks: CPMTask[];
19
+ criticalPath: CPMTask[];
20
+ projectDuration: number;
21
+ bottlenecks: CPMTask[];
22
+ }
23
+ /**
24
+ * Perform Critical Path Method analysis
25
+ *
26
+ * CPM calculates:
27
+ * - Earliest Start (ES): Earliest a task can start
28
+ * - Earliest Finish (EF): ES + duration
29
+ * - Latest Finish (LF): Latest a task can finish without delaying project
30
+ * - Latest Start (LS): LF - duration
31
+ * - Slack: LS - ES (or LF - EF)
32
+ * - Critical Path: Tasks with slack = 0
33
+ */
34
+ export declare function criticalPathAnalysis(tasks: Task[]): CPMResult;
35
+ /**
36
+ * Find tasks that can be executed in parallel (no dependencies between them)
37
+ * Optimized to O(n + e) where n = number of tasks, e = number of dependencies
38
+ */
39
+ export declare function findParallelTasks(tasks: Task[]): Task[][];
40
+ /**
41
+ * Suggest the next best task to work on
42
+ */
43
+ export declare function suggestNextTask(tasks: Task[], options?: {
44
+ contexts?: string[];
45
+ maxMinutes?: number;
46
+ }): Task | null;
47
+ //# sourceMappingURL=critical-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critical-path.d.ts","sourceRoot":"","sources":["../../src/algorithms/critical-path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAG/C;;GAEG;AACH,MAAM,WAAW,OAAQ,SAAQ,IAAI;IAEnC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,YAAY,EAAE,OAAO,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,OAAO,EAAE,CAAC;CACxB;AA6ND;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,CAiD7D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,CAmEzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,GACL,IAAI,GAAG,IAAI,CAmDb"}
@@ -0,0 +1,340 @@
1
+ import { topologicalSort, priorityToNumber } from "./topological-sort.js";
2
+ /** Default task duration if no estimate provided */
3
+ const DEFAULT_DURATION = 30;
4
+ /**
5
+ * Get task duration with fallback to default
6
+ */
7
+ function getTaskDuration(task) {
8
+ return task.estimate?.expected ?? DEFAULT_DURATION;
9
+ }
10
+ /**
11
+ * Get blocked_by dependencies for a task
12
+ */
13
+ function getBlockedByDeps(task) {
14
+ return (task.dependencies ?? []).filter((d) => d.type === "blocked_by").map((d) => d.taskId);
15
+ }
16
+ /**
17
+ * Initialize CPM tasks with default values
18
+ */
19
+ function initializeCPMTasks(sortedTasks) {
20
+ const taskMap = new Map();
21
+ for (const task of sortedTasks) {
22
+ const duration = getTaskDuration(task);
23
+ taskMap.set(task.id, {
24
+ ...task,
25
+ earliestStart: 0,
26
+ earliestFinish: duration,
27
+ latestStart: Infinity,
28
+ latestFinish: Infinity,
29
+ slack: 0,
30
+ isCritical: false,
31
+ dependentCount: 0,
32
+ });
33
+ }
34
+ return taskMap;
35
+ }
36
+ /**
37
+ * Forward pass: Calculate earliest start/finish times
38
+ * ES = max(EF of all predecessors)
39
+ * EF = ES + duration
40
+ */
41
+ function forwardPass(sortedTasks, taskMap) {
42
+ for (const task of sortedTasks) {
43
+ const cpmTask = taskMap.get(task.id);
44
+ if (!cpmTask)
45
+ continue;
46
+ const duration = getTaskDuration(task);
47
+ const deps = getBlockedByDeps(task);
48
+ // Find maximum EF among predecessors
49
+ let maxPredecessorEF = 0;
50
+ for (const depId of deps) {
51
+ const dep = taskMap.get(depId);
52
+ if (dep) {
53
+ maxPredecessorEF = Math.max(maxPredecessorEF, dep.earliestFinish);
54
+ }
55
+ }
56
+ cpmTask.earliestStart = maxPredecessorEF;
57
+ cpmTask.earliestFinish = cpmTask.earliestStart + duration;
58
+ }
59
+ }
60
+ /**
61
+ * Calculate project duration (maximum earliest finish)
62
+ */
63
+ function calculateProjectDuration(taskMap) {
64
+ return Math.max(...Array.from(taskMap.values()).map((t) => t.earliestFinish));
65
+ }
66
+ /**
67
+ * Build successor index: maps taskId -> list of tasks that depend on it
68
+ * This is O(n * d) where d is average dependencies, done once upfront
69
+ * Allows O(1) successor lookup instead of O(n) per task
70
+ */
71
+ function buildSuccessorIndex(sortedTasks, taskMap) {
72
+ const successorIndex = new Map();
73
+ // Initialize empty arrays for all tasks
74
+ for (const task of sortedTasks) {
75
+ successorIndex.set(task.id, []);
76
+ }
77
+ // Build the index: if task A is blocked_by task B, then A is a successor of B
78
+ for (const task of sortedTasks) {
79
+ const deps = getBlockedByDeps(task);
80
+ const cpmTask = taskMap.get(task.id);
81
+ if (!cpmTask)
82
+ continue;
83
+ for (const depId of deps) {
84
+ const successors = successorIndex.get(depId);
85
+ if (successors) {
86
+ successors.push(cpmTask);
87
+ }
88
+ }
89
+ }
90
+ return successorIndex;
91
+ }
92
+ /**
93
+ * Find tasks that have successors (are dependencies of other tasks)
94
+ */
95
+ function findTasksWithSuccessors(successorIndex) {
96
+ const tasksWithSuccessors = new Set();
97
+ for (const [taskId, successors] of successorIndex) {
98
+ if (successors.length > 0) {
99
+ tasksWithSuccessors.add(taskId);
100
+ }
101
+ }
102
+ return tasksWithSuccessors;
103
+ }
104
+ /**
105
+ * Backward pass: Calculate latest start/finish times
106
+ * LF = min(LS of all successors) or projectDuration for end tasks
107
+ * LS = LF - duration
108
+ */
109
+ function backwardPass(sortedTasks, taskMap, successorIndex, projectDuration) {
110
+ const tasksWithSuccessors = findTasksWithSuccessors(successorIndex);
111
+ // Initialize end tasks (tasks with no successors)
112
+ for (const task of taskMap.values()) {
113
+ if (!tasksWithSuccessors.has(task.id)) {
114
+ const duration = getTaskDuration(task);
115
+ task.latestFinish = projectDuration;
116
+ task.latestStart = task.latestFinish - duration;
117
+ }
118
+ }
119
+ // Process in reverse topological order
120
+ const reverseSorted = [...sortedTasks].reverse();
121
+ for (const task of reverseSorted) {
122
+ const cpmTask = taskMap.get(task.id);
123
+ if (!cpmTask)
124
+ continue;
125
+ const duration = getTaskDuration(task);
126
+ const successors = successorIndex.get(task.id) ?? [];
127
+ if (successors.length > 0) {
128
+ // LF = min(LS of all successors)
129
+ cpmTask.latestFinish = Math.min(...successors.map((s) => s.latestStart));
130
+ cpmTask.latestStart = cpmTask.latestFinish - duration;
131
+ }
132
+ }
133
+ }
134
+ /**
135
+ * Calculate slack and mark critical tasks
136
+ * Slack = LS - ES (or LF - EF)
137
+ * Critical = slack ≈ 0
138
+ */
139
+ function calculateSlackAndCritical(taskMap) {
140
+ const FLOAT_TOLERANCE = 0.001;
141
+ for (const task of taskMap.values()) {
142
+ task.slack = task.latestStart - task.earliestStart;
143
+ task.isCritical = Math.abs(task.slack) < FLOAT_TOLERANCE;
144
+ }
145
+ }
146
+ /**
147
+ * Count dependents for bottleneck detection using successor index
148
+ * Uses dynamic programming: dependentCount = direct successors + their dependentCounts
149
+ * O(n) instead of O(n³) with findDependents
150
+ */
151
+ function countDependents(sortedTasks, taskMap, successorIndex) {
152
+ // Process in reverse topological order so we compute children before parents
153
+ const reverseSorted = [...sortedTasks].reverse();
154
+ for (const task of reverseSorted) {
155
+ const cpmTask = taskMap.get(task.id);
156
+ if (!cpmTask)
157
+ continue;
158
+ const successors = successorIndex.get(task.id) ?? [];
159
+ // dependentCount = number of direct successors + sum of their dependentCounts
160
+ let count = successors.length;
161
+ for (const successor of successors) {
162
+ count += successor.dependentCount;
163
+ }
164
+ cpmTask.dependentCount = count;
165
+ }
166
+ }
167
+ /**
168
+ * Extract critical path tasks in topological order
169
+ */
170
+ function extractCriticalPath(sortedTasks, taskMap) {
171
+ return sortedTasks
172
+ .map((t) => taskMap.get(t.id))
173
+ .filter((t) => t !== undefined && t.isCritical);
174
+ }
175
+ /**
176
+ * Find top bottlenecks (critical tasks blocking the most downstream work)
177
+ */
178
+ function findBottlenecks(criticalPath, limit = 5) {
179
+ return [...criticalPath].sort((a, b) => b.dependentCount - a.dependentCount).slice(0, limit);
180
+ }
181
+ /**
182
+ * Perform Critical Path Method analysis
183
+ *
184
+ * CPM calculates:
185
+ * - Earliest Start (ES): Earliest a task can start
186
+ * - Earliest Finish (EF): ES + duration
187
+ * - Latest Finish (LF): Latest a task can finish without delaying project
188
+ * - Latest Start (LS): LF - duration
189
+ * - Slack: LS - ES (or LF - EF)
190
+ * - Critical Path: Tasks with slack = 0
191
+ */
192
+ export function criticalPathAnalysis(tasks) {
193
+ // Filter to only pending/in_progress tasks
194
+ const activeTasks = tasks.filter((t) => t.status === "pending" || t.status === "in_progress");
195
+ if (activeTasks.length === 0) {
196
+ return {
197
+ tasks: [],
198
+ criticalPath: [],
199
+ projectDuration: 0,
200
+ bottlenecks: [],
201
+ };
202
+ }
203
+ // Sort topologically
204
+ const sortedTasks = topologicalSort(activeTasks);
205
+ // Initialize CPM tasks
206
+ const taskMap = initializeCPMTasks(sortedTasks);
207
+ // Build successor index once (O(n*d)) for O(1) lookups
208
+ const successorIndex = buildSuccessorIndex(sortedTasks, taskMap);
209
+ // Forward pass: Calculate earliest start/finish
210
+ forwardPass(sortedTasks, taskMap);
211
+ // Calculate project duration
212
+ const projectDuration = calculateProjectDuration(taskMap);
213
+ // Backward pass: Calculate latest start/finish (uses successorIndex)
214
+ backwardPass(sortedTasks, taskMap, successorIndex, projectDuration);
215
+ // Calculate slack and mark critical tasks
216
+ calculateSlackAndCritical(taskMap);
217
+ // Count dependents for bottleneck detection (uses successorIndex, O(n))
218
+ countDependents(sortedTasks, taskMap, successorIndex);
219
+ // Extract critical path
220
+ const criticalPath = extractCriticalPath(sortedTasks, taskMap);
221
+ // Find bottlenecks
222
+ const bottlenecks = findBottlenecks(criticalPath);
223
+ return {
224
+ tasks: sortedTasks.map((t) => taskMap.get(t.id)),
225
+ criticalPath,
226
+ projectDuration,
227
+ bottlenecks,
228
+ };
229
+ }
230
+ /**
231
+ * Find tasks that can be executed in parallel (no dependencies between them)
232
+ * Optimized to O(n + e) where n = number of tasks, e = number of dependencies
233
+ */
234
+ export function findParallelTasks(tasks) {
235
+ const activeTasks = tasks.filter((t) => t.status === "pending" || t.status === "in_progress");
236
+ if (activeTasks.length === 0)
237
+ return [];
238
+ // Find tasks with no uncompleted dependencies
239
+ const completedIds = new Set(tasks.filter((t) => t.status === "completed").map((t) => t.id));
240
+ const available = activeTasks.filter((task) => {
241
+ const deps = getBlockedByDeps(task);
242
+ return deps.every((depId) => completedIds.has(depId));
243
+ });
244
+ if (available.length <= 1)
245
+ return [available];
246
+ // Build dependency Sets for O(1) lookup - O(n + e) total
247
+ const dependsOn = new Map();
248
+ for (const task of available) {
249
+ const deps = (task.dependencies ?? []).map((d) => d.taskId);
250
+ dependsOn.set(task.id, new Set(deps));
251
+ }
252
+ // Build reverse dependency index (who depends on me) - O(e) total
253
+ const dependedBy = new Map();
254
+ for (const task of available) {
255
+ dependedBy.set(task.id, new Set());
256
+ }
257
+ for (const task of available) {
258
+ const deps = dependsOn.get(task.id) ?? new Set();
259
+ for (const depId of deps) {
260
+ dependedBy.get(depId)?.add(task.id);
261
+ }
262
+ }
263
+ // Group tasks that don't depend on each other - O(n + e)
264
+ const groups = [];
265
+ const processed = new Set();
266
+ for (const task of available) {
267
+ if (processed.has(task.id))
268
+ continue;
269
+ const group = [task];
270
+ processed.add(task.id);
271
+ // Get all tasks that this task depends on or that depend on this task
272
+ const conflicting = new Set();
273
+ const taskDeps = dependsOn.get(task.id) ?? new Set();
274
+ const taskDependedBy = dependedBy.get(task.id) ?? new Set();
275
+ for (const id of taskDeps)
276
+ conflicting.add(id);
277
+ for (const id of taskDependedBy)
278
+ conflicting.add(id);
279
+ for (const other of available) {
280
+ if (processed.has(other.id))
281
+ continue;
282
+ // O(1) check: tasks are independent if neither depends on the other
283
+ const independent = !conflicting.has(other.id) && !dependsOn.get(other.id)?.has(task.id);
284
+ if (independent) {
285
+ group.push(other);
286
+ processed.add(other.id);
287
+ }
288
+ }
289
+ groups.push(group);
290
+ }
291
+ return groups;
292
+ }
293
+ /**
294
+ * Suggest the next best task to work on
295
+ */
296
+ export function suggestNextTask(tasks, options = {}) {
297
+ const activeTasks = tasks.filter((t) => t.status === "pending" || t.status === "in_progress");
298
+ if (activeTasks.length === 0)
299
+ return null;
300
+ // Get CPM analysis
301
+ const cpm = criticalPathAnalysis(tasks);
302
+ // Filter by availability (all dependencies completed)
303
+ const completedIds = new Set(tasks.filter((t) => t.status === "completed").map((t) => t.id));
304
+ let candidates = cpm.tasks.filter((task) => {
305
+ const deps = getBlockedByDeps(task);
306
+ return deps.every((depId) => completedIds.has(depId));
307
+ });
308
+ // Filter by context if specified
309
+ if (options.contexts?.length) {
310
+ const contextSet = new Set(options.contexts);
311
+ const contextFiltered = candidates.filter((t) => (t.contexts ?? []).some((c) => contextSet.has(c)));
312
+ if (contextFiltered.length > 0) {
313
+ candidates = contextFiltered;
314
+ }
315
+ }
316
+ // Filter by time if specified
317
+ if (options.maxMinutes) {
318
+ const timeFiltered = candidates.filter((t) => getTaskDuration(t) <= options.maxMinutes);
319
+ if (timeFiltered.length > 0) {
320
+ candidates = timeFiltered;
321
+ }
322
+ }
323
+ if (candidates.length === 0)
324
+ return null;
325
+ // Score and rank candidates
326
+ // Priority: Critical path > High priority > Most dependents > Shortest duration
327
+ const scored = candidates.map((task) => {
328
+ let score = 0;
329
+ if (task.isCritical)
330
+ score += 1000;
331
+ score += task.dependentCount * 100;
332
+ score += priorityToNumber(task.priority) * 10;
333
+ // Prefer shorter tasks (quick wins)
334
+ score += Math.max(0, 100 - getTaskDuration(task));
335
+ return { task, score };
336
+ });
337
+ scored.sort((a, b) => b.score - a.score);
338
+ return scored[0]?.task ?? null;
339
+ }
340
+ //# sourceMappingURL=critical-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critical-path.js","sourceRoot":"","sources":["../../src/algorithms/critical-path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=critical-path.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critical-path.test.d.ts","sourceRoot":"","sources":["../../src/algorithms/critical-path.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,184 @@
1
+ import { describe, test, expect } from "bun:test";
2
+ import { criticalPathAnalysis, findParallelTasks, suggestNextTask } from "./critical-path.js";
3
+ // Helper to create mock tasks
4
+ function createTask(id, options = {}) {
5
+ const task = {
6
+ id,
7
+ title: `Task ${id}`,
8
+ status: (options.status ?? "pending"),
9
+ priority: (options.priority ?? "medium"),
10
+ workspace: "test-workspace",
11
+ createdAt: new Date().toISOString(),
12
+ updatedAt: new Date().toISOString(),
13
+ dependencies: (options.deps ?? []).map((depId) => ({
14
+ taskId: depId,
15
+ type: "blocked_by",
16
+ })),
17
+ };
18
+ if (options.estimate) {
19
+ task.estimate = { expected: options.estimate, confidence: "medium" };
20
+ }
21
+ if (options.contexts) {
22
+ task.contexts = options.contexts;
23
+ }
24
+ return task;
25
+ }
26
+ describe("criticalPathAnalysis", () => {
27
+ test("returns empty result for empty input", () => {
28
+ const result = criticalPathAnalysis([]);
29
+ expect(result.tasks).toEqual([]);
30
+ expect(result.criticalPath).toEqual([]);
31
+ expect(result.projectDuration).toBe(0);
32
+ });
33
+ test("returns empty for all completed tasks", () => {
34
+ const tasks = [createTask("A", { status: "completed" })];
35
+ const result = criticalPathAnalysis(tasks);
36
+ expect(result.tasks).toEqual([]);
37
+ });
38
+ test("calculates single task correctly", () => {
39
+ const tasks = [createTask("A", { estimate: 60 })];
40
+ const result = criticalPathAnalysis(tasks);
41
+ expect(result.projectDuration).toBe(60);
42
+ expect(result.criticalPath.length).toBe(1);
43
+ expect(result.criticalPath[0].id).toBe("A");
44
+ expect(result.criticalPath[0].isCritical).toBe(true);
45
+ });
46
+ test("identifies critical path in linear chain", () => {
47
+ // A -> B -> C (each 30 min)
48
+ const tasks = [
49
+ createTask("A", { estimate: 30 }),
50
+ createTask("B", { estimate: 30, deps: ["A"] }),
51
+ createTask("C", { estimate: 30, deps: ["B"] }),
52
+ ];
53
+ const result = criticalPathAnalysis(tasks);
54
+ expect(result.projectDuration).toBe(90);
55
+ expect(result.criticalPath.length).toBe(3);
56
+ expect(result.criticalPath.map((t) => t.id)).toEqual(["A", "B", "C"]);
57
+ });
58
+ test("calculates slack for parallel tasks", () => {
59
+ // A (60) and B (30) both lead to C
60
+ // A is on critical path, B has 30 min slack
61
+ const tasks = [
62
+ createTask("A", { estimate: 60 }),
63
+ createTask("B", { estimate: 30 }),
64
+ createTask("C", { estimate: 30, deps: ["A", "B"] }),
65
+ ];
66
+ const result = criticalPathAnalysis(tasks);
67
+ expect(result.projectDuration).toBe(90); // A + C
68
+ const taskA = result.tasks.find((t) => t.id === "A");
69
+ const taskB = result.tasks.find((t) => t.id === "B");
70
+ const taskC = result.tasks.find((t) => t.id === "C");
71
+ expect(taskA.isCritical).toBe(true);
72
+ expect(taskB.slack).toBe(30); // B can start 30 min late
73
+ expect(taskC.isCritical).toBe(true);
74
+ });
75
+ test("identifies bottlenecks by dependent count", () => {
76
+ // A blocks B, C, D
77
+ const tasks = [
78
+ createTask("A", { estimate: 30 }),
79
+ createTask("B", { estimate: 30, deps: ["A"] }),
80
+ createTask("C", { estimate: 30, deps: ["A"] }),
81
+ createTask("D", { estimate: 30, deps: ["A"] }),
82
+ ];
83
+ const result = criticalPathAnalysis(tasks);
84
+ expect(result.bottlenecks.length).toBeGreaterThan(0);
85
+ expect(result.bottlenecks[0].id).toBe("A"); // A blocks the most tasks
86
+ });
87
+ });
88
+ describe("findParallelTasks", () => {
89
+ test("returns empty for empty input", () => {
90
+ const result = findParallelTasks([]);
91
+ expect(result).toEqual([]);
92
+ });
93
+ test("returns single group for independent tasks", () => {
94
+ const tasks = [createTask("A"), createTask("B"), createTask("C")];
95
+ const result = findParallelTasks(tasks);
96
+ expect(result.length).toBe(1);
97
+ expect(result[0].length).toBe(3);
98
+ });
99
+ test("excludes tasks with uncompleted dependencies", () => {
100
+ const tasks = [createTask("A"), createTask("B", { deps: ["A"] })];
101
+ const result = findParallelTasks(tasks);
102
+ // Only A is available (B is blocked)
103
+ expect(result.length).toBe(1);
104
+ expect(result[0].length).toBe(1);
105
+ expect(result[0][0].id).toBe("A");
106
+ });
107
+ test("includes task when dependency is completed", () => {
108
+ const tasks = [
109
+ createTask("A", { status: "completed" }),
110
+ createTask("B", { deps: ["A"] }),
111
+ createTask("C"),
112
+ ];
113
+ const result = findParallelTasks(tasks);
114
+ // B and C can run in parallel
115
+ expect(result.length).toBe(1);
116
+ expect(result[0].map((t) => t.id).sort()).toEqual(["B", "C"]);
117
+ });
118
+ test("excludes completed tasks from result", () => {
119
+ const tasks = [createTask("A", { status: "completed" }), createTask("B")];
120
+ const result = findParallelTasks(tasks);
121
+ expect(result.length).toBe(1);
122
+ expect(result[0].length).toBe(1);
123
+ expect(result[0][0].id).toBe("B");
124
+ });
125
+ });
126
+ describe("suggestNextTask", () => {
127
+ test("returns null for empty input", () => {
128
+ const result = suggestNextTask([]);
129
+ expect(result).toBeNull();
130
+ });
131
+ test("returns null when all tasks completed", () => {
132
+ const tasks = [createTask("A", { status: "completed" })];
133
+ const result = suggestNextTask(tasks);
134
+ expect(result).toBeNull();
135
+ });
136
+ test("prefers critical path tasks", () => {
137
+ // A is critical (longer), B has slack
138
+ const tasks = [
139
+ createTask("A", { estimate: 60, priority: "low" }),
140
+ createTask("B", { estimate: 30, priority: "high" }),
141
+ createTask("C", { estimate: 30, deps: ["A", "B"] }),
142
+ ];
143
+ const result = suggestNextTask(tasks);
144
+ // A is on critical path, should be suggested first
145
+ expect(result.id).toBe("A");
146
+ });
147
+ test("filters by context when specified", () => {
148
+ const tasks = [
149
+ createTask("A", { priority: "critical", contexts: ["office"] }),
150
+ createTask("B", { priority: "high", contexts: ["focus"] }),
151
+ ];
152
+ const result = suggestNextTask(tasks, { contexts: ["focus"] });
153
+ expect(result.id).toBe("B");
154
+ });
155
+ test("filters by max time when specified", () => {
156
+ const tasks = [
157
+ createTask("A", { estimate: 120, priority: "critical" }),
158
+ createTask("B", { estimate: 30, priority: "high" }),
159
+ ];
160
+ const result = suggestNextTask(tasks, { maxMinutes: 60 });
161
+ expect(result.id).toBe("B");
162
+ });
163
+ test("skips blocked tasks", () => {
164
+ const tasks = [
165
+ createTask("A", { priority: "low" }),
166
+ createTask("B", { priority: "critical", deps: ["A"] }),
167
+ ];
168
+ const result = suggestNextTask(tasks);
169
+ // B is blocked, so A should be suggested
170
+ expect(result.id).toBe("A");
171
+ });
172
+ test("considers tasks with more dependents", () => {
173
+ const tasks = [
174
+ createTask("A", { priority: "medium" }),
175
+ createTask("B", { priority: "medium" }),
176
+ createTask("C", { priority: "medium", deps: ["A"] }),
177
+ createTask("D", { priority: "medium", deps: ["A"] }),
178
+ ];
179
+ const result = suggestNextTask(tasks);
180
+ // A blocks more tasks (C and D), should be preferred over B
181
+ expect(result.id).toBe("A");
182
+ });
183
+ });
184
+ //# sourceMappingURL=critical-path.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critical-path.test.js","sourceRoot":"","sources":["../../src/algorithms/critical-path.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG9F,8BAA8B;AAC9B,SAAS,UAAU,CACjB,EAAU,EACV,UAMI,EAAE;IAEN,MAAM,IAAI,GAAS;QACjB,EAAE;QACF,KAAK,EAAE,QAAQ,EAAE,EAAE;QACnB,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,SAAS,CAAmB;QACvD,QAAQ,EAAE,CAAC,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAqB;QAC5D,SAAS,EAAE,gBAAgB;QAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,YAAY,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACjD,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,YAAqB;SAC5B,CAAC,CAAC;KACJ,CAAC;IACF,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAiB,EAAE,CAAC;IAChF,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE;QACjD,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC5C,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAE3C,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACpD,4BAA4B;QAC5B,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACjC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;SAC/C,CAAC;QACF,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAE3C,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC/C,mCAAmC;QACnC,4CAA4C;QAC5C,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACjC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACjC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;SACpD,CAAC;QACF,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAE3C,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ;QAEjD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAE,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAE,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAE,CAAC;QAEtD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,0BAA0B;QACxD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACrD,mBAAmB;QACnB,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACjC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;SAC/C,CAAC;QACF,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAE3C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,0BAA0B;IACzE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACzC,MAAM,MAAM,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACxD,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAExC,qCAAqC;QACrC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YACxC,UAAU,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,UAAU,CAAC,GAAG,CAAC;SAChB,CAAC;QACF,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAExC,8BAA8B;QAC9B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAChD,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACxC,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE;QACjD,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACvC,sCAAsC;QACtC,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAClD,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YACnD,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;SACpD,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtC,mDAAmD;QACnD,MAAM,CAAC,MAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC7C,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/D,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;SAC3D,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAE/D,MAAM,CAAC,MAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC9C,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;YACxD,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;SACpD,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAE1D,MAAM,CAAC,MAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC/B,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YACpC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;SACvD,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtC,yCAAyC;QACzC,MAAM,CAAC,MAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAChD,MAAM,KAAK,GAAG;YACZ,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;YACvC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;YACvC,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YACpD,UAAU,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;SACrD,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAEtC,4DAA4D;QAC5D,MAAM,CAAC,MAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}