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.
Files changed (162) hide show
  1. package/README.md +523 -0
  2. package/dist/cli/commands/approve.d.ts +27 -0
  3. package/dist/cli/commands/approve.d.ts.map +1 -0
  4. package/dist/cli/commands/approve.js +119 -0
  5. package/dist/cli/commands/approve.js.map +1 -0
  6. package/dist/cli/commands/batch.d.ts +15 -0
  7. package/dist/cli/commands/batch.d.ts.map +1 -0
  8. package/dist/cli/commands/batch.js +521 -0
  9. package/dist/cli/commands/batch.js.map +1 -0
  10. package/dist/cli/commands/create.d.ts +9 -0
  11. package/dist/cli/commands/create.d.ts.map +1 -0
  12. package/dist/cli/commands/create.js +321 -0
  13. package/dist/cli/commands/create.js.map +1 -0
  14. package/dist/cli/commands/delete.d.ts +9 -0
  15. package/dist/cli/commands/delete.d.ts.map +1 -0
  16. package/dist/cli/commands/delete.js +143 -0
  17. package/dist/cli/commands/delete.js.map +1 -0
  18. package/dist/cli/commands/export.d.ts +9 -0
  19. package/dist/cli/commands/export.d.ts.map +1 -0
  20. package/dist/cli/commands/export.js +66 -0
  21. package/dist/cli/commands/export.js.map +1 -0
  22. package/dist/cli/commands/find.d.ts +16 -0
  23. package/dist/cli/commands/find.d.ts.map +1 -0
  24. package/dist/cli/commands/find.js +252 -0
  25. package/dist/cli/commands/find.js.map +1 -0
  26. package/dist/cli/commands/get.d.ts +9 -0
  27. package/dist/cli/commands/get.d.ts.map +1 -0
  28. package/dist/cli/commands/get.js +74 -0
  29. package/dist/cli/commands/get.js.map +1 -0
  30. package/dist/cli/commands/graph.d.ts +9 -0
  31. package/dist/cli/commands/graph.d.ts.map +1 -0
  32. package/dist/cli/commands/graph.js +200 -0
  33. package/dist/cli/commands/graph.js.map +1 -0
  34. package/dist/cli/commands/import.d.ts +9 -0
  35. package/dist/cli/commands/import.d.ts.map +1 -0
  36. package/dist/cli/commands/import.js +807 -0
  37. package/dist/cli/commands/import.js.map +1 -0
  38. package/dist/cli/commands/init.d.ts +9 -0
  39. package/dist/cli/commands/init.d.ts.map +1 -0
  40. package/dist/cli/commands/init.js +57 -0
  41. package/dist/cli/commands/init.js.map +1 -0
  42. package/dist/cli/commands/list.d.ts +9 -0
  43. package/dist/cli/commands/list.d.ts.map +1 -0
  44. package/dist/cli/commands/list.js +175 -0
  45. package/dist/cli/commands/list.js.map +1 -0
  46. package/dist/cli/commands/merge.d.ts +9 -0
  47. package/dist/cli/commands/merge.d.ts.map +1 -0
  48. package/dist/cli/commands/merge.js +113 -0
  49. package/dist/cli/commands/merge.js.map +1 -0
  50. package/dist/cli/commands/serve.d.ts +9 -0
  51. package/dist/cli/commands/serve.d.ts.map +1 -0
  52. package/dist/cli/commands/serve.js +94 -0
  53. package/dist/cli/commands/serve.js.map +1 -0
  54. package/dist/cli/commands/update.d.ts +9 -0
  55. package/dist/cli/commands/update.d.ts.map +1 -0
  56. package/dist/cli/commands/update.js +423 -0
  57. package/dist/cli/commands/update.js.map +1 -0
  58. package/dist/cli/commands/wire.d.ts +15 -0
  59. package/dist/cli/commands/wire.d.ts.map +1 -0
  60. package/dist/cli/commands/wire.js +164 -0
  61. package/dist/cli/commands/wire.js.map +1 -0
  62. package/dist/cli/index.d.ts +7 -0
  63. package/dist/cli/index.d.ts.map +1 -0
  64. package/dist/cli/index.js +100 -0
  65. package/dist/cli/index.js.map +1 -0
  66. package/dist/cli/output/json.d.ts +16 -0
  67. package/dist/cli/output/json.d.ts.map +1 -0
  68. package/dist/cli/output/json.js +29 -0
  69. package/dist/cli/output/json.js.map +1 -0
  70. package/dist/cli/output/markdown.d.ts +15 -0
  71. package/dist/cli/output/markdown.d.ts.map +1 -0
  72. package/dist/cli/output/markdown.js +206 -0
  73. package/dist/cli/output/markdown.js.map +1 -0
  74. package/dist/cli/output/table.d.ts +23 -0
  75. package/dist/cli/output/table.d.ts.map +1 -0
  76. package/dist/cli/output/table.js +150 -0
  77. package/dist/cli/output/table.js.map +1 -0
  78. package/dist/cli/utils/helpers.d.ts +126 -0
  79. package/dist/cli/utils/helpers.d.ts.map +1 -0
  80. package/dist/cli/utils/helpers.js +325 -0
  81. package/dist/cli/utils/helpers.js.map +1 -0
  82. package/dist/core/graph/algorithms.d.ts +11 -0
  83. package/dist/core/graph/algorithms.d.ts.map +1 -0
  84. package/dist/core/graph/algorithms.js +14 -0
  85. package/dist/core/graph/algorithms.js.map +1 -0
  86. package/dist/core/graph/cycle.d.ts +155 -0
  87. package/dist/core/graph/cycle.d.ts.map +1 -0
  88. package/dist/core/graph/cycle.js +297 -0
  89. package/dist/core/graph/cycle.js.map +1 -0
  90. package/dist/core/graph/index.d.ts +223 -0
  91. package/dist/core/graph/index.d.ts.map +1 -0
  92. package/dist/core/graph/index.js +475 -0
  93. package/dist/core/graph/index.js.map +1 -0
  94. package/dist/core/graph/operations.d.ts +240 -0
  95. package/dist/core/graph/operations.d.ts.map +1 -0
  96. package/dist/core/graph/operations.js +503 -0
  97. package/dist/core/graph/operations.js.map +1 -0
  98. package/dist/core/graph/sort.d.ts +76 -0
  99. package/dist/core/graph/sort.d.ts.map +1 -0
  100. package/dist/core/graph/sort.js +254 -0
  101. package/dist/core/graph/sort.js.map +1 -0
  102. package/dist/core/graph/traversal.d.ts +122 -0
  103. package/dist/core/graph/traversal.d.ts.map +1 -0
  104. package/dist/core/graph/traversal.js +336 -0
  105. package/dist/core/graph/traversal.js.map +1 -0
  106. package/dist/core/models/task-node.d.ts +328 -0
  107. package/dist/core/models/task-node.d.ts.map +1 -0
  108. package/dist/core/models/task-node.js +1090 -0
  109. package/dist/core/models/task-node.js.map +1 -0
  110. package/dist/core/registry/index.d.ts +102 -0
  111. package/dist/core/registry/index.d.ts.map +1 -0
  112. package/dist/core/registry/index.js +249 -0
  113. package/dist/core/registry/index.js.map +1 -0
  114. package/dist/core/registry/root-guard.d.ts +19 -0
  115. package/dist/core/registry/root-guard.d.ts.map +1 -0
  116. package/dist/core/registry/root-guard.js +28 -0
  117. package/dist/core/registry/root-guard.js.map +1 -0
  118. package/dist/core/storage/atomic-write.d.ts +181 -0
  119. package/dist/core/storage/atomic-write.d.ts.map +1 -0
  120. package/dist/core/storage/atomic-write.js +379 -0
  121. package/dist/core/storage/atomic-write.js.map +1 -0
  122. package/dist/core/storage/file-store.d.ts +148 -0
  123. package/dist/core/storage/file-store.d.ts.map +1 -0
  124. package/dist/core/storage/file-store.js +423 -0
  125. package/dist/core/storage/file-store.js.map +1 -0
  126. package/dist/core/storage/indexer.d.ts +138 -0
  127. package/dist/core/storage/indexer.d.ts.map +1 -0
  128. package/dist/core/storage/indexer.js +350 -0
  129. package/dist/core/storage/indexer.js.map +1 -0
  130. package/dist/core/utils/status-helpers.d.ts +59 -0
  131. package/dist/core/utils/status-helpers.d.ts.map +1 -0
  132. package/dist/core/utils/status-helpers.js +149 -0
  133. package/dist/core/utils/status-helpers.js.map +1 -0
  134. package/dist/index.d.ts +10 -0
  135. package/dist/index.d.ts.map +1 -0
  136. package/dist/index.js +10 -0
  137. package/dist/index.js.map +1 -0
  138. package/dist/types/index.d.ts +504 -0
  139. package/dist/types/index.d.ts.map +1 -0
  140. package/dist/types/index.js +182 -0
  141. package/dist/types/index.js.map +1 -0
  142. package/dist/web/routes/graph.d.ts +17 -0
  143. package/dist/web/routes/graph.d.ts.map +1 -0
  144. package/dist/web/routes/graph.js +277 -0
  145. package/dist/web/routes/graph.js.map +1 -0
  146. package/dist/web/routes/projects.d.ts +14 -0
  147. package/dist/web/routes/projects.d.ts.map +1 -0
  148. package/dist/web/routes/projects.js +102 -0
  149. package/dist/web/routes/projects.js.map +1 -0
  150. package/dist/web/routes/tasks.d.ts +17 -0
  151. package/dist/web/routes/tasks.d.ts.map +1 -0
  152. package/dist/web/routes/tasks.js +538 -0
  153. package/dist/web/routes/tasks.js.map +1 -0
  154. package/dist/web/server.d.ts +121 -0
  155. package/dist/web/server.d.ts.map +1 -0
  156. package/dist/web/server.js +389 -0
  157. package/dist/web/server.js.map +1 -0
  158. package/dist/web-ui/assets/index-BB0qvF1y.css +1 -0
  159. package/dist/web-ui/assets/index-Vmm72oKY.js +34 -0
  160. package/dist/web-ui/index.html +14 -0
  161. package/dist/web-ui/vite.svg +1 -0
  162. package/package.json +94 -0
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Index Manager for fast task lookups
3
+ *
4
+ * Maintains pre-computed indexes for efficient queries:
5
+ * - Status-based grouping (byStatus)
6
+ * - Priority-based grouping (byPriority)
7
+ * - Root tasks (no incoming edges)
8
+ * - Orphan tasks (no edges)
9
+ * - Full-text search index (inverted index)
10
+ * - File reference index
11
+ *
12
+ * Provides O(1) incremental updates and O(n) full rebuild.
13
+ *
14
+ * @module core/storage
15
+ */
16
+ import { TaskGraphStore } from '../graph/index.js';
17
+ /**
18
+ * Index Manager class
19
+ *
20
+ * Maintains indexes for fast task queries and filtering.
21
+ */
22
+ export class IndexManager {
23
+ /** Tasks grouped by status */
24
+ _byStatus;
25
+ /** Tasks grouped by priority */
26
+ _byPriority;
27
+ /** Full-text search index (term -> task IDs) */
28
+ _searchText;
29
+ /** File reference index (file path -> task IDs) */
30
+ _files;
31
+ /** Root tasks (no incoming edges) - cached */
32
+ _rootTasks;
33
+ /** Orphan tasks (no edges) - cached */
34
+ _orphanTasks;
35
+ /** Cached result object */
36
+ _cachedIndexes;
37
+ /**
38
+ * Create a new IndexManager
39
+ */
40
+ constructor() {
41
+ this._byStatus = new Map();
42
+ this._byPriority = new Map();
43
+ this._searchText = new Map();
44
+ this._files = new Map();
45
+ this._rootTasks = new Set();
46
+ this._orphanTasks = new Set();
47
+ this._cachedIndexes = null;
48
+ // Initialize status indexes
49
+ const statuses = ['ready', 'in_progress', 'in_review', 'completed', 'blocked'];
50
+ for (const status of statuses) {
51
+ this._byStatus.set(status, new Set());
52
+ }
53
+ // Initialize priority indexes
54
+ const priorities = ['top', 'second', 'later'];
55
+ for (const priority of priorities) {
56
+ this._byPriority.set(priority, new Set());
57
+ }
58
+ }
59
+ /**
60
+ * Incremental update for a single task
61
+ * Removes old task from indexes and adds new version
62
+ * O(1) operation for most cases
63
+ *
64
+ * @param task - New or updated task
65
+ * @param oldTask - Previous task state (for removal from old indexes)
66
+ * @param graph - TaskGraphStore for edge information
67
+ */
68
+ updateTask(task, oldTask, graph) {
69
+ // Remove old task from indexes if exists
70
+ if (oldTask) {
71
+ this._removeTask(oldTask);
72
+ }
73
+ // Add new task to indexes
74
+ this._addTask(task, graph);
75
+ // Invalidate cache
76
+ this._cachedIndexes = null;
77
+ }
78
+ /**
79
+ * Remove task from indexes
80
+ * @param task - Task to remove
81
+ * @private
82
+ */
83
+ _removeTask(task) {
84
+ // Remove from status index
85
+ this._byStatus.get(task.status)?.delete(task.id);
86
+ // Remove from priority index
87
+ this._byPriority.get(task.priority)?.delete(task.id);
88
+ // Remove from search index
89
+ const text = `${task.title} ${task.description} ${task.notes}`.toLowerCase();
90
+ const tokens = text.match(/\b\w+\b/g) || [];
91
+ for (const token of tokens) {
92
+ this._searchText.get(token)?.delete(task.id);
93
+ // Clean up empty token entries
94
+ if (this._searchText.get(token)?.size === 0) {
95
+ this._searchText.delete(token);
96
+ }
97
+ }
98
+ // Remove from file index
99
+ for (const filePath of task.related_files) {
100
+ this._files.get(filePath)?.delete(task.id);
101
+ // Clean up empty file entries
102
+ if (this._files.get(filePath)?.size === 0) {
103
+ this._files.delete(filePath);
104
+ }
105
+ }
106
+ // Remove from root/orphan caches (will be rebuilt on next get)
107
+ this._rootTasks.delete(task.id);
108
+ this._orphanTasks.delete(task.id);
109
+ }
110
+ /**
111
+ * Add task to indexes
112
+ * @param task - Task to add
113
+ * @param graph - TaskGraphStore for edge information
114
+ * @private
115
+ */
116
+ _addTask(task, graph) {
117
+ // Add to status index
118
+ if (!this._byStatus.has(task.status)) {
119
+ this._byStatus.set(task.status, new Set());
120
+ }
121
+ this._byStatus.get(task.status).add(task.id);
122
+ // Add to priority index
123
+ if (!this._byPriority.has(task.priority)) {
124
+ this._byPriority.set(task.priority, new Set());
125
+ }
126
+ this._byPriority.get(task.priority).add(task.id);
127
+ // Add to search index (tokenize and index)
128
+ const text = `${task.title} ${task.description} ${task.notes}`.toLowerCase();
129
+ const tokens = text.match(/\b\w+\b/g) || [];
130
+ for (const token of tokens) {
131
+ if (!this._searchText.has(token)) {
132
+ this._searchText.set(token, new Set());
133
+ }
134
+ this._searchText.get(token).add(task.id);
135
+ }
136
+ // Add to file reference index
137
+ for (const filePath of task.related_files) {
138
+ if (!this._files.has(filePath)) {
139
+ this._files.set(filePath, new Set());
140
+ }
141
+ this._files.get(filePath).add(task.id);
142
+ }
143
+ // Update root/orphan status
144
+ this._updateRootOrphanStatus(task.id, graph);
145
+ }
146
+ /**
147
+ * Update root/orphan status for a task
148
+ * @param taskId - Task ID to check
149
+ * @param graph - TaskGraphStore for edge information
150
+ * @private
151
+ */
152
+ _updateRootOrphanStatus(taskId, graph) {
153
+ const incoming = graph.getIncomingEdges(taskId);
154
+ const outgoing = graph.getOutgoingEdges(taskId);
155
+ // Root task: no incoming edges
156
+ if (incoming.length === 0) {
157
+ this._rootTasks.add(taskId);
158
+ }
159
+ else {
160
+ this._rootTasks.delete(taskId);
161
+ }
162
+ // Orphan task: no edges at all
163
+ if (incoming.length === 0 && outgoing.length === 0) {
164
+ this._orphanTasks.add(taskId);
165
+ }
166
+ else {
167
+ this._orphanTasks.delete(taskId);
168
+ }
169
+ }
170
+ /**
171
+ * Rebuild all indexes from scratch
172
+ * O(n) operation where n is the number of tasks
173
+ *
174
+ * @param tasks - Map of all tasks
175
+ * @param graph - TaskGraphStore for edge information
176
+ */
177
+ rebuildIndexes(tasks, graph) {
178
+ // Clear existing indexes
179
+ this._byStatus.clear();
180
+ this._byPriority.clear();
181
+ this._searchText.clear();
182
+ this._files.clear();
183
+ this._rootTasks.clear();
184
+ this._orphanTasks.clear();
185
+ // Re-initialize status and priority maps
186
+ const statuses = ['ready', 'in_progress', 'in_review', 'completed', 'blocked'];
187
+ for (const status of statuses) {
188
+ this._byStatus.set(status, new Set());
189
+ }
190
+ const priorities = ['top', 'second', 'later'];
191
+ for (const priority of priorities) {
192
+ this._byPriority.set(priority, new Set());
193
+ }
194
+ // Rebuild from all tasks
195
+ for (const task of tasks.values()) {
196
+ this._addTask(task, graph);
197
+ }
198
+ // Invalidate cache
199
+ this._cachedIndexes = null;
200
+ }
201
+ /**
202
+ * Get task IDs by status
203
+ * @param status - Task status to filter by
204
+ * @returns Array of task IDs
205
+ */
206
+ getByStatus(status) {
207
+ return Array.from(this._byStatus.get(status) || []);
208
+ }
209
+ /**
210
+ * Get task IDs by priority
211
+ * @param priority - Task priority to filter by
212
+ * @returns Array of task IDs
213
+ */
214
+ getByPriority(priority) {
215
+ return Array.from(this._byPriority.get(priority) || []);
216
+ }
217
+ /**
218
+ * Search tasks by text query
219
+ * @param query - Search query (will be tokenized)
220
+ * @returns Array of task IDs matching any token
221
+ */
222
+ search(query) {
223
+ const tokens = query.toLowerCase().match(/\b\w+\b/g) || [];
224
+ const results = new Set();
225
+ for (const token of tokens) {
226
+ const matching = this._searchText.get(token);
227
+ if (matching) {
228
+ for (const taskId of matching) {
229
+ results.add(taskId);
230
+ }
231
+ }
232
+ }
233
+ return Array.from(results);
234
+ }
235
+ /**
236
+ * Get task IDs by related file
237
+ * @param filePath - File path to search for
238
+ * @returns Array of task IDs
239
+ */
240
+ getByFile(filePath) {
241
+ return Array.from(this._files.get(filePath) || []);
242
+ }
243
+ /**
244
+ * Get root tasks (no incoming edges)
245
+ * @returns Array of task IDs
246
+ */
247
+ getRootTasks() {
248
+ return Array.from(this._rootTasks);
249
+ }
250
+ /**
251
+ * Get orphan tasks (no edges)
252
+ * @returns Array of task IDs
253
+ */
254
+ getOrphanTasks() {
255
+ return Array.from(this._orphanTasks);
256
+ }
257
+ /**
258
+ * Get all indexes as a ProjectIndexes object
259
+ * Cached result - only recomputed if indexes changed
260
+ *
261
+ * @returns ProjectIndexes interface
262
+ */
263
+ getIndexes() {
264
+ if (this._cachedIndexes) {
265
+ return this._cachedIndexes;
266
+ }
267
+ // Build result object
268
+ const result = {
269
+ byStatus: {},
270
+ byPriority: {},
271
+ rootTasks: this.getRootTasks(),
272
+ orphanTasks: this.getOrphanTasks(),
273
+ searchText: {},
274
+ files: {},
275
+ };
276
+ // Convert status sets to arrays
277
+ for (const [status, taskIds] of this._byStatus) {
278
+ result.byStatus[status] = Array.from(taskIds);
279
+ }
280
+ // Convert priority sets to arrays
281
+ for (const [priority, taskIds] of this._byPriority) {
282
+ result.byPriority[priority] = Array.from(taskIds);
283
+ }
284
+ // Convert search index sets to arrays
285
+ for (const [token, taskIds] of this._searchText) {
286
+ result.searchText[token] = Array.from(taskIds);
287
+ }
288
+ // Convert file index sets to arrays
289
+ for (const [filePath, taskIds] of this._files) {
290
+ result.files[filePath] = Array.from(taskIds);
291
+ }
292
+ // Cache result
293
+ this._cachedIndexes = result;
294
+ return result;
295
+ }
296
+ /**
297
+ * Clear all indexes
298
+ */
299
+ clear() {
300
+ this._byStatus.clear();
301
+ this._byPriority.clear();
302
+ this._searchText.clear();
303
+ this._files.clear();
304
+ this._rootTasks.clear();
305
+ this._orphanTasks.clear();
306
+ this._cachedIndexes = null;
307
+ // Re-initialize status and priority maps
308
+ const statuses = ['ready', 'in_progress', 'in_review', 'completed', 'blocked'];
309
+ for (const status of statuses) {
310
+ this._byStatus.set(status, new Set());
311
+ }
312
+ const priorities = ['top', 'second', 'later'];
313
+ for (const priority of priorities) {
314
+ this._byPriority.set(priority, new Set());
315
+ }
316
+ }
317
+ /**
318
+ * Get index statistics (for debugging)
319
+ * @returns Statistics about the indexes
320
+ */
321
+ getStats() {
322
+ const statusCounts = {
323
+ ready: 0,
324
+ in_progress: 0,
325
+ in_review: 0,
326
+ completed: 0,
327
+ blocked: 0,
328
+ };
329
+ for (const [status, taskIds] of this._byStatus) {
330
+ statusCounts[status] = taskIds.size;
331
+ }
332
+ const priorityCounts = {
333
+ top: 0,
334
+ second: 0,
335
+ later: 0,
336
+ };
337
+ for (const [priority, taskIds] of this._byPriority) {
338
+ priorityCounts[priority] = taskIds.size;
339
+ }
340
+ return {
341
+ statusCounts,
342
+ priorityCounts,
343
+ searchTermsCount: this._searchText.size,
344
+ fileRefCount: this._files.size,
345
+ rootTasksCount: this._rootTasks.size,
346
+ orphanTasksCount: this._orphanTasks.size,
347
+ };
348
+ }
349
+ }
350
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../../src/core/storage/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Status Helper Functions
3
+ *
4
+ * Utilities for automatic status transitions in the graph-based task system.
5
+ *
6
+ * @module core/utils/status-helpers
7
+ */
8
+ import type { TaskGraphStore } from '../graph/index.js';
9
+ /**
10
+ * Recalculate status of all tasks that depend on a blocker
11
+ *
12
+ * When a blocker task's status changes (e.g., completed), this function
13
+ * recalculates the status of all tasks that were blocked by it.
14
+ *
15
+ * This enables the "all blockers resolved → ready" automatic transition
16
+ * from the status refactor spec (Rule 5).
17
+ *
18
+ * @param blockerId - The ID of the task whose status changed
19
+ * @param graph - The task graph containing all tasks
20
+ * @returns Array of task IDs that had their status recalculated
21
+ */
22
+ export declare function recalculateDependentStatuses(blockerId: string, graph: TaskGraphStore): string[];
23
+ /**
24
+ * Check if all blockers for a task are resolved
25
+ *
26
+ * A blocker is considered resolved if:
27
+ * - The blocker task has status 'completed', OR
28
+ * - The blocker task no longer exists in the graph
29
+ *
30
+ * @param taskBlockers - Array of blocker task IDs
31
+ * @param graph - The task graph to check blocker status
32
+ * @returns True if all blockers are resolved or there are no blockers
33
+ */
34
+ export declare function areAllBlockersResolved(taskBlockers: string[], graph: TaskGraphStore): boolean;
35
+ /**
36
+ * Get all tasks that are blocking a given task
37
+ *
38
+ * @param taskId - The task to get blockers for
39
+ * @param graph - The task graph
40
+ * @returns Array of blocker task nodes
41
+ */
42
+ export declare function getActiveBlockers(taskId: string, graph: TaskGraphStore): Array<{
43
+ id: string;
44
+ title: string;
45
+ status: string;
46
+ }>;
47
+ /**
48
+ * Get all tasks that this task is blocking
49
+ *
50
+ * @param taskId - The task to find dependents for
51
+ * @param graph - The task graph
52
+ * @returns Array of task nodes that are blocked by this task
53
+ */
54
+ export declare function getTasksBlockedBy(taskId: string, graph: TaskGraphStore): Array<{
55
+ id: string;
56
+ title: string;
57
+ status: string;
58
+ }>;
59
+ //# sourceMappingURL=status-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-helpers.d.ts","sourceRoot":"","sources":["../../../src/core/utils/status-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,cAAc,GACpB,MAAM,EAAE,CAmCV;AAuCD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,cAAc,GACpB,OAAO,CAcT;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,cAAc,GACpB,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBtD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,cAAc,GACpB,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CActD"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Status Helper Functions
3
+ *
4
+ * Utilities for automatic status transitions in the graph-based task system.
5
+ *
6
+ * @module core/utils/status-helpers
7
+ */
8
+ /**
9
+ * Recalculate status of all tasks that depend on a blocker
10
+ *
11
+ * When a blocker task's status changes (e.g., completed), this function
12
+ * recalculates the status of all tasks that were blocked by it.
13
+ *
14
+ * This enables the "all blockers resolved → ready" automatic transition
15
+ * from the status refactor spec (Rule 5).
16
+ *
17
+ * @param blockerId - The ID of the task whose status changed
18
+ * @param graph - The task graph containing all tasks
19
+ * @returns Array of task IDs that had their status recalculated
20
+ */
21
+ export function recalculateDependentStatuses(blockerId, graph) {
22
+ const updatedTaskIds = [];
23
+ // Find all tasks that have this blocker in their blockers array
24
+ for (const task of graph.getAllTasks()) {
25
+ if (task.blockers.includes(blockerId)) {
26
+ const oldStatus = task.status;
27
+ // Check if ALL blockers are now resolved (completed or deleted)
28
+ const allBlockersResolved = areAllBlockersResolved(task.blockers, graph);
29
+ if (allBlockersResolved) {
30
+ // All blockers are resolved - calculate new status without considering blockers
31
+ // Use the standard status calculation logic but skip the blockers check
32
+ const newStatus = calculateStatusIgnoringBlockers(task);
33
+ if (newStatus !== task.status) {
34
+ task.status = newStatus;
35
+ // Touch the task to update timestamp
36
+ task.recalculateStatus(); // This will update timestamp
37
+ // Override the status since recalculateStatus() would set it back to blocked
38
+ task.status = newStatus;
39
+ }
40
+ }
41
+ else {
42
+ // Still has active blockers - just recalculate normally
43
+ task.recalculateStatus();
44
+ }
45
+ if (task.status !== oldStatus) {
46
+ updatedTaskIds.push(task.id);
47
+ }
48
+ }
49
+ }
50
+ return updatedTaskIds;
51
+ }
52
+ /**
53
+ * Calculate task status ignoring blockers
54
+ *
55
+ * Used when all blockers are resolved to determine what the status should be.
56
+ * This is the same logic as TaskNode.calculateStatus() but skips the blockers check.
57
+ *
58
+ * @param task - The task to calculate status for
59
+ * @returns The calculated status (ready, in_progress, or in_review)
60
+ */
61
+ function calculateStatusIgnoringBlockers(task) {
62
+ // Check if ready for review (all items complete)
63
+ const allCriteriaComplete = task.success_criteria.every(c => c.completed);
64
+ const allDeliverablesComplete = task.deliverables.every(d => d.completed);
65
+ const allNeedFixComplete = task.need_fix.every(f => f.completed);
66
+ const allComplete = allCriteriaComplete && allDeliverablesComplete && allNeedFixComplete;
67
+ if (allComplete) {
68
+ return 'in_review';
69
+ }
70
+ // Check if work has started
71
+ const anyCriteriaChecked = task.success_criteria.some(c => c.completed);
72
+ const anyDeliverableChecked = task.deliverables.some(d => d.completed);
73
+ const hasNeedFix = task.need_fix.length > 0;
74
+ if (anyCriteriaChecked || anyDeliverableChecked || hasNeedFix) {
75
+ return 'in_progress';
76
+ }
77
+ // Default - ready for work
78
+ return 'ready';
79
+ }
80
+ /**
81
+ * Check if all blockers for a task are resolved
82
+ *
83
+ * A blocker is considered resolved if:
84
+ * - The blocker task has status 'completed', OR
85
+ * - The blocker task no longer exists in the graph
86
+ *
87
+ * @param taskBlockers - Array of blocker task IDs
88
+ * @param graph - The task graph to check blocker status
89
+ * @returns True if all blockers are resolved or there are no blockers
90
+ */
91
+ export function areAllBlockersResolved(taskBlockers, graph) {
92
+ if (taskBlockers.length === 0) {
93
+ return true;
94
+ }
95
+ for (const blockerId of taskBlockers) {
96
+ const blockerTask = graph.getNode(blockerId);
97
+ // If blocker doesn't exist or is not completed, task is still blocked
98
+ if (blockerTask && blockerTask.status !== 'completed') {
99
+ return false;
100
+ }
101
+ }
102
+ return true;
103
+ }
104
+ /**
105
+ * Get all tasks that are blocking a given task
106
+ *
107
+ * @param taskId - The task to get blockers for
108
+ * @param graph - The task graph
109
+ * @returns Array of blocker task nodes
110
+ */
111
+ export function getActiveBlockers(taskId, graph) {
112
+ const task = graph.getNode(taskId);
113
+ if (!task || task.blockers.length === 0) {
114
+ return [];
115
+ }
116
+ const blockers = [];
117
+ for (const blockerId of task.blockers) {
118
+ const blockerTask = graph.getNode(blockerId);
119
+ if (blockerTask && blockerTask.status !== 'completed') {
120
+ blockers.push({
121
+ id: blockerId,
122
+ title: blockerTask.title,
123
+ status: blockerTask.status,
124
+ });
125
+ }
126
+ }
127
+ return blockers;
128
+ }
129
+ /**
130
+ * Get all tasks that this task is blocking
131
+ *
132
+ * @param taskId - The task to find dependents for
133
+ * @param graph - The task graph
134
+ * @returns Array of task nodes that are blocked by this task
135
+ */
136
+ export function getTasksBlockedBy(taskId, graph) {
137
+ const blockedTasks = [];
138
+ for (const task of graph.getAllTasks()) {
139
+ if (task.blockers.includes(taskId)) {
140
+ blockedTasks.push({
141
+ id: task.id,
142
+ title: task.title,
143
+ status: task.status,
144
+ });
145
+ }
146
+ }
147
+ return blockedTasks;
148
+ }
149
+ //# sourceMappingURL=status-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-helpers.js","sourceRoot":"","sources":["../../../src/core/utils/status-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Octie - Graph-based task management system
3
+ *
4
+ * Main entry point for the library.
5
+ */
6
+ export { TaskGraphStore } from './core/graph/index.js';
7
+ export { TaskNode } from './core/models/task-node.js';
8
+ export { TaskStorage } from './core/storage/file-store.js';
9
+ export * from './types/index.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,cAAc,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Octie - Graph-based task management system
3
+ *
4
+ * Main entry point for the library.
5
+ */
6
+ export { TaskGraphStore } from './core/graph/index.js';
7
+ export { TaskNode } from './core/models/task-node.js';
8
+ export { TaskStorage } from './core/storage/file-store.js';
9
+ export * from './types/index.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,cAAc,kBAAkB,CAAC"}