@diegonogueiradev_/mcp-graph 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 (233) hide show
  1. package/dist/core/context/compact-context.d.ts +51 -0
  2. package/dist/core/context/compact-context.d.ts.map +1 -0
  3. package/dist/core/context/compact-context.js +115 -0
  4. package/dist/core/context/compact-context.js.map +1 -0
  5. package/dist/core/context/rag-context.d.ts +36 -0
  6. package/dist/core/context/rag-context.d.ts.map +1 -0
  7. package/dist/core/context/rag-context.js +69 -0
  8. package/dist/core/context/rag-context.js.map +1 -0
  9. package/dist/core/context/token-estimator.d.ts +7 -0
  10. package/dist/core/context/token-estimator.d.ts.map +1 -0
  11. package/dist/core/context/token-estimator.js +9 -0
  12. package/dist/core/context/token-estimator.js.map +1 -0
  13. package/dist/core/graph/graph-indexes.d.ts +3 -0
  14. package/dist/core/graph/graph-indexes.d.ts.map +1 -0
  15. package/dist/core/graph/graph-indexes.js +28 -0
  16. package/dist/core/graph/graph-indexes.js.map +1 -0
  17. package/dist/core/graph/graph-types.d.ts +72 -0
  18. package/dist/core/graph/graph-types.d.ts.map +1 -0
  19. package/dist/core/graph/graph-types.js +2 -0
  20. package/dist/core/graph/graph-types.js.map +1 -0
  21. package/dist/core/importer/import-prd.d.ts +7 -0
  22. package/dist/core/importer/import-prd.d.ts.map +1 -0
  23. package/dist/core/importer/import-prd.js +7 -0
  24. package/dist/core/importer/import-prd.js.map +1 -0
  25. package/dist/core/importer/prd-to-graph.d.ts +18 -0
  26. package/dist/core/importer/prd-to-graph.d.ts.map +1 -0
  27. package/dist/core/importer/prd-to-graph.js +188 -0
  28. package/dist/core/importer/prd-to-graph.js.map +1 -0
  29. package/dist/core/parser/classify.d.ts +31 -0
  30. package/dist/core/parser/classify.d.ts.map +1 -0
  31. package/dist/core/parser/classify.js +128 -0
  32. package/dist/core/parser/classify.js.map +1 -0
  33. package/dist/core/parser/extract.d.ts +21 -0
  34. package/dist/core/parser/extract.d.ts.map +1 -0
  35. package/dist/core/parser/extract.js +66 -0
  36. package/dist/core/parser/extract.js.map +1 -0
  37. package/dist/core/parser/normalize.d.ts +9 -0
  38. package/dist/core/parser/normalize.d.ts.map +1 -0
  39. package/dist/core/parser/normalize.js +22 -0
  40. package/dist/core/parser/normalize.js.map +1 -0
  41. package/dist/core/parser/read-file.d.ts +7 -0
  42. package/dist/core/parser/read-file.d.ts.map +1 -0
  43. package/dist/core/parser/read-file.js +17 -0
  44. package/dist/core/parser/read-file.js.map +1 -0
  45. package/dist/core/parser/segment.d.ts +13 -0
  46. package/dist/core/parser/segment.d.ts.map +1 -0
  47. package/dist/core/parser/segment.js +53 -0
  48. package/dist/core/parser/segment.js.map +1 -0
  49. package/dist/core/planner/decompose.d.ts +25 -0
  50. package/dist/core/planner/decompose.d.ts.map +1 -0
  51. package/dist/core/planner/decompose.js +100 -0
  52. package/dist/core/planner/decompose.js.map +1 -0
  53. package/dist/core/planner/dependency-chain.d.ts +20 -0
  54. package/dist/core/planner/dependency-chain.d.ts.map +1 -0
  55. package/dist/core/planner/dependency-chain.js +163 -0
  56. package/dist/core/planner/dependency-chain.js.map +1 -0
  57. package/dist/core/planner/next-task.d.ts +16 -0
  58. package/dist/core/planner/next-task.d.ts.map +1 -0
  59. package/dist/core/planner/next-task.js +76 -0
  60. package/dist/core/planner/next-task.js.map +1 -0
  61. package/dist/core/planner/velocity.d.ts +38 -0
  62. package/dist/core/planner/velocity.d.ts.map +1 -0
  63. package/dist/core/planner/velocity.js +92 -0
  64. package/dist/core/planner/velocity.js.map +1 -0
  65. package/dist/core/search/fts-search.d.ts +16 -0
  66. package/dist/core/search/fts-search.d.ts.map +1 -0
  67. package/dist/core/search/fts-search.js +57 -0
  68. package/dist/core/search/fts-search.js.map +1 -0
  69. package/dist/core/search/tfidf.d.ts +32 -0
  70. package/dist/core/search/tfidf.d.ts.map +1 -0
  71. package/dist/core/search/tfidf.js +67 -0
  72. package/dist/core/search/tfidf.js.map +1 -0
  73. package/dist/core/search/tokenizer.d.ts +9 -0
  74. package/dist/core/search/tokenizer.d.ts.map +1 -0
  75. package/dist/core/search/tokenizer.js +37 -0
  76. package/dist/core/search/tokenizer.js.map +1 -0
  77. package/dist/core/store/migrations.d.ts +4 -0
  78. package/dist/core/store/migrations.d.ts.map +1 -0
  79. package/dist/core/store/migrations.js +137 -0
  80. package/dist/core/store/migrations.js.map +1 -0
  81. package/dist/core/store/sqlite-store.d.ts +68 -0
  82. package/dist/core/store/sqlite-store.d.ts.map +1 -0
  83. package/dist/core/store/sqlite-store.js +608 -0
  84. package/dist/core/store/sqlite-store.js.map +1 -0
  85. package/dist/core/utils/errors.d.ts +20 -0
  86. package/dist/core/utils/errors.d.ts.map +1 -0
  87. package/dist/core/utils/errors.js +39 -0
  88. package/dist/core/utils/errors.js.map +1 -0
  89. package/dist/core/utils/fs.d.ts +2 -0
  90. package/dist/core/utils/fs.d.ts.map +1 -0
  91. package/dist/core/utils/fs.js +11 -0
  92. package/dist/core/utils/fs.js.map +1 -0
  93. package/dist/core/utils/id.d.ts +2 -0
  94. package/dist/core/utils/id.d.ts.map +1 -0
  95. package/dist/core/utils/id.js +6 -0
  96. package/dist/core/utils/id.js.map +1 -0
  97. package/dist/core/utils/logger.d.ts +7 -0
  98. package/dist/core/utils/logger.d.ts.map +1 -0
  99. package/dist/core/utils/logger.js +23 -0
  100. package/dist/core/utils/logger.js.map +1 -0
  101. package/dist/core/utils/time.d.ts +2 -0
  102. package/dist/core/utils/time.d.ts.map +1 -0
  103. package/dist/core/utils/time.js +4 -0
  104. package/dist/core/utils/time.js.map +1 -0
  105. package/dist/index.d.ts +10 -0
  106. package/dist/index.d.ts.map +1 -0
  107. package/dist/index.js +9 -0
  108. package/dist/index.js.map +1 -0
  109. package/dist/mcp/init-project.d.ts +2 -0
  110. package/dist/mcp/init-project.d.ts.map +1 -0
  111. package/dist/mcp/init-project.js +104 -0
  112. package/dist/mcp/init-project.js.map +1 -0
  113. package/dist/mcp/server.d.ts +2 -0
  114. package/dist/mcp/server.d.ts.map +1 -0
  115. package/dist/mcp/server.js +30 -0
  116. package/dist/mcp/server.js.map +1 -0
  117. package/dist/mcp/stdio.d.ts +3 -0
  118. package/dist/mcp/stdio.d.ts.map +1 -0
  119. package/dist/mcp/stdio.js +20 -0
  120. package/dist/mcp/stdio.js.map +1 -0
  121. package/dist/mcp/tools/add-edge.d.ts +4 -0
  122. package/dist/mcp/tools/add-edge.d.ts.map +1 -0
  123. package/dist/mcp/tools/add-edge.js +62 -0
  124. package/dist/mcp/tools/add-edge.js.map +1 -0
  125. package/dist/mcp/tools/add-node.d.ts +4 -0
  126. package/dist/mcp/tools/add-node.d.ts.map +1 -0
  127. package/dist/mcp/tools/add-node.js +80 -0
  128. package/dist/mcp/tools/add-node.js.map +1 -0
  129. package/dist/mcp/tools/bulk-update-status.d.ts +4 -0
  130. package/dist/mcp/tools/bulk-update-status.d.ts.map +1 -0
  131. package/dist/mcp/tools/bulk-update-status.js +19 -0
  132. package/dist/mcp/tools/bulk-update-status.js.map +1 -0
  133. package/dist/mcp/tools/clone-node.d.ts +4 -0
  134. package/dist/mcp/tools/clone-node.d.ts.map +1 -0
  135. package/dist/mcp/tools/clone-node.js +107 -0
  136. package/dist/mcp/tools/clone-node.js.map +1 -0
  137. package/dist/mcp/tools/context.d.ts +4 -0
  138. package/dist/mcp/tools/context.d.ts.map +1 -0
  139. package/dist/mcp/tools/context.js +26 -0
  140. package/dist/mcp/tools/context.js.map +1 -0
  141. package/dist/mcp/tools/decompose.d.ts +4 -0
  142. package/dist/mcp/tools/decompose.d.ts.map +1 -0
  143. package/dist/mcp/tools/decompose.js +22 -0
  144. package/dist/mcp/tools/decompose.js.map +1 -0
  145. package/dist/mcp/tools/delete-edge.d.ts +4 -0
  146. package/dist/mcp/tools/delete-edge.d.ts.map +1 -0
  147. package/dist/mcp/tools/delete-edge.js +25 -0
  148. package/dist/mcp/tools/delete-edge.js.map +1 -0
  149. package/dist/mcp/tools/delete-node.d.ts +4 -0
  150. package/dist/mcp/tools/delete-node.d.ts.map +1 -0
  151. package/dist/mcp/tools/delete-node.js +25 -0
  152. package/dist/mcp/tools/delete-node.js.map +1 -0
  153. package/dist/mcp/tools/dependencies.d.ts +4 -0
  154. package/dist/mcp/tools/dependencies.d.ts.map +1 -0
  155. package/dist/mcp/tools/dependencies.js +42 -0
  156. package/dist/mcp/tools/dependencies.js.map +1 -0
  157. package/dist/mcp/tools/export-graph.d.ts +4 -0
  158. package/dist/mcp/tools/export-graph.d.ts.map +1 -0
  159. package/dist/mcp/tools/export-graph.js +14 -0
  160. package/dist/mcp/tools/export-graph.js.map +1 -0
  161. package/dist/mcp/tools/import-prd.d.ts +4 -0
  162. package/dist/mcp/tools/import-prd.d.ts.map +1 -0
  163. package/dist/mcp/tools/import-prd.js +72 -0
  164. package/dist/mcp/tools/import-prd.js.map +1 -0
  165. package/dist/mcp/tools/index.d.ts +4 -0
  166. package/dist/mcp/tools/index.d.ts.map +1 -0
  167. package/dist/mcp/tools/index.js +53 -0
  168. package/dist/mcp/tools/index.js.map +1 -0
  169. package/dist/mcp/tools/init.d.ts +4 -0
  170. package/dist/mcp/tools/init.d.ts.map +1 -0
  171. package/dist/mcp/tools/init.js +15 -0
  172. package/dist/mcp/tools/init.js.map +1 -0
  173. package/dist/mcp/tools/list-edges.d.ts +4 -0
  174. package/dist/mcp/tools/list-edges.d.ts.map +1 -0
  175. package/dist/mcp/tools/list-edges.js +49 -0
  176. package/dist/mcp/tools/list-edges.js.map +1 -0
  177. package/dist/mcp/tools/list.d.ts +4 -0
  178. package/dist/mcp/tools/list.d.ts.map +1 -0
  179. package/dist/mcp/tools/list.js +53 -0
  180. package/dist/mcp/tools/list.js.map +1 -0
  181. package/dist/mcp/tools/move-node.d.ts +4 -0
  182. package/dist/mcp/tools/move-node.d.ts.map +1 -0
  183. package/dist/mcp/tools/move-node.js +107 -0
  184. package/dist/mcp/tools/move-node.js.map +1 -0
  185. package/dist/mcp/tools/next.d.ts +4 -0
  186. package/dist/mcp/tools/next.d.ts.map +1 -0
  187. package/dist/mcp/tools/next.js +28 -0
  188. package/dist/mcp/tools/next.js.map +1 -0
  189. package/dist/mcp/tools/rag-context.d.ts +4 -0
  190. package/dist/mcp/tools/rag-context.d.ts.map +1 -0
  191. package/dist/mcp/tools/rag-context.js +25 -0
  192. package/dist/mcp/tools/rag-context.js.map +1 -0
  193. package/dist/mcp/tools/search.d.ts +4 -0
  194. package/dist/mcp/tools/search.d.ts.map +1 -0
  195. package/dist/mcp/tools/search.js +38 -0
  196. package/dist/mcp/tools/search.js.map +1 -0
  197. package/dist/mcp/tools/show.d.ts +4 -0
  198. package/dist/mcp/tools/show.d.ts.map +1 -0
  199. package/dist/mcp/tools/show.js +38 -0
  200. package/dist/mcp/tools/show.js.map +1 -0
  201. package/dist/mcp/tools/snapshot.d.ts +6 -0
  202. package/dist/mcp/tools/snapshot.d.ts.map +1 -0
  203. package/dist/mcp/tools/snapshot.js +43 -0
  204. package/dist/mcp/tools/snapshot.js.map +1 -0
  205. package/dist/mcp/tools/stats.d.ts +4 -0
  206. package/dist/mcp/tools/stats.d.ts.map +1 -0
  207. package/dist/mcp/tools/stats.js +43 -0
  208. package/dist/mcp/tools/stats.js.map +1 -0
  209. package/dist/mcp/tools/update-node.d.ts +4 -0
  210. package/dist/mcp/tools/update-node.d.ts.map +1 -0
  211. package/dist/mcp/tools/update-node.js +41 -0
  212. package/dist/mcp/tools/update-node.js.map +1 -0
  213. package/dist/mcp/tools/update-status.d.ts +4 -0
  214. package/dist/mcp/tools/update-status.d.ts.map +1 -0
  215. package/dist/mcp/tools/update-status.js +29 -0
  216. package/dist/mcp/tools/update-status.js.map +1 -0
  217. package/dist/mcp/tools/velocity.d.ts +4 -0
  218. package/dist/mcp/tools/velocity.d.ts.map +1 -0
  219. package/dist/mcp/tools/velocity.js +22 -0
  220. package/dist/mcp/tools/velocity.js.map +1 -0
  221. package/dist/schemas/edge.schema.d.ts +31 -0
  222. package/dist/schemas/edge.schema.d.ts.map +1 -0
  223. package/dist/schemas/edge.schema.js +16 -0
  224. package/dist/schemas/edge.schema.js.map +1 -0
  225. package/dist/schemas/graph.schema.d.ts +102 -0
  226. package/dist/schemas/graph.schema.d.ts.map +1 -0
  227. package/dist/schemas/graph.schema.js +28 -0
  228. package/dist/schemas/graph.schema.js.map +1 -0
  229. package/dist/schemas/node.schema.d.ts +80 -0
  230. package/dist/schemas/node.schema.d.ts.map +1 -0
  231. package/dist/schemas/node.schema.js +38 -0
  232. package/dist/schemas/node.schema.js.map +1 -0
  233. package/package.json +54 -0
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Task decomposition: detects large tasks and suggests breakdown.
3
+ *
4
+ * A task is considered "large" if:
5
+ * - estimateMinutes > 120 (2 hours)
6
+ * - xpSize is L or XL
7
+ * - Has more than 5 acceptance criteria (complex scope)
8
+ */
9
+ import type { GraphDocument, GraphNode } from "../graph/graph-types.js";
10
+ export interface DecomposeResult {
11
+ node: GraphNode;
12
+ reasons: string[];
13
+ suggestedSubtasks: SuggestedSubtask[];
14
+ }
15
+ export interface SuggestedSubtask {
16
+ title: string;
17
+ estimateMinutes?: number;
18
+ xpSize: string;
19
+ basedOn: string;
20
+ }
21
+ /**
22
+ * Detect large tasks in the graph that should be decomposed.
23
+ */
24
+ export declare function detectLargeTasks(doc: GraphDocument): DecomposeResult[];
25
+ //# sourceMappingURL=decompose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decompose.d.ts","sourceRoot":"","sources":["../../../src/core/planner/decompose.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAWxE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,eAAe,EAAE,CAqCtE"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Task decomposition: detects large tasks and suggests breakdown.
3
+ *
4
+ * A task is considered "large" if:
5
+ * - estimateMinutes > 120 (2 hours)
6
+ * - xpSize is L or XL
7
+ * - Has more than 5 acceptance criteria (complex scope)
8
+ */
9
+ import { logger } from "../utils/logger.js";
10
+ const XP_SIZE_ORDER = {
11
+ XS: 1, S: 2, M: 3, L: 4, XL: 5,
12
+ };
13
+ const ESTIMATE_THRESHOLD = 120; // minutes
14
+ const AC_THRESHOLD = 5;
15
+ const LARGE_XP_THRESHOLD = 4; // L=4, XL=5
16
+ /**
17
+ * Detect large tasks in the graph that should be decomposed.
18
+ */
19
+ export function detectLargeTasks(doc) {
20
+ const results = [];
21
+ const tasks = doc.nodes.filter((n) => (n.type === "task" || n.type === "subtask") && n.status !== "done");
22
+ for (const node of tasks) {
23
+ const reasons = [];
24
+ if (node.estimateMinutes && node.estimateMinutes > ESTIMATE_THRESHOLD) {
25
+ reasons.push(`estimate ${node.estimateMinutes}min > ${ESTIMATE_THRESHOLD}min threshold`);
26
+ }
27
+ const sizeOrder = XP_SIZE_ORDER[node.xpSize || "M"] ?? 3;
28
+ if (sizeOrder >= LARGE_XP_THRESHOLD) {
29
+ reasons.push(`XP size ${node.xpSize} is large`);
30
+ }
31
+ const acCount = node.acceptanceCriteria?.length ?? 0;
32
+ if (acCount > AC_THRESHOLD) {
33
+ reasons.push(`${acCount} acceptance criteria > ${AC_THRESHOLD} threshold`);
34
+ }
35
+ if (reasons.length === 0)
36
+ continue;
37
+ // Check if already decomposed (has children)
38
+ const hasChildren = doc.nodes.some((n) => n.parentId === node.id);
39
+ if (hasChildren)
40
+ continue;
41
+ const suggestedSubtasks = suggestDecomposition(node);
42
+ results.push({ node, reasons, suggestedSubtasks });
43
+ }
44
+ logger.info(`Decomposition: ${results.length} large tasks detected from ${tasks.length} total`);
45
+ return results;
46
+ }
47
+ /**
48
+ * Suggest subtask breakdown based on acceptance criteria and estimate.
49
+ */
50
+ function suggestDecomposition(node) {
51
+ const subtasks = [];
52
+ const ac = node.acceptanceCriteria ?? [];
53
+ if (ac.length > 0) {
54
+ // Group acceptance criteria into subtasks (2-3 AC per subtask)
55
+ const chunkSize = Math.max(2, Math.ceil(ac.length / Math.ceil(ac.length / 3)));
56
+ for (let i = 0; i < ac.length; i += chunkSize) {
57
+ const chunk = ac.slice(i, i + chunkSize);
58
+ const title = chunk.length === 1
59
+ ? chunk[0]
60
+ : `${chunk[0].slice(0, 60)}${chunk.length > 1 ? ` (+${chunk.length - 1} criteria)` : ""}`;
61
+ const estPerSubtask = node.estimateMinutes
62
+ ? Math.ceil(node.estimateMinutes / Math.ceil(ac.length / chunkSize))
63
+ : undefined;
64
+ subtasks.push({
65
+ title,
66
+ estimateMinutes: estPerSubtask,
67
+ xpSize: estimateSubtaskSize(estPerSubtask),
68
+ basedOn: "acceptance_criteria",
69
+ });
70
+ }
71
+ }
72
+ else if (node.estimateMinutes && node.estimateMinutes > ESTIMATE_THRESHOLD) {
73
+ // No AC — split by time estimate
74
+ const numParts = Math.ceil(node.estimateMinutes / 60);
75
+ const estPerPart = Math.ceil(node.estimateMinutes / numParts);
76
+ for (let i = 0; i < numParts; i++) {
77
+ subtasks.push({
78
+ title: `${node.title} — part ${i + 1}/${numParts}`,
79
+ estimateMinutes: estPerPart,
80
+ xpSize: estimateSubtaskSize(estPerPart),
81
+ basedOn: "time_split",
82
+ });
83
+ }
84
+ }
85
+ return subtasks;
86
+ }
87
+ function estimateSubtaskSize(minutes) {
88
+ if (!minutes)
89
+ return "S";
90
+ if (minutes <= 15)
91
+ return "XS";
92
+ if (minutes <= 30)
93
+ return "S";
94
+ if (minutes <= 60)
95
+ return "M";
96
+ if (minutes <= 120)
97
+ return "L";
98
+ return "XL";
99
+ }
100
+ //# sourceMappingURL=decompose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decompose.js","sourceRoot":"","sources":["../../../src/core/planner/decompose.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Dependency chain analysis: transitive blockers, cycle detection, critical path.
3
+ */
4
+ import type { GraphDocument, GraphNode } from "../graph/graph-types.js";
5
+ /**
6
+ * Find all transitive blockers for a given node.
7
+ * Follows depends_on edges backwards and blocks edges forwards.
8
+ */
9
+ export declare function findTransitiveBlockers(doc: GraphDocument, nodeId: string): GraphNode[];
10
+ /**
11
+ * Detect cycles in the dependency graph using DFS.
12
+ * Only considers depends_on and blocks edges.
13
+ */
14
+ export declare function detectCycles(doc: GraphDocument): string[][];
15
+ /**
16
+ * Find the critical path (longest path by estimateMinutes) through depends_on edges.
17
+ * Uses topological sort on the dependency DAG.
18
+ */
19
+ export declare function findCriticalPath(doc: GraphDocument): GraphNode[];
20
+ //# sourceMappingURL=dependency-chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-chain.d.ts","sourceRoot":"","sources":["../../../src/core/planner/dependency-chain.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGxE;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CA+BtF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,EAAE,EAAE,CAgD3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,EAAE,CAmFhE"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Dependency chain analysis: transitive blockers, cycle detection, critical path.
3
+ */
4
+ import { logger } from "../utils/logger.js";
5
+ /**
6
+ * Find all transitive blockers for a given node.
7
+ * Follows depends_on edges backwards and blocks edges forwards.
8
+ */
9
+ export function findTransitiveBlockers(doc, nodeId) {
10
+ const visited = new Set();
11
+ const queue = [nodeId];
12
+ visited.add(nodeId);
13
+ const blockers = [];
14
+ const nodeMap = new Map(doc.nodes.map((n) => [n.id, n]));
15
+ while (queue.length > 0) {
16
+ const current = queue.shift();
17
+ for (const edge of doc.edges) {
18
+ let blockerId = null;
19
+ // "from depends_on to" means to is a blocker of from
20
+ if (edge.from === current && edge.relationType === "depends_on") {
21
+ blockerId = edge.to;
22
+ }
23
+ else if (edge.to === current && edge.relationType === "blocks") {
24
+ blockerId = edge.from;
25
+ }
26
+ if (blockerId && !visited.has(blockerId)) {
27
+ visited.add(blockerId);
28
+ queue.push(blockerId);
29
+ const node = nodeMap.get(blockerId);
30
+ if (node)
31
+ blockers.push(node);
32
+ }
33
+ }
34
+ }
35
+ logger.info(`Transitive blockers for ${nodeId}: ${blockers.length} found`);
36
+ return blockers;
37
+ }
38
+ /**
39
+ * Detect cycles in the dependency graph using DFS.
40
+ * Only considers depends_on and blocks edges.
41
+ */
42
+ export function detectCycles(doc) {
43
+ const adj = new Map();
44
+ for (const edge of doc.edges) {
45
+ if (edge.relationType === "depends_on") {
46
+ // from depends_on to → dependency direction: from → to
47
+ const list = adj.get(edge.from) ?? [];
48
+ list.push(edge.to);
49
+ adj.set(edge.from, list);
50
+ }
51
+ else if (edge.relationType === "blocks") {
52
+ // from blocks to → dependency direction: to → from
53
+ const list = adj.get(edge.to) ?? [];
54
+ list.push(edge.from);
55
+ adj.set(edge.to, list);
56
+ }
57
+ }
58
+ const allNodes = new Set(doc.nodes.map((n) => n.id));
59
+ const visited = new Set();
60
+ const inStack = new Set();
61
+ const cycles = [];
62
+ function dfs(node, path) {
63
+ visited.add(node);
64
+ inStack.add(node);
65
+ path.push(node);
66
+ for (const neighbor of adj.get(node) ?? []) {
67
+ if (inStack.has(neighbor)) {
68
+ const cycleStart = path.indexOf(neighbor);
69
+ cycles.push([...path.slice(cycleStart), neighbor]);
70
+ }
71
+ else if (!visited.has(neighbor)) {
72
+ dfs(neighbor, path);
73
+ }
74
+ }
75
+ path.pop();
76
+ inStack.delete(node);
77
+ }
78
+ for (const node of allNodes) {
79
+ if (!visited.has(node)) {
80
+ dfs(node, []);
81
+ }
82
+ }
83
+ logger.info(`Cycle detection: ${cycles.length} cycles found`);
84
+ return cycles;
85
+ }
86
+ /**
87
+ * Find the critical path (longest path by estimateMinutes) through depends_on edges.
88
+ * Uses topological sort on the dependency DAG.
89
+ */
90
+ export function findCriticalPath(doc) {
91
+ const DEFAULT_ESTIMATE = 60;
92
+ const nodeMap = new Map(doc.nodes.map((n) => [n.id, n]));
93
+ // Build adjacency list for depends_on edges (from depends on to → to must finish before from)
94
+ // Direction: dependency edges point from dependent to prerequisite
95
+ // We want longest path, so build forward graph: prerequisite → dependent
96
+ const forward = new Map();
97
+ const inDegree = new Map();
98
+ for (const node of doc.nodes) {
99
+ forward.set(node.id, []);
100
+ inDegree.set(node.id, 0);
101
+ }
102
+ for (const edge of doc.edges) {
103
+ if (edge.relationType === "depends_on") {
104
+ // edge.from depends_on edge.to → edge.to is prerequisite
105
+ const list = forward.get(edge.to) ?? [];
106
+ list.push(edge.from);
107
+ forward.set(edge.to, list);
108
+ inDegree.set(edge.from, (inDegree.get(edge.from) ?? 0) + 1);
109
+ }
110
+ }
111
+ // Topological sort (Kahn's algorithm) + longest path
112
+ const dist = new Map();
113
+ const prev = new Map();
114
+ const queue = [];
115
+ for (const node of doc.nodes) {
116
+ const est = node.estimateMinutes ?? DEFAULT_ESTIMATE;
117
+ dist.set(node.id, est);
118
+ prev.set(node.id, null);
119
+ if ((inDegree.get(node.id) ?? 0) === 0) {
120
+ queue.push(node.id);
121
+ }
122
+ }
123
+ while (queue.length > 0) {
124
+ const current = queue.shift();
125
+ const currentDist = dist.get(current) ?? 0;
126
+ for (const neighbor of forward.get(current) ?? []) {
127
+ const neighborEst = nodeMap.get(neighbor)?.estimateMinutes ?? DEFAULT_ESTIMATE;
128
+ const newDist = currentDist + neighborEst;
129
+ if (newDist > (dist.get(neighbor) ?? 0)) {
130
+ dist.set(neighbor, newDist);
131
+ prev.set(neighbor, current);
132
+ }
133
+ const deg = (inDegree.get(neighbor) ?? 1) - 1;
134
+ inDegree.set(neighbor, deg);
135
+ if (deg === 0) {
136
+ queue.push(neighbor);
137
+ }
138
+ }
139
+ }
140
+ // Find the node with maximum distance
141
+ let maxNode = null;
142
+ let maxDist = 0;
143
+ for (const [id, d] of dist) {
144
+ if (d > maxDist) {
145
+ maxDist = d;
146
+ maxNode = id;
147
+ }
148
+ }
149
+ if (!maxNode)
150
+ return [];
151
+ // Reconstruct path
152
+ const path = [];
153
+ let current = maxNode;
154
+ while (current) {
155
+ const node = nodeMap.get(current);
156
+ if (node)
157
+ path.unshift(node);
158
+ current = prev.get(current) ?? null;
159
+ }
160
+ logger.info(`Critical path: ${path.length} nodes, ${maxDist} total minutes`);
161
+ return path;
162
+ }
163
+ //# sourceMappingURL=dependency-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-chain.js","sourceRoot":"","sources":["../../../src/core/planner/dependency-chain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Execution planner: suggests the next best task to work on.
3
+ *
4
+ * Algorithm:
5
+ * 1. Filter nodes of type task/subtask with status backlog or ready
6
+ * 2. Eliminate nodes with unresolved depends_on edges (dependency target not done)
7
+ * 3. Eliminate nodes with blocked = true
8
+ * 4. Sort by: priority ASC, xpSize ASC, estimateMinutes ASC, createdAt ASC
9
+ */
10
+ import type { GraphDocument, GraphNode } from "../graph/graph-types.js";
11
+ export interface NextTaskResult {
12
+ node: GraphNode;
13
+ reason: string;
14
+ }
15
+ export declare function findNextTask(doc: GraphDocument): NextTaskResult | null;
16
+ //# sourceMappingURL=next-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-task.d.ts","sourceRoot":"","sources":["../../../src/core/planner/next-task.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAU,MAAM,yBAAyB,CAAC;AAOhF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,GAAG,IAAI,CA0EtE"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Execution planner: suggests the next best task to work on.
3
+ *
4
+ * Algorithm:
5
+ * 1. Filter nodes of type task/subtask with status backlog or ready
6
+ * 2. Eliminate nodes with unresolved depends_on edges (dependency target not done)
7
+ * 3. Eliminate nodes with blocked = true
8
+ * 4. Sort by: priority ASC, xpSize ASC, estimateMinutes ASC, createdAt ASC
9
+ */
10
+ import { logger } from "../utils/logger.js";
11
+ const XP_SIZE_ORDER = {
12
+ XS: 1, S: 2, M: 3, L: 4, XL: 5,
13
+ };
14
+ export function findNextTask(doc) {
15
+ // Step 1: Filter eligible nodes
16
+ const eligible = doc.nodes.filter((n) => (n.type === "task" || n.type === "subtask") &&
17
+ (n.status === "backlog" || n.status === "ready") &&
18
+ !n.blocked);
19
+ logger.info(`Next task: ${eligible.length} eligible from ${doc.nodes.length} total`);
20
+ if (eligible.length === 0)
21
+ return null;
22
+ // Step 2: Build a set of done node IDs for dependency checking
23
+ const doneIds = new Set(doc.nodes.filter((n) => n.status === "done").map((n) => n.id));
24
+ // Step 3: Find depends_on edges and filter out nodes with unresolved deps
25
+ const unblocked = eligible.filter((node) => {
26
+ const depsEdges = doc.edges.filter((e) => e.from === node.id && e.relationType === "depends_on");
27
+ // All dependency targets must be done
28
+ return depsEdges.every((e) => doneIds.has(e.to));
29
+ });
30
+ if (unblocked.length === 0) {
31
+ // All eligible tasks have unresolved dependencies — return the one with fewest deps
32
+ const withDepCount = eligible.map((node) => {
33
+ const deps = doc.edges.filter((e) => e.from === node.id && e.relationType === "depends_on" && !doneIds.has(e.to));
34
+ return { node, pendingDeps: deps.length };
35
+ });
36
+ withDepCount.sort((a, b) => a.pendingDeps - b.pendingDeps);
37
+ return {
38
+ node: withDepCount[0].node,
39
+ reason: `Todas as tasks tĂŞm dependĂŞncias pendentes. Esta tem menos (${withDepCount[0].pendingDeps}).`,
40
+ };
41
+ }
42
+ // Step 4: Sort
43
+ unblocked.sort((a, b) => {
44
+ // Priority ASC (1 = critical, 5 = optional)
45
+ if (a.priority !== b.priority)
46
+ return a.priority - b.priority;
47
+ // XP size ASC
48
+ const sizeA = XP_SIZE_ORDER[a.xpSize || "M"] ?? 3;
49
+ const sizeB = XP_SIZE_ORDER[b.xpSize || "M"] ?? 3;
50
+ if (sizeA !== sizeB)
51
+ return sizeA - sizeB;
52
+ // Estimate ASC
53
+ const estA = a.estimateMinutes ?? 999;
54
+ const estB = b.estimateMinutes ?? 999;
55
+ if (estA !== estB)
56
+ return estA - estB;
57
+ // Prefer tasks with more acceptance criteria (clearer definition)
58
+ const acA = a.acceptanceCriteria?.length ?? 0;
59
+ const acB = b.acceptanceCriteria?.length ?? 0;
60
+ if (acA !== acB)
61
+ return acB - acA;
62
+ // CreatedAt ASC (older first)
63
+ return a.createdAt.localeCompare(b.createdAt);
64
+ });
65
+ const best = unblocked[0];
66
+ const reasons = ["desbloqueada"];
67
+ if (best.priority <= 2)
68
+ reasons.push("alta prioridade");
69
+ if (best.xpSize && XP_SIZE_ORDER[best.xpSize] <= 2)
70
+ reasons.push("baixa complexidade");
71
+ return {
72
+ node: best,
73
+ reason: reasons.join(", "),
74
+ };
75
+ }
76
+ //# sourceMappingURL=next-task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-task.js","sourceRoot":"","sources":["../../../src/core/planner/next-task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Velocity tracking: measures sprint completion metrics.
3
+ *
4
+ * Computes:
5
+ * - Tasks completed per sprint
6
+ * - Average XP size completed
7
+ * - Estimated completion time (based on created→done timestamps)
8
+ */
9
+ import type { GraphDocument } from "../graph/graph-types.js";
10
+ export interface SprintVelocity {
11
+ sprint: string;
12
+ tasksCompleted: number;
13
+ totalPoints: number;
14
+ avgPointsPerTask: number;
15
+ avgCompletionHours: number | null;
16
+ tasks: VelocityTask[];
17
+ }
18
+ export interface VelocityTask {
19
+ id: string;
20
+ title: string;
21
+ xpSize: string;
22
+ points: number;
23
+ completionHours: number | null;
24
+ }
25
+ export interface VelocitySummary {
26
+ sprints: SprintVelocity[];
27
+ overall: {
28
+ totalTasksCompleted: number;
29
+ totalPoints: number;
30
+ avgPointsPerSprint: number;
31
+ avgCompletionHours: number | null;
32
+ };
33
+ }
34
+ /**
35
+ * Calculate velocity metrics for all sprints in the graph.
36
+ */
37
+ export declare function calculateVelocity(doc: GraphDocument): VelocitySummary;
38
+ //# sourceMappingURL=velocity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"velocity.d.ts","sourceRoot":"","sources":["../../../src/core/planner/velocity.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,yBAAyB,CAAC;AAOxE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE;QACP,mBAAmB,EAAE,MAAM,CAAC;QAC5B,WAAW,EAAE,MAAM,CAAC;QACpB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,eAAe,CAwErE"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Velocity tracking: measures sprint completion metrics.
3
+ *
4
+ * Computes:
5
+ * - Tasks completed per sprint
6
+ * - Average XP size completed
7
+ * - Estimated completion time (based on created→done timestamps)
8
+ */
9
+ import { logger } from "../utils/logger.js";
10
+ const XP_SIZE_POINTS = {
11
+ XS: 1, S: 2, M: 3, L: 5, XL: 8,
12
+ };
13
+ /**
14
+ * Calculate velocity metrics for all sprints in the graph.
15
+ */
16
+ export function calculateVelocity(doc) {
17
+ // Group done tasks by sprint
18
+ const doneTasks = doc.nodes.filter((n) => n.status === "done" && (n.type === "task" || n.type === "subtask"));
19
+ const bySprint = new Map();
20
+ for (const node of doneTasks) {
21
+ const sprint = node.sprint ?? "(no sprint)";
22
+ const group = bySprint.get(sprint) ?? [];
23
+ group.push(node);
24
+ bySprint.set(sprint, group);
25
+ }
26
+ const sprints = [];
27
+ for (const [sprint, tasks] of bySprint) {
28
+ const velocityTasks = tasks.map((t) => {
29
+ const points = XP_SIZE_POINTS[t.xpSize ?? "M"] ?? 3;
30
+ const completionHours = computeCompletionHours(t);
31
+ return {
32
+ id: t.id,
33
+ title: t.title,
34
+ xpSize: t.xpSize ?? "M",
35
+ points,
36
+ completionHours,
37
+ };
38
+ });
39
+ const totalPoints = velocityTasks.reduce((sum, t) => sum + t.points, 0);
40
+ const hoursValues = velocityTasks
41
+ .map((t) => t.completionHours)
42
+ .filter((h) => h !== null);
43
+ sprints.push({
44
+ sprint,
45
+ tasksCompleted: tasks.length,
46
+ totalPoints,
47
+ avgPointsPerTask: tasks.length > 0 ? Math.round((totalPoints / tasks.length) * 10) / 10 : 0,
48
+ avgCompletionHours: hoursValues.length > 0
49
+ ? Math.round((hoursValues.reduce((a, b) => a + b, 0) / hoursValues.length) * 10) / 10
50
+ : null,
51
+ tasks: velocityTasks,
52
+ });
53
+ }
54
+ // Sort sprints by name
55
+ sprints.sort((a, b) => a.sprint.localeCompare(b.sprint));
56
+ const totalTasksCompleted = doneTasks.length;
57
+ const totalPoints = sprints.reduce((sum, s) => sum + s.totalPoints, 0);
58
+ const sprintCount = sprints.filter((s) => s.sprint !== "(no sprint)").length || 1;
59
+ const allHours = sprints
60
+ .flatMap((s) => s.tasks)
61
+ .map((t) => t.completionHours)
62
+ .filter((h) => h !== null);
63
+ logger.info(`Velocity: ${totalTasksCompleted} tasks done, ${totalPoints} points across ${sprints.length} sprints`);
64
+ return {
65
+ sprints,
66
+ overall: {
67
+ totalTasksCompleted,
68
+ totalPoints,
69
+ avgPointsPerSprint: Math.round((totalPoints / sprintCount) * 10) / 10,
70
+ avgCompletionHours: allHours.length > 0
71
+ ? Math.round((allHours.reduce((a, b) => a + b, 0) / allHours.length) * 10) / 10
72
+ : null,
73
+ },
74
+ };
75
+ }
76
+ /**
77
+ * Estimate completion time in hours from createdAt to updatedAt.
78
+ * Returns null if timestamps are invalid or equal.
79
+ */
80
+ function computeCompletionHours(node) {
81
+ try {
82
+ const created = new Date(node.createdAt).getTime();
83
+ const updated = new Date(node.updatedAt).getTime();
84
+ if (isNaN(created) || isNaN(updated) || updated <= created)
85
+ return null;
86
+ return Math.round(((updated - created) / (1000 * 60 * 60)) * 10) / 10;
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ //# sourceMappingURL=velocity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"velocity.js","sourceRoot":"","sources":["../../../src/core/planner/velocity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { SqliteStore } from "../store/sqlite-store.js";
2
+ import type { GraphNode } from "../graph/graph-types.js";
3
+ export interface SearchResult {
4
+ node: GraphNode;
5
+ score: number;
6
+ }
7
+ export interface SearchOptions {
8
+ limit?: number;
9
+ rerank?: boolean;
10
+ }
11
+ /**
12
+ * Search nodes using FTS5 full-text search with BM25 ranking.
13
+ * Optionally applies TF-IDF reranking for better relevance.
14
+ */
15
+ export declare function searchNodes(store: SqliteStore, query: string, options?: SearchOptions): SearchResult[];
16
+ //# sourceMappingURL=fts-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fts-search.d.ts","sourceRoot":"","sources":["../../../src/core/search/fts-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAIzD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAqBD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,YAAY,EAAE,CAqChB"}