octie-cli 1.0.0
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.
- package/README.md +523 -0
- package/dist/cli/commands/approve.d.ts +27 -0
- package/dist/cli/commands/approve.d.ts.map +1 -0
- package/dist/cli/commands/approve.js +119 -0
- package/dist/cli/commands/approve.js.map +1 -0
- package/dist/cli/commands/batch.d.ts +15 -0
- package/dist/cli/commands/batch.d.ts.map +1 -0
- package/dist/cli/commands/batch.js +521 -0
- package/dist/cli/commands/batch.js.map +1 -0
- package/dist/cli/commands/create.d.ts +9 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +321 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +9 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +143 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/export.d.ts +9 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +66 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/find.d.ts +16 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +252 -0
- package/dist/cli/commands/find.js.map +1 -0
- package/dist/cli/commands/get.d.ts +9 -0
- package/dist/cli/commands/get.d.ts.map +1 -0
- package/dist/cli/commands/get.js +74 -0
- package/dist/cli/commands/get.js.map +1 -0
- package/dist/cli/commands/graph.d.ts +9 -0
- package/dist/cli/commands/graph.d.ts.map +1 -0
- package/dist/cli/commands/graph.js +200 -0
- package/dist/cli/commands/graph.js.map +1 -0
- package/dist/cli/commands/import.d.ts +9 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +807 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +57 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +9 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +175 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/merge.d.ts +9 -0
- package/dist/cli/commands/merge.d.ts.map +1 -0
- package/dist/cli/commands/merge.js +113 -0
- package/dist/cli/commands/merge.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +9 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +94 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/update.d.ts +9 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +423 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/wire.d.ts +15 -0
- package/dist/cli/commands/wire.d.ts.map +1 -0
- package/dist/cli/commands/wire.js +164 -0
- package/dist/cli/commands/wire.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +100 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output/json.d.ts +16 -0
- package/dist/cli/output/json.d.ts.map +1 -0
- package/dist/cli/output/json.js +29 -0
- package/dist/cli/output/json.js.map +1 -0
- package/dist/cli/output/markdown.d.ts +15 -0
- package/dist/cli/output/markdown.d.ts.map +1 -0
- package/dist/cli/output/markdown.js +206 -0
- package/dist/cli/output/markdown.js.map +1 -0
- package/dist/cli/output/table.d.ts +23 -0
- package/dist/cli/output/table.d.ts.map +1 -0
- package/dist/cli/output/table.js +150 -0
- package/dist/cli/output/table.js.map +1 -0
- package/dist/cli/utils/helpers.d.ts +126 -0
- package/dist/cli/utils/helpers.d.ts.map +1 -0
- package/dist/cli/utils/helpers.js +325 -0
- package/dist/cli/utils/helpers.js.map +1 -0
- package/dist/core/graph/algorithms.d.ts +11 -0
- package/dist/core/graph/algorithms.d.ts.map +1 -0
- package/dist/core/graph/algorithms.js +14 -0
- package/dist/core/graph/algorithms.js.map +1 -0
- package/dist/core/graph/cycle.d.ts +155 -0
- package/dist/core/graph/cycle.d.ts.map +1 -0
- package/dist/core/graph/cycle.js +297 -0
- package/dist/core/graph/cycle.js.map +1 -0
- package/dist/core/graph/index.d.ts +223 -0
- package/dist/core/graph/index.d.ts.map +1 -0
- package/dist/core/graph/index.js +475 -0
- package/dist/core/graph/index.js.map +1 -0
- package/dist/core/graph/operations.d.ts +240 -0
- package/dist/core/graph/operations.d.ts.map +1 -0
- package/dist/core/graph/operations.js +503 -0
- package/dist/core/graph/operations.js.map +1 -0
- package/dist/core/graph/sort.d.ts +76 -0
- package/dist/core/graph/sort.d.ts.map +1 -0
- package/dist/core/graph/sort.js +254 -0
- package/dist/core/graph/sort.js.map +1 -0
- package/dist/core/graph/traversal.d.ts +122 -0
- package/dist/core/graph/traversal.d.ts.map +1 -0
- package/dist/core/graph/traversal.js +336 -0
- package/dist/core/graph/traversal.js.map +1 -0
- package/dist/core/models/task-node.d.ts +328 -0
- package/dist/core/models/task-node.d.ts.map +1 -0
- package/dist/core/models/task-node.js +1090 -0
- package/dist/core/models/task-node.js.map +1 -0
- package/dist/core/registry/index.d.ts +102 -0
- package/dist/core/registry/index.d.ts.map +1 -0
- package/dist/core/registry/index.js +249 -0
- package/dist/core/registry/index.js.map +1 -0
- package/dist/core/registry/root-guard.d.ts +19 -0
- package/dist/core/registry/root-guard.d.ts.map +1 -0
- package/dist/core/registry/root-guard.js +28 -0
- package/dist/core/registry/root-guard.js.map +1 -0
- package/dist/core/storage/atomic-write.d.ts +181 -0
- package/dist/core/storage/atomic-write.d.ts.map +1 -0
- package/dist/core/storage/atomic-write.js +379 -0
- package/dist/core/storage/atomic-write.js.map +1 -0
- package/dist/core/storage/file-store.d.ts +148 -0
- package/dist/core/storage/file-store.d.ts.map +1 -0
- package/dist/core/storage/file-store.js +423 -0
- package/dist/core/storage/file-store.js.map +1 -0
- package/dist/core/storage/indexer.d.ts +138 -0
- package/dist/core/storage/indexer.d.ts.map +1 -0
- package/dist/core/storage/indexer.js +350 -0
- package/dist/core/storage/indexer.js.map +1 -0
- package/dist/core/utils/status-helpers.d.ts +59 -0
- package/dist/core/utils/status-helpers.d.ts.map +1 -0
- package/dist/core/utils/status-helpers.js +149 -0
- package/dist/core/utils/status-helpers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +504 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +182 -0
- package/dist/types/index.js.map +1 -0
- package/dist/web/routes/graph.d.ts +17 -0
- package/dist/web/routes/graph.d.ts.map +1 -0
- package/dist/web/routes/graph.js +277 -0
- package/dist/web/routes/graph.js.map +1 -0
- package/dist/web/routes/projects.d.ts +14 -0
- package/dist/web/routes/projects.d.ts.map +1 -0
- package/dist/web/routes/projects.js +102 -0
- package/dist/web/routes/projects.js.map +1 -0
- package/dist/web/routes/tasks.d.ts +17 -0
- package/dist/web/routes/tasks.d.ts.map +1 -0
- package/dist/web/routes/tasks.js +538 -0
- package/dist/web/routes/tasks.js.map +1 -0
- package/dist/web/server.d.ts +121 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +389 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web-ui/assets/index-BB0qvF1y.css +1 -0
- package/dist/web-ui/assets/index-Vmm72oKY.js +34 -0
- package/dist/web-ui/index.html +14 -0
- package/dist/web-ui/vite.svg +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph traversal algorithms
|
|
3
|
+
*
|
|
4
|
+
* Implements BFS and DFS traversal methods for path finding and
|
|
5
|
+
* reachable node discovery.
|
|
6
|
+
* Time complexity: O(V + E) where V = vertices, E = edges
|
|
7
|
+
*
|
|
8
|
+
* @module core/graph/traversal
|
|
9
|
+
*/
|
|
10
|
+
import { TaskNotFoundError } from '../../types/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Breadth-First Search traversal
|
|
13
|
+
*
|
|
14
|
+
* Explores nodes layer by layer, finding all reachable nodes from a start node.
|
|
15
|
+
* Useful for finding all descendants (forward) or ancestors (backward).
|
|
16
|
+
*
|
|
17
|
+
* Time Complexity: O(V + E) in worst case
|
|
18
|
+
* Space Complexity: O(V) for visited set and queue
|
|
19
|
+
*
|
|
20
|
+
* @param graph - Task graph store
|
|
21
|
+
* @param startId - Starting task ID
|
|
22
|
+
* @param direction - Traversal direction: 'forward' (outgoing) or 'backward' (incoming)
|
|
23
|
+
* @returns Array of reachable task IDs in order of discovery
|
|
24
|
+
* @throws {TaskNotFoundError} If start node doesn't exist
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* // Find all tasks that depend on the start task
|
|
29
|
+
* const descendants = bfsTraversal(graph, 'task-001', 'forward');
|
|
30
|
+
*
|
|
31
|
+
* // Find all tasks that the start task depends on
|
|
32
|
+
* const ancestors = bfsTraversal(graph, 'task-001', 'backward');
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function bfsTraversal(graph, startId, direction = 'forward') {
|
|
36
|
+
// Validate start node exists
|
|
37
|
+
if (!graph.hasNode(startId)) {
|
|
38
|
+
throw new TaskNotFoundError(startId);
|
|
39
|
+
}
|
|
40
|
+
const visited = new Set();
|
|
41
|
+
const queue = [startId];
|
|
42
|
+
const result = [];
|
|
43
|
+
/**
|
|
44
|
+
* Get neighbors based on traversal direction
|
|
45
|
+
* @param id - Task ID
|
|
46
|
+
* @returns Array of neighbor task IDs
|
|
47
|
+
*/
|
|
48
|
+
const getNeighbors = (id) => {
|
|
49
|
+
return direction === 'forward'
|
|
50
|
+
? graph.getOutgoingEdges(id)
|
|
51
|
+
: graph.getIncomingEdges(id);
|
|
52
|
+
};
|
|
53
|
+
while (queue.length > 0) {
|
|
54
|
+
// Dequeue next node
|
|
55
|
+
const nodeId = queue.shift();
|
|
56
|
+
// Skip if already visited
|
|
57
|
+
if (visited.has(nodeId)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// Mark as visited and add to result
|
|
61
|
+
visited.add(nodeId);
|
|
62
|
+
result.push(nodeId);
|
|
63
|
+
// Enqueue all unvisited neighbors
|
|
64
|
+
const neighbors = getNeighbors(nodeId);
|
|
65
|
+
for (const neighbor of neighbors) {
|
|
66
|
+
if (!visited.has(neighbor)) {
|
|
67
|
+
queue.push(neighbor);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Depth-First Search to find path between two nodes
|
|
75
|
+
*
|
|
76
|
+
* Attempts to find a path from start to end using DFS with backtracking.
|
|
77
|
+
* Returns the first path found, or null if no path exists.
|
|
78
|
+
*
|
|
79
|
+
* Time Complexity: O(V + E) in worst case
|
|
80
|
+
* Space Complexity: O(V) for recursion stack and visited set
|
|
81
|
+
*
|
|
82
|
+
* @param graph - Task graph store
|
|
83
|
+
* @param startId - Starting task ID
|
|
84
|
+
* @param endId - Target task ID
|
|
85
|
+
* @param direction - Search direction: 'forward' (follow outgoing) or 'backward' (follow incoming)
|
|
86
|
+
* @returns Path array from start to end, or null if no path exists
|
|
87
|
+
* @throws {TaskNotFoundError} If either node doesn't exist
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* // Find path from task-001 to task-005
|
|
92
|
+
* const path = dfsFindPath(graph, 'task-001', 'task-005');
|
|
93
|
+
* if (path) {
|
|
94
|
+
* console.log('Path:', path.join(' -> '));
|
|
95
|
+
* // Output: Path: task-001 -> task-002 -> task-004 -> task-005
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export function dfsFindPath(graph, startId, endId, direction = 'forward') {
|
|
100
|
+
// Validate both nodes exist
|
|
101
|
+
if (!graph.hasNode(startId)) {
|
|
102
|
+
throw new TaskNotFoundError(startId);
|
|
103
|
+
}
|
|
104
|
+
if (!graph.hasNode(endId)) {
|
|
105
|
+
throw new TaskNotFoundError(endId);
|
|
106
|
+
}
|
|
107
|
+
const visited = new Set();
|
|
108
|
+
const path = [];
|
|
109
|
+
/**
|
|
110
|
+
* Get neighbors based on search direction
|
|
111
|
+
* @param id - Task ID
|
|
112
|
+
* @returns Array of neighbor task IDs
|
|
113
|
+
*/
|
|
114
|
+
const getNeighbors = (id) => {
|
|
115
|
+
return direction === 'forward'
|
|
116
|
+
? graph.getOutgoingEdges(id)
|
|
117
|
+
: graph.getIncomingEdges(id);
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Recursive DFS with backtracking
|
|
121
|
+
* @param currentId - Current node being visited
|
|
122
|
+
* @returns true if path was found
|
|
123
|
+
*/
|
|
124
|
+
function dfs(currentId) {
|
|
125
|
+
// Skip if already visited
|
|
126
|
+
if (visited.has(currentId)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
// Mark as visited and add to path
|
|
130
|
+
visited.add(currentId);
|
|
131
|
+
path.push(currentId);
|
|
132
|
+
// Check if we found the target
|
|
133
|
+
if (currentId === endId) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
// Recursively search neighbors
|
|
137
|
+
const neighbors = getNeighbors(currentId);
|
|
138
|
+
for (const neighbor of neighbors) {
|
|
139
|
+
if (dfs(neighbor)) {
|
|
140
|
+
return true; // Path found, propagate success
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Backtrack: remove from path
|
|
144
|
+
path.pop();
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
return dfs(startId) ? path : null;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Find all paths between two nodes
|
|
151
|
+
*
|
|
152
|
+
* Uses DFS to find all possible paths from start to end.
|
|
153
|
+
* Warning: Can be expensive on dense graphs with many paths.
|
|
154
|
+
*
|
|
155
|
+
* @param graph - Task graph store
|
|
156
|
+
* @param startId - Starting task ID
|
|
157
|
+
* @param endId - Target task ID
|
|
158
|
+
* @param direction - Search direction: 'forward' or 'backward'
|
|
159
|
+
* @param maxPaths - Maximum number of paths to find (default: 100, prevents explosion)
|
|
160
|
+
* @returns Array of paths (each path is an array of task IDs)
|
|
161
|
+
* @throws {TaskNotFoundError} If either node doesn't exist
|
|
162
|
+
*/
|
|
163
|
+
export function findAllPaths(graph, startId, endId, direction = 'forward', maxPaths = 100) {
|
|
164
|
+
// Validate both nodes exist
|
|
165
|
+
if (!graph.hasNode(startId)) {
|
|
166
|
+
throw new TaskNotFoundError(startId);
|
|
167
|
+
}
|
|
168
|
+
if (!graph.hasNode(endId)) {
|
|
169
|
+
throw new TaskNotFoundError(endId);
|
|
170
|
+
}
|
|
171
|
+
const allPaths = [];
|
|
172
|
+
const visited = new Set();
|
|
173
|
+
const currentPath = [];
|
|
174
|
+
/**
|
|
175
|
+
* Get neighbors based on search direction
|
|
176
|
+
*/
|
|
177
|
+
const getNeighbors = (id) => {
|
|
178
|
+
return direction === 'forward'
|
|
179
|
+
? graph.getOutgoingEdges(id)
|
|
180
|
+
: graph.getIncomingEdges(id);
|
|
181
|
+
};
|
|
182
|
+
/**
|
|
183
|
+
* Recursive DFS to find all paths
|
|
184
|
+
*/
|
|
185
|
+
function dfs(currentId) {
|
|
186
|
+
// Early exit if we found enough paths
|
|
187
|
+
if (allPaths.length >= maxPaths) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// Mark as visited and add to current path
|
|
191
|
+
visited.add(currentId);
|
|
192
|
+
currentPath.push(currentId);
|
|
193
|
+
// Check if we found the target
|
|
194
|
+
if (currentId === endId) {
|
|
195
|
+
allPaths.push([...currentPath]);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// Continue searching neighbors
|
|
199
|
+
for (const neighbor of getNeighbors(currentId)) {
|
|
200
|
+
if (!visited.has(neighbor)) {
|
|
201
|
+
dfs(neighbor);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Backtrack
|
|
206
|
+
currentPath.pop();
|
|
207
|
+
visited.delete(currentId);
|
|
208
|
+
}
|
|
209
|
+
dfs(startId);
|
|
210
|
+
return allPaths;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get shortest path between two nodes using BFS
|
|
214
|
+
*
|
|
215
|
+
* BFS naturally finds the shortest path in unweighted graphs.
|
|
216
|
+
*
|
|
217
|
+
* @param graph - Task graph store
|
|
218
|
+
* @param startId - Starting task ID
|
|
219
|
+
* @param endId - Target task ID
|
|
220
|
+
* @param direction - Search direction: 'forward' or 'backward'
|
|
221
|
+
* @returns Shortest path array, or null if no path exists
|
|
222
|
+
* @throws {TaskNotFoundError} If either node doesn't exist
|
|
223
|
+
*/
|
|
224
|
+
export function findShortestPath(graph, startId, endId, direction = 'forward') {
|
|
225
|
+
// Validate both nodes exist
|
|
226
|
+
if (!graph.hasNode(startId)) {
|
|
227
|
+
throw new TaskNotFoundError(startId);
|
|
228
|
+
}
|
|
229
|
+
if (!graph.hasNode(endId)) {
|
|
230
|
+
throw new TaskNotFoundError(endId);
|
|
231
|
+
}
|
|
232
|
+
if (startId === endId) {
|
|
233
|
+
return [startId];
|
|
234
|
+
}
|
|
235
|
+
const visited = new Set([startId]);
|
|
236
|
+
const queue = [
|
|
237
|
+
{ nodeId: startId, path: [startId] },
|
|
238
|
+
];
|
|
239
|
+
/**
|
|
240
|
+
* Get neighbors based on search direction
|
|
241
|
+
*/
|
|
242
|
+
const getNeighbors = (id) => {
|
|
243
|
+
return direction === 'forward'
|
|
244
|
+
? graph.getOutgoingEdges(id)
|
|
245
|
+
: graph.getIncomingEdges(id);
|
|
246
|
+
};
|
|
247
|
+
while (queue.length > 0) {
|
|
248
|
+
const { nodeId, path } = queue.shift();
|
|
249
|
+
for (const neighbor of getNeighbors(nodeId)) {
|
|
250
|
+
if (neighbor === endId) {
|
|
251
|
+
return [...path, neighbor];
|
|
252
|
+
}
|
|
253
|
+
if (!visited.has(neighbor)) {
|
|
254
|
+
visited.add(neighbor);
|
|
255
|
+
queue.push({ nodeId: neighbor, path: [...path, neighbor] });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return null; // No path found
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Check if two nodes are connected (path exists)
|
|
263
|
+
*
|
|
264
|
+
* @param graph - Task graph store
|
|
265
|
+
* @param fromId - Source task ID
|
|
266
|
+
* @param toId - Target task ID
|
|
267
|
+
* @param direction - Search direction: 'forward' or 'backward'
|
|
268
|
+
* @returns true if a path exists between the nodes
|
|
269
|
+
*/
|
|
270
|
+
export function areConnected(graph, fromId, toId, direction = 'forward') {
|
|
271
|
+
try {
|
|
272
|
+
const path = findShortestPath(graph, fromId, toId, direction);
|
|
273
|
+
return path !== null;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Get distance (number of edges) between two nodes
|
|
281
|
+
*
|
|
282
|
+
* @param graph - Task graph store
|
|
283
|
+
* @param fromId - Source task ID
|
|
284
|
+
* @param toId - Target task ID
|
|
285
|
+
* @param direction - Search direction: 'forward' or 'backward'
|
|
286
|
+
* @returns Number of edges in shortest path, or -1 if no path exists
|
|
287
|
+
*/
|
|
288
|
+
export function getDistance(graph, fromId, toId, direction = 'forward') {
|
|
289
|
+
const path = findShortestPath(graph, fromId, toId, direction);
|
|
290
|
+
return path ? path.length - 1 : -1;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Get connected components in the graph
|
|
294
|
+
*
|
|
295
|
+
* Identifies groups of nodes that are reachable from each other.
|
|
296
|
+
* For directed graphs, uses weakly connected components
|
|
297
|
+
* (treating edges as undirected).
|
|
298
|
+
*
|
|
299
|
+
* @param graph - Task graph store
|
|
300
|
+
* @returns Array of connected components (each is an array of task IDs)
|
|
301
|
+
*/
|
|
302
|
+
export function getConnectedComponents(graph) {
|
|
303
|
+
const visited = new Set();
|
|
304
|
+
const components = [];
|
|
305
|
+
/**
|
|
306
|
+
* Get all neighbors (both incoming and outgoing) for undirected traversal
|
|
307
|
+
*/
|
|
308
|
+
const getAllNeighbors = (id) => {
|
|
309
|
+
const outgoing = graph.getOutgoingEdges(id);
|
|
310
|
+
const incoming = graph.getIncomingEdges(id);
|
|
311
|
+
return [...new Set([...outgoing, ...incoming])];
|
|
312
|
+
};
|
|
313
|
+
for (const taskId of graph.getAllTaskIds()) {
|
|
314
|
+
if (!visited.has(taskId)) {
|
|
315
|
+
// Start a new component
|
|
316
|
+
const component = [];
|
|
317
|
+
const queue = [taskId];
|
|
318
|
+
while (queue.length > 0) {
|
|
319
|
+
const nodeId = queue.shift();
|
|
320
|
+
if (visited.has(nodeId)) {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
visited.add(nodeId);
|
|
324
|
+
component.push(nodeId);
|
|
325
|
+
for (const neighbor of getAllNeighbors(nodeId)) {
|
|
326
|
+
if (!visited.has(neighbor)) {
|
|
327
|
+
queue.push(neighbor);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
components.push(component);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return components;
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=traversal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traversal.js","sourceRoot":"","sources":["../../../src/core/graph/traversal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Node Model
|
|
3
|
+
*
|
|
4
|
+
* Implements the TaskNode class with:
|
|
5
|
+
* - Required field validation
|
|
6
|
+
* - Atomic task validation
|
|
7
|
+
* - Auto-timestamp management (created_at, updated_at, completed_at)
|
|
8
|
+
* - Status transition validation
|
|
9
|
+
* - Success criteria and deliverable tracking
|
|
10
|
+
*
|
|
11
|
+
* @module core/models/task-node
|
|
12
|
+
*/
|
|
13
|
+
import type { TaskNode as TaskNodeType, TaskStatus, TaskPriority, SuccessCriterion, Deliverable, C7Verification, FixItem } from '../../types/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Validate atomic task requirements
|
|
16
|
+
*
|
|
17
|
+
* Atomic tasks MUST be:
|
|
18
|
+
* - Specific (clear, focused purpose)
|
|
19
|
+
* - Executable (can be completed in 2-8 hours typical, max 2 days)
|
|
20
|
+
* - Verifiable (has quantitative success criteria)
|
|
21
|
+
* - Independent (minimizes dependencies)
|
|
22
|
+
*
|
|
23
|
+
* @param taskData - Task data to validate
|
|
24
|
+
* @throws {AtomicTaskViolationError} If task violates atomic requirements
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateAtomicTask(taskData: {
|
|
27
|
+
title: string;
|
|
28
|
+
description: string;
|
|
29
|
+
success_criteria: SuccessCriterion[];
|
|
30
|
+
deliverables: Deliverable[];
|
|
31
|
+
}): void;
|
|
32
|
+
/**
|
|
33
|
+
* Task Node Class
|
|
34
|
+
*
|
|
35
|
+
* Represents a single task in the graph with:
|
|
36
|
+
* - Auto-managed timestamps (created_at, updated_at, completed_at)
|
|
37
|
+
* - Required field validation at creation
|
|
38
|
+
* - Atomic task validation
|
|
39
|
+
* - Status transition validation
|
|
40
|
+
* - Private setters to prevent manual timestamp manipulation
|
|
41
|
+
*/
|
|
42
|
+
export declare class TaskNode implements TaskNodeType {
|
|
43
|
+
readonly id: string;
|
|
44
|
+
title: string;
|
|
45
|
+
description: string;
|
|
46
|
+
status: TaskStatus;
|
|
47
|
+
priority: TaskPriority;
|
|
48
|
+
success_criteria: SuccessCriterion[];
|
|
49
|
+
deliverables: Deliverable[];
|
|
50
|
+
/** Blocking issues that must be resolved before review (equal importance to criteria/deliverables) */
|
|
51
|
+
need_fix: FixItem[];
|
|
52
|
+
/** Optional agent/session that owns this task (decoupled from status) */
|
|
53
|
+
assignee: string | null;
|
|
54
|
+
blockers: string[];
|
|
55
|
+
/** Explanatory text describing WHY this task depends on its blockers */
|
|
56
|
+
dependencies: string;
|
|
57
|
+
sub_items: string[];
|
|
58
|
+
related_files: string[];
|
|
59
|
+
notes: string;
|
|
60
|
+
c7_verified: C7Verification[];
|
|
61
|
+
private _created_at;
|
|
62
|
+
private _updated_at;
|
|
63
|
+
private _completed_at;
|
|
64
|
+
edges: string[];
|
|
65
|
+
/**
|
|
66
|
+
* Get the creation timestamp (immutable)
|
|
67
|
+
*/
|
|
68
|
+
get created_at(): string;
|
|
69
|
+
/**
|
|
70
|
+
* Get the last update timestamp (auto-managed)
|
|
71
|
+
*/
|
|
72
|
+
get updated_at(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Get the completion timestamp (auto-managed, null if not complete)
|
|
75
|
+
*/
|
|
76
|
+
get completed_at(): string | null;
|
|
77
|
+
/**
|
|
78
|
+
* Create a new TaskNode
|
|
79
|
+
*
|
|
80
|
+
* @param data - Task data (title, description, success_criteria, deliverables are REQUIRED)
|
|
81
|
+
* @param _skipAtomicValidation - Private: skip atomic validation (used only by fromJSON for deserialization)
|
|
82
|
+
* @throws {ValidationError} If required fields are missing or invalid
|
|
83
|
+
* @throws {AtomicTaskViolationError} If task violates atomic requirements
|
|
84
|
+
*/
|
|
85
|
+
constructor(data: {
|
|
86
|
+
title?: string;
|
|
87
|
+
description?: string;
|
|
88
|
+
status?: TaskStatus;
|
|
89
|
+
priority?: TaskPriority;
|
|
90
|
+
success_criteria?: SuccessCriterion[];
|
|
91
|
+
deliverables?: Deliverable[];
|
|
92
|
+
need_fix?: FixItem[];
|
|
93
|
+
assignee?: string | null;
|
|
94
|
+
blockers?: string[];
|
|
95
|
+
/** Explanatory text describing WHY this task depends on its blockers */
|
|
96
|
+
dependencies?: string;
|
|
97
|
+
sub_items?: string[];
|
|
98
|
+
related_files?: string[];
|
|
99
|
+
notes?: string;
|
|
100
|
+
c7_verified?: C7Verification[];
|
|
101
|
+
id?: string;
|
|
102
|
+
edges?: string[];
|
|
103
|
+
created_at?: string;
|
|
104
|
+
updated_at?: string;
|
|
105
|
+
completed_at?: string | null;
|
|
106
|
+
_skipAtomicValidation?: boolean;
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* Update the task title
|
|
110
|
+
* @param title - New title
|
|
111
|
+
*/
|
|
112
|
+
setTitle(title: string): void;
|
|
113
|
+
/**
|
|
114
|
+
* Update the task description
|
|
115
|
+
* @param description - New description
|
|
116
|
+
*/
|
|
117
|
+
setDescription(description: string): void;
|
|
118
|
+
/**
|
|
119
|
+
* Update the task status
|
|
120
|
+
* @param status - New status
|
|
121
|
+
*/
|
|
122
|
+
setStatus(status: TaskStatus): void;
|
|
123
|
+
/**
|
|
124
|
+
* Update the task priority
|
|
125
|
+
* @param priority - New priority
|
|
126
|
+
*/
|
|
127
|
+
setPriority(priority: TaskPriority): void;
|
|
128
|
+
/**
|
|
129
|
+
* Add a success criterion
|
|
130
|
+
* @param criterion - Success criterion to add
|
|
131
|
+
*/
|
|
132
|
+
addSuccessCriterion(criterion: SuccessCriterion): void;
|
|
133
|
+
/**
|
|
134
|
+
* Mark a success criterion as complete
|
|
135
|
+
* @param criterionId - ID of the criterion to mark complete
|
|
136
|
+
*/
|
|
137
|
+
completeCriterion(criterionId: string): void;
|
|
138
|
+
/**
|
|
139
|
+
* Unmark a success criterion as complete
|
|
140
|
+
* @param criterionId - ID of the criterion to unmark
|
|
141
|
+
* @throws {ImmutabilityViolationError} If criterion is already completed (immutable)
|
|
142
|
+
*/
|
|
143
|
+
uncompleteCriterion(criterionId: string): void;
|
|
144
|
+
/**
|
|
145
|
+
* Add a deliverable
|
|
146
|
+
* @param deliverable - Deliverable to add
|
|
147
|
+
*/
|
|
148
|
+
addDeliverable(deliverable: Deliverable): void;
|
|
149
|
+
/**
|
|
150
|
+
* Mark a deliverable as complete
|
|
151
|
+
* @param deliverableId - ID of the deliverable to mark complete
|
|
152
|
+
*/
|
|
153
|
+
completeDeliverable(deliverableId: string): void;
|
|
154
|
+
/**
|
|
155
|
+
* Unmark a deliverable as complete
|
|
156
|
+
* @param deliverableId - ID of the deliverable to unmark
|
|
157
|
+
* @throws {ImmutabilityViolationError} If deliverable is already completed (immutable)
|
|
158
|
+
*/
|
|
159
|
+
uncompleteDeliverable(deliverableId: string): void;
|
|
160
|
+
/**
|
|
161
|
+
* Add a need_fix item
|
|
162
|
+
* Need_fix items are blocking issues that must be resolved before review
|
|
163
|
+
* @param text - Description of what needs to be fixed
|
|
164
|
+
* @param options - Optional file_path and source
|
|
165
|
+
*/
|
|
166
|
+
addNeedFix(text: string, options?: {
|
|
167
|
+
file_path?: string;
|
|
168
|
+
source?: FixItem['source'];
|
|
169
|
+
}): void;
|
|
170
|
+
/**
|
|
171
|
+
* Mark a need_fix item as complete
|
|
172
|
+
* @param fixId - ID of the need_fix item to mark complete
|
|
173
|
+
*/
|
|
174
|
+
completeNeedFix(fixId: string): void;
|
|
175
|
+
/**
|
|
176
|
+
* Set the assignee for this task
|
|
177
|
+
* Assignee is decoupled from status - just a placeholder for future team management
|
|
178
|
+
* @param agentId - Agent/session ID, or null to clear
|
|
179
|
+
*/
|
|
180
|
+
setAssignee(agentId: string | null): void;
|
|
181
|
+
/**
|
|
182
|
+
* Add a blocker task ID
|
|
183
|
+
* @param blockerId - Task ID that blocks this task
|
|
184
|
+
*/
|
|
185
|
+
addBlocker(blockerId: string): void;
|
|
186
|
+
/**
|
|
187
|
+
* Remove a blocker task ID
|
|
188
|
+
* @param blockerId - Task ID to remove from blockers
|
|
189
|
+
*/
|
|
190
|
+
removeBlocker(blockerId: string): void;
|
|
191
|
+
/**
|
|
192
|
+
* Set the dependencies explanation text (twin to blockers)
|
|
193
|
+
* @param explanation - Explanatory text describing WHY this task depends on its blockers
|
|
194
|
+
*/
|
|
195
|
+
setDependencies(explanation: string): void;
|
|
196
|
+
/**
|
|
197
|
+
* Clear the dependencies explanation text
|
|
198
|
+
* Typically called when removing the last blocker
|
|
199
|
+
*/
|
|
200
|
+
clearDependencies(): void;
|
|
201
|
+
/**
|
|
202
|
+
* Remove a success criterion
|
|
203
|
+
* @param criterionId - ID of the criterion to remove
|
|
204
|
+
* @throws {ValidationError} If criterion not found or removal would leave no criteria
|
|
205
|
+
* @throws {ImmutabilityViolationError} If criterion is completed (immutable)
|
|
206
|
+
*/
|
|
207
|
+
removeSuccessCriterion(criterionId: string): void;
|
|
208
|
+
/**
|
|
209
|
+
* Remove a deliverable
|
|
210
|
+
* @param deliverableId - ID of the deliverable to remove
|
|
211
|
+
* @throws {ValidationError} If deliverable not found or removal would leave no deliverables
|
|
212
|
+
* @throws {ImmutabilityViolationError} If deliverable is completed (immutable)
|
|
213
|
+
*/
|
|
214
|
+
removeDeliverable(deliverableId: string): void;
|
|
215
|
+
/**
|
|
216
|
+
* Remove a related file path
|
|
217
|
+
* @param filePath - File path to remove
|
|
218
|
+
*/
|
|
219
|
+
removeRelatedFile(filePath: string): void;
|
|
220
|
+
/**
|
|
221
|
+
* Remove a C7 verification entry
|
|
222
|
+
* @param libraryId - Library ID to remove from C7 verifications
|
|
223
|
+
*/
|
|
224
|
+
removeC7Verification(libraryId: string): void;
|
|
225
|
+
/**
|
|
226
|
+
* Add a related file path
|
|
227
|
+
* @param filePath - File path relative to project root
|
|
228
|
+
*/
|
|
229
|
+
addRelatedFile(filePath: string): void;
|
|
230
|
+
/**
|
|
231
|
+
* Append notes
|
|
232
|
+
* @param notes - Notes to append
|
|
233
|
+
*/
|
|
234
|
+
appendNotes(notes: string): void;
|
|
235
|
+
/**
|
|
236
|
+
* Add C7 verification
|
|
237
|
+
* @param verification - C7 verification entry
|
|
238
|
+
*/
|
|
239
|
+
addC7Verification(verification: C7Verification): void;
|
|
240
|
+
/**
|
|
241
|
+
* Add an outgoing edge
|
|
242
|
+
* @param taskId - Task ID this task points to
|
|
243
|
+
*/
|
|
244
|
+
addEdge(taskId: string): void;
|
|
245
|
+
/**
|
|
246
|
+
* Remove an outgoing edge
|
|
247
|
+
* @param taskId - Task ID to remove from edges
|
|
248
|
+
*/
|
|
249
|
+
removeEdge(taskId: string): void;
|
|
250
|
+
/**
|
|
251
|
+
* Add a sub-item task ID
|
|
252
|
+
* @param subItemId - Child task ID
|
|
253
|
+
*/
|
|
254
|
+
addSubItem(subItemId: string): void;
|
|
255
|
+
/**
|
|
256
|
+
* Remove a sub-item task ID
|
|
257
|
+
* @param subItemId - Child task ID to remove
|
|
258
|
+
*/
|
|
259
|
+
removeSubItem(subItemId: string): void;
|
|
260
|
+
/**
|
|
261
|
+
* Check if the task is complete (ready for review)
|
|
262
|
+
* All three must be complete: success_criteria, deliverables, and need_fix
|
|
263
|
+
* @returns True if all success criteria, deliverables, and need_fix items are complete
|
|
264
|
+
* @private
|
|
265
|
+
*/
|
|
266
|
+
private _isComplete;
|
|
267
|
+
/**
|
|
268
|
+
* Update completed_at timestamp and status based on completion state
|
|
269
|
+
* Called automatically after any change to success_criteria, deliverables, or need_fix
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
private _checkCompletion;
|
|
273
|
+
/**
|
|
274
|
+
* Update the updated_at timestamp
|
|
275
|
+
* Called automatically after any field change
|
|
276
|
+
* @private
|
|
277
|
+
*/
|
|
278
|
+
private _touch;
|
|
279
|
+
/**
|
|
280
|
+
* Calculate the derived status based on task state
|
|
281
|
+
*
|
|
282
|
+
* Status is DERIVED from state, not set directly:
|
|
283
|
+
* Priority order: blocked > in_review > in_progress > ready
|
|
284
|
+
*
|
|
285
|
+
* Rules:
|
|
286
|
+
* 1. Has unresolved blockers → 'blocked'
|
|
287
|
+
* 2. All criteria + deliverables + need_fix complete → 'in_review'
|
|
288
|
+
* 3. Any item checked OR need_fix exists → 'in_progress'
|
|
289
|
+
* 4. Default → 'ready'
|
|
290
|
+
*
|
|
291
|
+
* NOTE: This is a pure calculation function. It does NOT modify status.
|
|
292
|
+
* Use recalculateStatus() to apply the calculated status.
|
|
293
|
+
*
|
|
294
|
+
* @returns The calculated status based on current task state
|
|
295
|
+
*/
|
|
296
|
+
calculateStatus(): TaskStatus;
|
|
297
|
+
/**
|
|
298
|
+
* Recalculate and update status based on task state
|
|
299
|
+
* This is the main method to call when task state changes
|
|
300
|
+
*
|
|
301
|
+
* Special cases:
|
|
302
|
+
* - completed tasks with new need_fix items → in_progress (regression)
|
|
303
|
+
* - completed tasks with new blockers → blocked (regression)
|
|
304
|
+
* - Otherwise, completed status is preserved (requires manual approve())
|
|
305
|
+
*
|
|
306
|
+
* @returns The new status (may be same as current)
|
|
307
|
+
*/
|
|
308
|
+
recalculateStatus(): TaskStatus;
|
|
309
|
+
/**
|
|
310
|
+
* Approve a task that is in review
|
|
311
|
+
* This is the ONLY manual status transition in the new system
|
|
312
|
+
*
|
|
313
|
+
* @throws {ValidationError} If task is not in 'in_review' status
|
|
314
|
+
*/
|
|
315
|
+
approve(): void;
|
|
316
|
+
/**
|
|
317
|
+
* Serialize the task node to plain object
|
|
318
|
+
* Useful for JSON serialization
|
|
319
|
+
*/
|
|
320
|
+
toJSON(): TaskNodeType;
|
|
321
|
+
/**
|
|
322
|
+
* Create a TaskNode from plain object
|
|
323
|
+
* Useful for JSON deserialization
|
|
324
|
+
* Skips atomic validation since task was already validated when created
|
|
325
|
+
*/
|
|
326
|
+
static fromJSON(data: TaskNodeType): TaskNode;
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=task-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-node.d.ts","sourceRoot":"","sources":["../../../src/core/models/task-node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EACV,QAAQ,IAAI,YAAY,EACxB,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,OAAO,EACR,MAAM,sBAAsB,CAAC;AAuQ9B;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IACrC,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B,GAAG,IAAI,CA8IP;AAyBD;;;;;;;;;GASG;AACH,qBAAa,QAAS,YAAW,YAAY;IAE3C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAGpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IACrC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,sGAAsG;IACtG,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,cAAc,EAAE,CAAC;IAG9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAgB;IAGrC,KAAK,EAAE,MAAM,EAAE,CAAC;IAEhB;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED;;;;;;;OAOG;gBACS,IAAI,EAAE;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,UAAU,CAAC;QACpB,QAAQ,CAAC,EAAE,YAAY,CAAC;QACxB,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,CAAC;QACtC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;QAC7B,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,wEAAwE;QACxE,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;QAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC;IA6GD;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAW7B;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAWzC;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IA+BnC;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAKzC;;;OAGG;IACH,mBAAmB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAYtD;;;OAGG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAY5C;;;;OAIG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAmB9C;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAY9C;;;OAGG;IACH,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAWhD;;;;OAIG;IACH,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAkBlD;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,GAAG,IAAI;IAe5F;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAWpC;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKzC;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQnC;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAStC;;;OAGG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAK1C;;;OAGG;IACH,iBAAiB,IAAI,IAAI;IAKzB;;;;;OAKG;IACH,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAyBjD;;;;;OAKG;IACH,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAyB9C;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQzC;;;OAGG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQ7C;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOtC;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUhC;;;OAGG;IACH,iBAAiB,CAAC,YAAY,EAAE,cAAc,GAAG,IAAI;IAKrD;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO7B;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQhC;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAOnC;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQtC;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAOnB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;OAIG;IACH,OAAO,CAAC,MAAM;IAId;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,IAAI,UAAU;IA+B7B;;;;;;;;;;OAUG;IACH,iBAAiB,IAAI,UAAU;IAuB/B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAWf;;;OAGG;IACH,MAAM,IAAI,YAAY;IAwBtB;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ;CAmC9C"}
|