@task-mcp/shared 1.0.19 → 1.0.21

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 (163) hide show
  1. package/package.json +1 -6
  2. package/src/schemas/task.ts +60 -14
  3. package/src/utils/date.ts +40 -0
  4. package/src/utils/hierarchy.ts +63 -1
  5. package/src/utils/index.ts +2 -0
  6. package/src/utils/natural-language.ts +12 -0
  7. package/src/utils/projection.ts +14 -3
  8. package/dist/algorithms/critical-path.d.ts +0 -46
  9. package/dist/algorithms/critical-path.d.ts.map +0 -1
  10. package/dist/algorithms/critical-path.js +0 -320
  11. package/dist/algorithms/critical-path.js.map +0 -1
  12. package/dist/algorithms/critical-path.test.d.ts +0 -2
  13. package/dist/algorithms/critical-path.test.d.ts.map +0 -1
  14. package/dist/algorithms/critical-path.test.js +0 -194
  15. package/dist/algorithms/critical-path.test.js.map +0 -1
  16. package/dist/algorithms/dependency-integrity.d.ts +0 -81
  17. package/dist/algorithms/dependency-integrity.d.ts.map +0 -1
  18. package/dist/algorithms/dependency-integrity.js +0 -207
  19. package/dist/algorithms/dependency-integrity.js.map +0 -1
  20. package/dist/algorithms/dependency-integrity.test.d.ts +0 -2
  21. package/dist/algorithms/dependency-integrity.test.d.ts.map +0 -1
  22. package/dist/algorithms/dependency-integrity.test.js +0 -309
  23. package/dist/algorithms/dependency-integrity.test.js.map +0 -1
  24. package/dist/algorithms/index.d.ts +0 -5
  25. package/dist/algorithms/index.d.ts.map +0 -1
  26. package/dist/algorithms/index.js +0 -5
  27. package/dist/algorithms/index.js.map +0 -1
  28. package/dist/algorithms/tech-analysis.d.ts +0 -106
  29. package/dist/algorithms/tech-analysis.d.ts.map +0 -1
  30. package/dist/algorithms/tech-analysis.js +0 -344
  31. package/dist/algorithms/tech-analysis.js.map +0 -1
  32. package/dist/algorithms/tech-analysis.test.d.ts +0 -2
  33. package/dist/algorithms/tech-analysis.test.d.ts.map +0 -1
  34. package/dist/algorithms/tech-analysis.test.js +0 -338
  35. package/dist/algorithms/tech-analysis.test.js.map +0 -1
  36. package/dist/algorithms/topological-sort.d.ts +0 -41
  37. package/dist/algorithms/topological-sort.d.ts.map +0 -1
  38. package/dist/algorithms/topological-sort.js +0 -165
  39. package/dist/algorithms/topological-sort.js.map +0 -1
  40. package/dist/algorithms/topological-sort.test.d.ts +0 -2
  41. package/dist/algorithms/topological-sort.test.d.ts.map +0 -1
  42. package/dist/algorithms/topological-sort.test.js +0 -162
  43. package/dist/algorithms/topological-sort.test.js.map +0 -1
  44. package/dist/index.d.ts +0 -4
  45. package/dist/index.d.ts.map +0 -1
  46. package/dist/index.js +0 -7
  47. package/dist/index.js.map +0 -1
  48. package/dist/schemas/inbox.d.ts +0 -55
  49. package/dist/schemas/inbox.d.ts.map +0 -1
  50. package/dist/schemas/inbox.js +0 -25
  51. package/dist/schemas/inbox.js.map +0 -1
  52. package/dist/schemas/index.d.ts +0 -7
  53. package/dist/schemas/index.d.ts.map +0 -1
  54. package/dist/schemas/index.js +0 -17
  55. package/dist/schemas/index.js.map +0 -1
  56. package/dist/schemas/project.d.ts +0 -177
  57. package/dist/schemas/project.d.ts.map +0 -1
  58. package/dist/schemas/project.js +0 -56
  59. package/dist/schemas/project.js.map +0 -1
  60. package/dist/schemas/response-format.d.ts +0 -148
  61. package/dist/schemas/response-format.d.ts.map +0 -1
  62. package/dist/schemas/response-format.js +0 -18
  63. package/dist/schemas/response-format.js.map +0 -1
  64. package/dist/schemas/response-schema.d.ts +0 -307
  65. package/dist/schemas/response-schema.d.ts.map +0 -1
  66. package/dist/schemas/response-schema.js +0 -75
  67. package/dist/schemas/response-schema.js.map +0 -1
  68. package/dist/schemas/response-schema.test.d.ts +0 -2
  69. package/dist/schemas/response-schema.test.d.ts.map +0 -1
  70. package/dist/schemas/response-schema.test.js +0 -256
  71. package/dist/schemas/response-schema.test.js.map +0 -1
  72. package/dist/schemas/state.d.ts +0 -17
  73. package/dist/schemas/state.d.ts.map +0 -1
  74. package/dist/schemas/state.js +0 -17
  75. package/dist/schemas/state.js.map +0 -1
  76. package/dist/schemas/task.d.ts +0 -625
  77. package/dist/schemas/task.d.ts.map +0 -1
  78. package/dist/schemas/task.js +0 -152
  79. package/dist/schemas/task.js.map +0 -1
  80. package/dist/schemas/view.d.ts +0 -143
  81. package/dist/schemas/view.d.ts.map +0 -1
  82. package/dist/schemas/view.js +0 -48
  83. package/dist/schemas/view.js.map +0 -1
  84. package/dist/utils/dashboard-renderer.d.ts +0 -93
  85. package/dist/utils/dashboard-renderer.d.ts.map +0 -1
  86. package/dist/utils/dashboard-renderer.js +0 -424
  87. package/dist/utils/dashboard-renderer.js.map +0 -1
  88. package/dist/utils/dashboard-renderer.test.d.ts +0 -2
  89. package/dist/utils/dashboard-renderer.test.d.ts.map +0 -1
  90. package/dist/utils/dashboard-renderer.test.js +0 -774
  91. package/dist/utils/dashboard-renderer.test.js.map +0 -1
  92. package/dist/utils/date.d.ts +0 -81
  93. package/dist/utils/date.d.ts.map +0 -1
  94. package/dist/utils/date.js +0 -294
  95. package/dist/utils/date.js.map +0 -1
  96. package/dist/utils/date.test.d.ts +0 -2
  97. package/dist/utils/date.test.d.ts.map +0 -1
  98. package/dist/utils/date.test.js +0 -276
  99. package/dist/utils/date.test.js.map +0 -1
  100. package/dist/utils/hierarchy.d.ts +0 -75
  101. package/dist/utils/hierarchy.d.ts.map +0 -1
  102. package/dist/utils/hierarchy.js +0 -189
  103. package/dist/utils/hierarchy.js.map +0 -1
  104. package/dist/utils/hierarchy.test.d.ts +0 -2
  105. package/dist/utils/hierarchy.test.d.ts.map +0 -1
  106. package/dist/utils/hierarchy.test.js +0 -351
  107. package/dist/utils/hierarchy.test.js.map +0 -1
  108. package/dist/utils/id.d.ts +0 -60
  109. package/dist/utils/id.d.ts.map +0 -1
  110. package/dist/utils/id.js +0 -118
  111. package/dist/utils/id.js.map +0 -1
  112. package/dist/utils/id.test.d.ts +0 -2
  113. package/dist/utils/id.test.d.ts.map +0 -1
  114. package/dist/utils/id.test.js +0 -193
  115. package/dist/utils/id.test.js.map +0 -1
  116. package/dist/utils/index.d.ts +0 -12
  117. package/dist/utils/index.d.ts.map +0 -1
  118. package/dist/utils/index.js +0 -34
  119. package/dist/utils/index.js.map +0 -1
  120. package/dist/utils/natural-language.d.ts +0 -57
  121. package/dist/utils/natural-language.d.ts.map +0 -1
  122. package/dist/utils/natural-language.js +0 -205
  123. package/dist/utils/natural-language.js.map +0 -1
  124. package/dist/utils/natural-language.test.d.ts +0 -2
  125. package/dist/utils/natural-language.test.d.ts.map +0 -1
  126. package/dist/utils/natural-language.test.js +0 -156
  127. package/dist/utils/natural-language.test.js.map +0 -1
  128. package/dist/utils/priority-queue.d.ts +0 -17
  129. package/dist/utils/priority-queue.d.ts.map +0 -1
  130. package/dist/utils/priority-queue.js +0 -62
  131. package/dist/utils/priority-queue.js.map +0 -1
  132. package/dist/utils/projection.d.ts +0 -65
  133. package/dist/utils/projection.d.ts.map +0 -1
  134. package/dist/utils/projection.js +0 -170
  135. package/dist/utils/projection.js.map +0 -1
  136. package/dist/utils/projection.test.d.ts +0 -2
  137. package/dist/utils/projection.test.d.ts.map +0 -1
  138. package/dist/utils/projection.test.js +0 -336
  139. package/dist/utils/projection.test.js.map +0 -1
  140. package/dist/utils/terminal-ui.d.ts +0 -208
  141. package/dist/utils/terminal-ui.d.ts.map +0 -1
  142. package/dist/utils/terminal-ui.js +0 -611
  143. package/dist/utils/terminal-ui.js.map +0 -1
  144. package/dist/utils/terminal-ui.test.d.ts +0 -2
  145. package/dist/utils/terminal-ui.test.d.ts.map +0 -1
  146. package/dist/utils/terminal-ui.test.js +0 -683
  147. package/dist/utils/terminal-ui.test.js.map +0 -1
  148. package/dist/utils/workspace.d.ts +0 -100
  149. package/dist/utils/workspace.d.ts.map +0 -1
  150. package/dist/utils/workspace.js +0 -173
  151. package/dist/utils/workspace.js.map +0 -1
  152. package/src/algorithms/critical-path.test.ts +0 -241
  153. package/src/algorithms/dependency-integrity.test.ts +0 -348
  154. package/src/algorithms/tech-analysis.test.ts +0 -413
  155. package/src/algorithms/topological-sort.test.ts +0 -190
  156. package/src/schemas/response-schema.test.ts +0 -314
  157. package/src/utils/dashboard-renderer.test.ts +0 -983
  158. package/src/utils/date.test.ts +0 -329
  159. package/src/utils/hierarchy.test.ts +0 -411
  160. package/src/utils/id.test.ts +0 -235
  161. package/src/utils/natural-language.test.ts +0 -182
  162. package/src/utils/projection.test.ts +0 -425
  163. package/src/utils/terminal-ui.test.ts +0 -831
@@ -1,348 +0,0 @@
1
- import { describe, test, expect } from "bun:test";
2
- import {
3
- DependencyErrorCode,
4
- validateDependency,
5
- findInvalidDependencies,
6
- findSelfDependencies,
7
- detectCircularDependencies,
8
- checkDependencyIntegrity,
9
- } from "./dependency-integrity.js";
10
- import type { Task } from "../schemas/task.js";
11
-
12
- // Helper to create mock tasks
13
- function createTask(
14
- id: string,
15
- title: string = `Task ${id}`,
16
- deps: Array<{ taskId: string; type: "blocked_by" | "blocks" | "related" }> = []
17
- ): Task {
18
- return {
19
- id,
20
- title,
21
- status: "pending",
22
- priority: "medium",
23
- workspace: "test-workspace",
24
- createdAt: new Date().toISOString(),
25
- updatedAt: new Date().toISOString(),
26
- dependencies: deps,
27
- };
28
- }
29
-
30
- describe("validateDependency", () => {
31
- test("returns valid for a valid dependency", () => {
32
- const tasks = [createTask("A"), createTask("B")];
33
- const result = validateDependency({
34
- taskId: "B",
35
- blockedBy: "A",
36
- tasks,
37
- });
38
- expect(result.valid).toBe(true);
39
- expect(result.errorCode).toBeUndefined();
40
- });
41
-
42
- test("rejects self-dependency", () => {
43
- const tasks = [createTask("A")];
44
- const result = validateDependency({
45
- taskId: "A",
46
- blockedBy: "A",
47
- tasks,
48
- });
49
- expect(result.valid).toBe(false);
50
- expect(result.errorCode).toBe(DependencyErrorCode.SELF_DEPENDENCY);
51
- expect(result.errorMessage).toContain("cannot depend on itself");
52
- expect(result.suggestion).toBeDefined();
53
- });
54
-
55
- test("rejects when task not found", () => {
56
- const tasks = [createTask("A")];
57
- const result = validateDependency({
58
- taskId: "B",
59
- blockedBy: "A",
60
- tasks,
61
- });
62
- expect(result.valid).toBe(false);
63
- expect(result.errorCode).toBe(DependencyErrorCode.TASK_NOT_FOUND);
64
- expect(result.errorMessage).toContain("Task not found");
65
- });
66
-
67
- test("rejects when blocker not found", () => {
68
- const tasks = [createTask("A")];
69
- const result = validateDependency({
70
- taskId: "A",
71
- blockedBy: "B",
72
- tasks,
73
- });
74
- expect(result.valid).toBe(false);
75
- expect(result.errorCode).toBe(DependencyErrorCode.BLOCKER_NOT_FOUND);
76
- expect(result.errorMessage).toContain("Blocking task not found");
77
- });
78
-
79
- test("rejects duplicate dependency", () => {
80
- const tasks = [
81
- createTask("A"),
82
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
83
- ];
84
- const result = validateDependency({
85
- taskId: "B",
86
- blockedBy: "A",
87
- tasks,
88
- });
89
- expect(result.valid).toBe(false);
90
- expect(result.errorCode).toBe(DependencyErrorCode.DUPLICATE_DEPENDENCY);
91
- expect(result.errorMessage).toContain("already blocked by");
92
- });
93
-
94
- test("allows duplicate when checkDuplicates is false", () => {
95
- const tasks = [
96
- createTask("A"),
97
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
98
- ];
99
- const result = validateDependency({
100
- taskId: "B",
101
- blockedBy: "A",
102
- tasks,
103
- checkDuplicates: false,
104
- });
105
- expect(result.valid).toBe(true);
106
- });
107
-
108
- test("rejects circular dependency", () => {
109
- const tasks = [
110
- createTask("A", "Task A", [{ taskId: "B", type: "blocked_by" }]),
111
- createTask("B"),
112
- ];
113
- // B is blocking A, so A blocking B would create a cycle
114
- const result = validateDependency({
115
- taskId: "B",
116
- blockedBy: "A",
117
- tasks,
118
- });
119
- expect(result.valid).toBe(false);
120
- expect(result.errorCode).toBe(DependencyErrorCode.CIRCULAR_DEPENDENCY);
121
- expect(result.errorMessage).toContain("cycle");
122
- expect(result.suggestion).toContain("depends on");
123
- });
124
-
125
- test("rejects indirect circular dependency", () => {
126
- const tasks = [
127
- createTask("A", "Task A", [{ taskId: "B", type: "blocked_by" }]),
128
- createTask("B", "Task B", [{ taskId: "C", type: "blocked_by" }]),
129
- createTask("C"),
130
- ];
131
- // A <- B <- C, adding C <- A would create cycle
132
- const result = validateDependency({
133
- taskId: "C",
134
- blockedBy: "A",
135
- tasks,
136
- });
137
- expect(result.valid).toBe(false);
138
- expect(result.errorCode).toBe(DependencyErrorCode.CIRCULAR_DEPENDENCY);
139
- });
140
- });
141
-
142
- describe("findInvalidDependencies", () => {
143
- test("returns empty array when all dependencies are valid", () => {
144
- const tasks = [
145
- createTask("A"),
146
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
147
- ];
148
- const result = findInvalidDependencies(tasks);
149
- expect(result).toEqual([]);
150
- });
151
-
152
- test("finds orphaned dependency references", () => {
153
- const tasks = [
154
- createTask("A", "Task A", [{ taskId: "non-existent", type: "blocked_by" }]),
155
- ];
156
- const result = findInvalidDependencies(tasks);
157
- expect(result.length).toBe(1);
158
- expect(result[0]!.taskId).toBe("A");
159
- expect(result[0]!.taskTitle).toBe("Task A");
160
- expect(result[0]!.invalidDependencyId).toBe("non-existent");
161
- expect(result[0]!.type).toBe("blocked_by");
162
- });
163
-
164
- test("finds multiple invalid references across tasks", () => {
165
- const tasks = [
166
- createTask("A", "Task A", [{ taskId: "deleted-1", type: "blocked_by" }]),
167
- createTask("B", "Task B", [
168
- { taskId: "A", type: "blocked_by" },
169
- { taskId: "deleted-2", type: "blocks" },
170
- ]),
171
- ];
172
- const result = findInvalidDependencies(tasks);
173
- expect(result.length).toBe(2);
174
- expect(result.map((r) => r.invalidDependencyId).sort()).toEqual([
175
- "deleted-1",
176
- "deleted-2",
177
- ]);
178
- });
179
-
180
- test("returns empty array for tasks without dependencies", () => {
181
- const tasks = [createTask("A"), createTask("B")];
182
- const result = findInvalidDependencies(tasks);
183
- expect(result).toEqual([]);
184
- });
185
- });
186
-
187
- describe("findSelfDependencies", () => {
188
- test("returns empty array when no self-dependencies exist", () => {
189
- const tasks = [
190
- createTask("A"),
191
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
192
- ];
193
- const result = findSelfDependencies(tasks);
194
- expect(result).toEqual([]);
195
- });
196
-
197
- test("finds task with self-dependency", () => {
198
- const tasks = [
199
- createTask("A", "Task A", [{ taskId: "A", type: "blocked_by" }]),
200
- ];
201
- const result = findSelfDependencies(tasks);
202
- expect(result).toEqual(["A"]);
203
- });
204
-
205
- test("finds multiple self-dependencies", () => {
206
- const tasks = [
207
- createTask("A", "Task A", [{ taskId: "A", type: "blocked_by" }]),
208
- createTask("B"),
209
- createTask("C", "Task C", [{ taskId: "C", type: "blocks" }]),
210
- ];
211
- const result = findSelfDependencies(tasks);
212
- expect(result.sort()).toEqual(["A", "C"]);
213
- });
214
- });
215
-
216
- describe("detectCircularDependencies", () => {
217
- test("returns empty array when no cycles exist", () => {
218
- const tasks = [
219
- createTask("A"),
220
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
221
- createTask("C", "Task C", [{ taskId: "B", type: "blocked_by" }]),
222
- ];
223
- const result = detectCircularDependencies(tasks);
224
- expect(result).toEqual([]);
225
- });
226
-
227
- test("detects direct circular dependency (A -> B -> A)", () => {
228
- const tasks = [
229
- createTask("A", "Task A", [{ taskId: "B", type: "blocked_by" }]),
230
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
231
- ];
232
- const result = detectCircularDependencies(tasks);
233
- expect(result.length).toBe(1);
234
- expect(result[0]!.sort()).toEqual(["A", "B"]);
235
- });
236
-
237
- test("detects longer cycle (A -> B -> C -> A)", () => {
238
- const tasks = [
239
- createTask("A", "Task A", [{ taskId: "B", type: "blocked_by" }]),
240
- createTask("B", "Task B", [{ taskId: "C", type: "blocked_by" }]),
241
- createTask("C", "Task C", [{ taskId: "A", type: "blocked_by" }]),
242
- ];
243
- const result = detectCircularDependencies(tasks);
244
- expect(result.length).toBe(1);
245
- expect(result[0]!.sort()).toEqual(["A", "B", "C"]);
246
- });
247
-
248
- test("ignores non-blocking dependency types for cycle detection", () => {
249
- const tasks = [
250
- createTask("A", "Task A", [{ taskId: "B", type: "related" }]),
251
- createTask("B", "Task B", [{ taskId: "A", type: "related" }]),
252
- ];
253
- const result = detectCircularDependencies(tasks);
254
- expect(result).toEqual([]);
255
- });
256
-
257
- test("handles tasks with missing dependency targets", () => {
258
- const tasks = [
259
- createTask("A", "Task A", [{ taskId: "non-existent", type: "blocked_by" }]),
260
- ];
261
- const result = detectCircularDependencies(tasks);
262
- expect(result).toEqual([]);
263
- });
264
- });
265
-
266
- describe("checkDependencyIntegrity", () => {
267
- test("returns valid for healthy task set", () => {
268
- const tasks = [
269
- createTask("A"),
270
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
271
- createTask("C", "Task C", [{ taskId: "B", type: "blocked_by" }]),
272
- ];
273
- const result = checkDependencyIntegrity(tasks);
274
- expect(result.valid).toBe(true);
275
- expect(result.totalTasks).toBe(3);
276
- expect(result.totalDependencies).toBe(2);
277
- expect(result.issues.selfDependencies).toEqual([]);
278
- expect(result.issues.invalidReferences).toEqual([]);
279
- expect(result.issues.circularDependencies).toEqual([]);
280
- expect(result.summary).toContain("All 2 dependencies");
281
- expect(result.summary).toContain("valid");
282
- });
283
-
284
- test("detects self-dependency issues", () => {
285
- const tasks = [
286
- createTask("A", "Task A", [{ taskId: "A", type: "blocked_by" }]),
287
- ];
288
- const result = checkDependencyIntegrity(tasks);
289
- expect(result.valid).toBe(false);
290
- expect(result.issues.selfDependencies).toEqual(["A"]);
291
- expect(result.summary).toContain("self-dependencies");
292
- });
293
-
294
- test("detects invalid reference issues", () => {
295
- const tasks = [
296
- createTask("A", "Task A", [{ taskId: "deleted", type: "blocked_by" }]),
297
- ];
298
- const result = checkDependencyIntegrity(tasks);
299
- expect(result.valid).toBe(false);
300
- expect(result.issues.invalidReferences.length).toBe(1);
301
- expect(result.summary).toContain("invalid references");
302
- });
303
-
304
- test("detects circular dependency issues", () => {
305
- const tasks = [
306
- createTask("A", "Task A", [{ taskId: "B", type: "blocked_by" }]),
307
- createTask("B", "Task B", [{ taskId: "A", type: "blocked_by" }]),
308
- ];
309
- const result = checkDependencyIntegrity(tasks);
310
- expect(result.valid).toBe(false);
311
- expect(result.issues.circularDependencies.length).toBe(1);
312
- expect(result.summary).toContain("circular dependency");
313
- });
314
-
315
- test("reports multiple issue types", () => {
316
- const tasks = [
317
- createTask("A", "Task A", [
318
- { taskId: "A", type: "blocked_by" }, // self-dependency
319
- { taskId: "deleted", type: "blocked_by" }, // invalid reference
320
- ]),
321
- createTask("B", "Task B", [{ taskId: "C", type: "blocked_by" }]),
322
- createTask("C", "Task C", [{ taskId: "B", type: "blocked_by" }]), // circular
323
- ];
324
- const result = checkDependencyIntegrity(tasks);
325
- expect(result.valid).toBe(false);
326
- expect(result.issues.selfDependencies.length).toBeGreaterThan(0);
327
- expect(result.issues.invalidReferences.length).toBeGreaterThan(0);
328
- expect(result.issues.circularDependencies.length).toBeGreaterThan(0);
329
- expect(result.summary).toContain("self-dependencies");
330
- expect(result.summary).toContain("invalid references");
331
- expect(result.summary).toContain("circular dependency");
332
- });
333
-
334
- test("handles empty task array", () => {
335
- const result = checkDependencyIntegrity([]);
336
- expect(result.valid).toBe(true);
337
- expect(result.totalTasks).toBe(0);
338
- expect(result.totalDependencies).toBe(0);
339
- });
340
-
341
- test("handles tasks with no dependencies", () => {
342
- const tasks = [createTask("A"), createTask("B"), createTask("C")];
343
- const result = checkDependencyIntegrity(tasks);
344
- expect(result.valid).toBe(true);
345
- expect(result.totalTasks).toBe(3);
346
- expect(result.totalDependencies).toBe(0);
347
- });
348
- });