mcp-adr-analysis-server 2.0.21 → 2.1.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 (263) hide show
  1. package/README.md +94 -839
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/config/ai-config.d.ts.map +1 -1
  4. package/dist/src/config/ai-config.js +9 -9
  5. package/dist/src/config/ai-config.js.map +1 -1
  6. package/dist/src/index.d.ts +15 -0
  7. package/dist/src/index.d.ts.map +1 -1
  8. package/dist/src/index.js +1594 -837
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/prompts/analysis-prompts.d.ts +4 -1
  11. package/dist/src/prompts/analysis-prompts.d.ts.map +1 -1
  12. package/dist/src/prompts/analysis-prompts.js +61 -30
  13. package/dist/src/prompts/analysis-prompts.js.map +1 -1
  14. package/dist/src/prompts/index.d.ts +17 -1
  15. package/dist/src/prompts/index.d.ts.map +1 -1
  16. package/dist/src/prompts/index.js +325 -1
  17. package/dist/src/prompts/index.js.map +1 -1
  18. package/dist/src/prompts/rule-generation-prompts.d.ts +5 -1
  19. package/dist/src/prompts/rule-generation-prompts.d.ts.map +1 -1
  20. package/dist/src/prompts/rule-generation-prompts.js +5 -1
  21. package/dist/src/prompts/rule-generation-prompts.js.map +1 -1
  22. package/dist/src/prompts/security-prompts.d.ts +6 -1
  23. package/dist/src/prompts/security-prompts.d.ts.map +1 -1
  24. package/dist/src/prompts/security-prompts.js +6 -1
  25. package/dist/src/prompts/security-prompts.js.map +1 -1
  26. package/dist/src/prompts/todo-prompts.d.ts +49 -0
  27. package/dist/src/prompts/todo-prompts.d.ts.map +1 -0
  28. package/dist/src/prompts/todo-prompts.js +824 -0
  29. package/dist/src/prompts/todo-prompts.js.map +1 -0
  30. package/dist/src/resources/index.d.ts.map +1 -1
  31. package/dist/src/resources/index.js +9 -7
  32. package/dist/src/resources/index.js.map +1 -1
  33. package/dist/src/tools/adr-bootstrap-validation-tool.d.ts +47 -0
  34. package/dist/src/tools/adr-bootstrap-validation-tool.d.ts.map +1 -0
  35. package/dist/src/tools/adr-bootstrap-validation-tool.js +979 -0
  36. package/dist/src/tools/adr-bootstrap-validation-tool.js.map +1 -0
  37. package/dist/src/tools/adr-suggestion-tool.d.ts +1 -0
  38. package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -1
  39. package/dist/src/tools/adr-suggestion-tool.js +330 -32
  40. package/dist/src/tools/adr-suggestion-tool.js.map +1 -1
  41. package/dist/src/tools/content-masking-tool.d.ts +5 -0
  42. package/dist/src/tools/content-masking-tool.d.ts.map +1 -1
  43. package/dist/src/tools/content-masking-tool.js +631 -28
  44. package/dist/src/tools/content-masking-tool.js.map +1 -1
  45. package/dist/src/tools/deployment-readiness-tool.d.ts +8 -5
  46. package/dist/src/tools/deployment-readiness-tool.d.ts.map +1 -1
  47. package/dist/src/tools/deployment-readiness-tool.js +1017 -93
  48. package/dist/src/tools/deployment-readiness-tool.js.map +1 -1
  49. package/dist/src/tools/environment-analysis-tool.d.ts +4 -0
  50. package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -1
  51. package/dist/src/tools/environment-analysis-tool.js +568 -24
  52. package/dist/src/tools/environment-analysis-tool.js.map +1 -1
  53. package/dist/src/tools/interactive-adr-planning-tool.d.ts.map +1 -1
  54. package/dist/src/tools/interactive-adr-planning-tool.js +270 -108
  55. package/dist/src/tools/interactive-adr-planning-tool.js.map +1 -1
  56. package/dist/src/tools/mcp-planning-tool.d.ts.map +1 -1
  57. package/dist/src/tools/mcp-planning-tool.js +316 -183
  58. package/dist/src/tools/mcp-planning-tool.js.map +1 -1
  59. package/dist/src/tools/memory-loading-tool.d.ts +60 -0
  60. package/dist/src/tools/memory-loading-tool.d.ts.map +1 -0
  61. package/dist/src/tools/memory-loading-tool.js +457 -0
  62. package/dist/src/tools/memory-loading-tool.js.map +1 -0
  63. package/dist/src/tools/research-integration-tool.d.ts +4 -1
  64. package/dist/src/tools/research-integration-tool.d.ts.map +1 -1
  65. package/dist/src/tools/research-integration-tool.js +5 -1
  66. package/dist/src/tools/research-integration-tool.js.map +1 -1
  67. package/dist/src/tools/review-existing-adrs-tool.d.ts +19 -0
  68. package/dist/src/tools/review-existing-adrs-tool.d.ts.map +1 -0
  69. package/dist/src/tools/review-existing-adrs-tool.js +1204 -0
  70. package/dist/src/tools/review-existing-adrs-tool.js.map +1 -0
  71. package/dist/src/tools/rule-generation-tool.d.ts +2 -0
  72. package/dist/src/tools/rule-generation-tool.d.ts.map +1 -1
  73. package/dist/src/tools/rule-generation-tool.js +274 -33
  74. package/dist/src/tools/rule-generation-tool.js.map +1 -1
  75. package/dist/src/tools/smart-git-push-tool-v2.d.ts +4 -0
  76. package/dist/src/tools/smart-git-push-tool-v2.d.ts.map +1 -1
  77. package/dist/src/tools/smart-git-push-tool-v2.js +423 -229
  78. package/dist/src/tools/smart-git-push-tool-v2.js.map +1 -1
  79. package/dist/src/tools/smart-git-push-tool.d.ts +3 -0
  80. package/dist/src/tools/smart-git-push-tool.d.ts.map +1 -1
  81. package/dist/src/tools/smart-git-push-tool.js +241 -235
  82. package/dist/src/tools/smart-git-push-tool.js.map +1 -1
  83. package/dist/src/tools/tool-chain-orchestrator.d.ts +2 -2
  84. package/dist/src/tools/tool-chain-orchestrator.d.ts.map +1 -1
  85. package/dist/src/tools/tool-chain-orchestrator.js +152 -93
  86. package/dist/src/tools/tool-chain-orchestrator.js.map +1 -1
  87. package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts +22 -13
  88. package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts.map +1 -1
  89. package/dist/src/tools/troubleshoot-guided-workflow-tool.js +660 -28
  90. package/dist/src/tools/troubleshoot-guided-workflow-tool.js.map +1 -1
  91. package/dist/src/types/ape-framework.d.ts +93 -0
  92. package/dist/src/types/ape-framework.d.ts.map +1 -1
  93. package/dist/src/types/ape-framework.js +10 -10
  94. package/dist/src/types/ape-framework.js.map +1 -1
  95. package/dist/src/types/enhanced-errors.d.ts +173 -0
  96. package/dist/src/types/enhanced-errors.d.ts.map +1 -0
  97. package/dist/src/types/enhanced-errors.js +668 -0
  98. package/dist/src/types/enhanced-errors.js.map +1 -0
  99. package/dist/src/types/index.d.ts +129 -3
  100. package/dist/src/types/index.d.ts.map +1 -1
  101. package/dist/src/types/index.js +15 -0
  102. package/dist/src/types/index.js.map +1 -1
  103. package/dist/src/types/knowledge-generation.d.ts +78 -0
  104. package/dist/src/types/knowledge-generation.d.ts.map +1 -1
  105. package/dist/src/types/knowledge-generation.js +10 -6
  106. package/dist/src/types/knowledge-generation.js.map +1 -1
  107. package/dist/src/types/knowledge-graph-schemas.d.ts +92 -0
  108. package/dist/src/types/knowledge-graph-schemas.d.ts.map +1 -1
  109. package/dist/src/types/knowledge-graph-schemas.js +45 -17
  110. package/dist/src/types/knowledge-graph-schemas.js.map +1 -1
  111. package/dist/src/types/memory-entities.d.ts +7209 -0
  112. package/dist/src/types/memory-entities.d.ts.map +1 -0
  113. package/dist/src/types/memory-entities.js +395 -0
  114. package/dist/src/types/memory-entities.js.map +1 -0
  115. package/dist/src/types/reflexion-framework.d.ts +44 -0
  116. package/dist/src/types/reflexion-framework.d.ts.map +1 -1
  117. package/dist/src/types/reflexion-framework.js +7 -7
  118. package/dist/src/types/reflexion-framework.js.map +1 -1
  119. package/dist/src/types/todo-json-schemas.d.ts +7 -653
  120. package/dist/src/types/todo-json-schemas.d.ts.map +1 -1
  121. package/dist/src/types/todo-json-schemas.js +6 -110
  122. package/dist/src/types/todo-json-schemas.js.map +1 -1
  123. package/dist/src/types/tool-arguments.d.ts +224 -0
  124. package/dist/src/types/tool-arguments.d.ts.map +1 -0
  125. package/dist/src/types/tool-arguments.js +6 -0
  126. package/dist/src/types/tool-arguments.js.map +1 -0
  127. package/dist/src/utils/actual-file-operations.d.ts.map +1 -1
  128. package/dist/src/utils/actual-file-operations.js +25 -9
  129. package/dist/src/utils/actual-file-operations.js.map +1 -1
  130. package/dist/src/utils/adr-discovery.d.ts +33 -1
  131. package/dist/src/utils/adr-discovery.d.ts.map +1 -1
  132. package/dist/src/utils/adr-discovery.js +14 -9
  133. package/dist/src/utils/adr-discovery.js.map +1 -1
  134. package/dist/src/utils/adr-suggestions.d.ts +72 -0
  135. package/dist/src/utils/adr-suggestions.d.ts.map +1 -1
  136. package/dist/src/utils/adr-suggestions.js +6 -0
  137. package/dist/src/utils/adr-suggestions.js.map +1 -1
  138. package/dist/src/utils/cache.d.ts.map +1 -1
  139. package/dist/src/utils/cache.js +22 -19
  140. package/dist/src/utils/cache.js.map +1 -1
  141. package/dist/src/utils/chain-of-thought-template.d.ts +13 -1
  142. package/dist/src/utils/chain-of-thought-template.d.ts.map +1 -1
  143. package/dist/src/utils/chain-of-thought-template.js +31 -22
  144. package/dist/src/utils/chain-of-thought-template.js.map +1 -1
  145. package/dist/src/utils/config.d.ts.map +1 -1
  146. package/dist/src/utils/config.js +1 -0
  147. package/dist/src/utils/config.js.map +1 -1
  148. package/dist/src/utils/directory-compat.js +1 -1
  149. package/dist/src/utils/directory-compat.js.map +1 -1
  150. package/dist/src/utils/enhanced-logging.d.ts +195 -0
  151. package/dist/src/utils/enhanced-logging.d.ts.map +1 -0
  152. package/dist/src/utils/enhanced-logging.js +449 -0
  153. package/dist/src/utils/enhanced-logging.js.map +1 -0
  154. package/dist/src/utils/file-system.d.ts +182 -34
  155. package/dist/src/utils/file-system.d.ts.map +1 -1
  156. package/dist/src/utils/file-system.js +648 -774
  157. package/dist/src/utils/file-system.js.map +1 -1
  158. package/dist/src/utils/gitleaks-detector.d.ts +50 -0
  159. package/dist/src/utils/gitleaks-detector.d.ts.map +1 -0
  160. package/dist/src/utils/gitleaks-detector.js +334 -0
  161. package/dist/src/utils/gitleaks-detector.js.map +1 -0
  162. package/dist/src/utils/interactive-approval.d.ts +1 -1
  163. package/dist/src/utils/interactive-approval.d.ts.map +1 -1
  164. package/dist/src/utils/interactive-approval.js +22 -17
  165. package/dist/src/utils/interactive-approval.js.map +1 -1
  166. package/dist/src/utils/json-safe.d.ts.map +1 -1
  167. package/dist/src/utils/json-safe.js +9 -6
  168. package/dist/src/utils/json-safe.js.map +1 -1
  169. package/dist/src/utils/knowledge-graph-manager.d.ts +37 -1
  170. package/dist/src/utils/knowledge-graph-manager.d.ts.map +1 -1
  171. package/dist/src/utils/knowledge-graph-manager.js +315 -70
  172. package/dist/src/utils/knowledge-graph-manager.js.map +1 -1
  173. package/dist/src/utils/location-filter.d.ts +35 -10
  174. package/dist/src/utils/location-filter.d.ts.map +1 -1
  175. package/dist/src/utils/location-filter.js +360 -94
  176. package/dist/src/utils/location-filter.js.map +1 -1
  177. package/dist/src/utils/mcp-response-validator.d.ts.map +1 -1
  178. package/dist/src/utils/mcp-response-validator.js +34 -19
  179. package/dist/src/utils/mcp-response-validator.js.map +1 -1
  180. package/dist/src/utils/memory-entity-manager.d.ts +134 -0
  181. package/dist/src/utils/memory-entity-manager.d.ts.map +1 -0
  182. package/dist/src/utils/memory-entity-manager.js +851 -0
  183. package/dist/src/utils/memory-entity-manager.js.map +1 -0
  184. package/dist/src/utils/memory-health-scoring.d.ts +125 -0
  185. package/dist/src/utils/memory-health-scoring.d.ts.map +1 -0
  186. package/dist/src/utils/memory-health-scoring.js +277 -0
  187. package/dist/src/utils/memory-health-scoring.js.map +1 -0
  188. package/dist/src/utils/memory-migration-manager.d.ts +93 -0
  189. package/dist/src/utils/memory-migration-manager.d.ts.map +1 -0
  190. package/dist/src/utils/memory-migration-manager.js +842 -0
  191. package/dist/src/utils/memory-migration-manager.js.map +1 -0
  192. package/dist/src/utils/memory-relationship-mapper.d.ts +87 -0
  193. package/dist/src/utils/memory-relationship-mapper.d.ts.map +1 -0
  194. package/dist/src/utils/memory-relationship-mapper.js +482 -0
  195. package/dist/src/utils/memory-relationship-mapper.js.map +1 -0
  196. package/dist/src/utils/memory-rollback-manager.d.ts +105 -0
  197. package/dist/src/utils/memory-rollback-manager.d.ts.map +1 -0
  198. package/dist/src/utils/memory-rollback-manager.js +575 -0
  199. package/dist/src/utils/memory-rollback-manager.js.map +1 -0
  200. package/dist/src/utils/memory-transformation.d.ts +59 -0
  201. package/dist/src/utils/memory-transformation.d.ts.map +1 -0
  202. package/dist/src/utils/memory-transformation.js +742 -0
  203. package/dist/src/utils/memory-transformation.js.map +1 -0
  204. package/dist/src/utils/output-masking.d.ts +12 -0
  205. package/dist/src/utils/output-masking.d.ts.map +1 -1
  206. package/dist/src/utils/output-masking.js +5 -0
  207. package/dist/src/utils/output-masking.js.map +1 -1
  208. package/dist/src/utils/prompt-execution.d.ts.map +1 -1
  209. package/dist/src/utils/prompt-execution.js +72 -51
  210. package/dist/src/utils/prompt-execution.js.map +1 -1
  211. package/dist/src/utils/release-readiness-detector.d.ts.map +1 -1
  212. package/dist/src/utils/release-readiness-detector.js +43 -42
  213. package/dist/src/utils/release-readiness-detector.js.map +1 -1
  214. package/dist/src/utils/research-integration.d.ts.map +1 -1
  215. package/dist/src/utils/research-integration.js +73 -44
  216. package/dist/src/utils/research-integration.js.map +1 -1
  217. package/dist/src/utils/research-questions.d.ts.map +1 -1
  218. package/dist/src/utils/research-questions.js +40 -14
  219. package/dist/src/utils/research-questions.js.map +1 -1
  220. package/dist/src/utils/ripgrep-wrapper.d.ts +84 -0
  221. package/dist/src/utils/ripgrep-wrapper.d.ts.map +1 -0
  222. package/dist/src/utils/ripgrep-wrapper.js +255 -0
  223. package/dist/src/utils/ripgrep-wrapper.js.map +1 -0
  224. package/dist/src/utils/rule-generation.d.ts.map +1 -1
  225. package/dist/src/utils/rule-generation.js +26 -15
  226. package/dist/src/utils/rule-generation.js.map +1 -1
  227. package/dist/src/utils/todo-file-watcher.d.ts +11 -23
  228. package/dist/src/utils/todo-file-watcher.d.ts.map +1 -1
  229. package/dist/src/utils/todo-file-watcher.js +18 -156
  230. package/dist/src/utils/todo-file-watcher.js.map +1 -1
  231. package/dist/src/utils/tree-sitter-analyzer.d.ts +185 -0
  232. package/dist/src/utils/tree-sitter-analyzer.d.ts.map +1 -0
  233. package/dist/src/utils/tree-sitter-analyzer.js +885 -0
  234. package/dist/src/utils/tree-sitter-analyzer.js.map +1 -0
  235. package/package.json +51 -10
  236. package/dist/src/tools/smart-score-tool.d.ts +0 -173
  237. package/dist/src/tools/smart-score-tool.d.ts.map +0 -1
  238. package/dist/src/tools/smart-score-tool.js +0 -681
  239. package/dist/src/tools/smart-score-tool.js.map +0 -1
  240. package/dist/src/tools/todo-management-tool-v2.d.ts +0 -368
  241. package/dist/src/tools/todo-management-tool-v2.d.ts.map +0 -1
  242. package/dist/src/tools/todo-management-tool-v2.js +0 -922
  243. package/dist/src/tools/todo-management-tool-v2.js.map +0 -1
  244. package/dist/src/utils/enhanced-sensitive-detector.d.ts +0 -61
  245. package/dist/src/utils/enhanced-sensitive-detector.d.ts.map +0 -1
  246. package/dist/src/utils/enhanced-sensitive-detector.js +0 -437
  247. package/dist/src/utils/enhanced-sensitive-detector.js.map +0 -1
  248. package/dist/src/utils/project-health-scoring.d.ts +0 -177
  249. package/dist/src/utils/project-health-scoring.d.ts.map +0 -1
  250. package/dist/src/utils/project-health-scoring.js +0 -370
  251. package/dist/src/utils/project-health-scoring.js.map +0 -1
  252. package/dist/src/utils/todo-json-manager.d.ts +0 -71
  253. package/dist/src/utils/todo-json-manager.d.ts.map +0 -1
  254. package/dist/src/utils/todo-json-manager.js +0 -396
  255. package/dist/src/utils/todo-json-manager.js.map +0 -1
  256. package/dist/src/utils/todo-markdown-converter.d.ts +0 -16
  257. package/dist/src/utils/todo-markdown-converter.d.ts.map +0 -1
  258. package/dist/src/utils/todo-markdown-converter.js +0 -362
  259. package/dist/src/utils/todo-markdown-converter.js.map +0 -1
  260. package/dist/src/utils/todo-migration.d.ts +0 -47
  261. package/dist/src/utils/todo-migration.d.ts.map +0 -1
  262. package/dist/src/utils/todo-migration.js +0 -261
  263. package/dist/src/utils/todo-migration.js.map +0 -1
@@ -1,922 +0,0 @@
1
- /**
2
- * JSON-First TODO Management Tool
3
- *
4
- * Replaces markdown-based TODO management with structured JSON backend
5
- * for consistent LLM interactions and automatic scoring integration.
6
- *
7
- * IMPORTANT FOR AI ASSISTANTS: This tool requires the .mcp-adr-cache infrastructure
8
- * to be initialized first. Run `discover_existing_adrs` before using this tool.
9
- *
10
- * Cache Dependencies:
11
- * - Requires: .mcp-adr-cache/todo-data.json (main TODO storage)
12
- * - Requires: .mcp-adr-cache/knowledge-graph-snapshots.json (for intent tracking)
13
- * - Updates: .mcp-adr-cache/project-health-scores.json (task completion metrics)
14
- *
15
- * Key Features:
16
- * - JSON-first storage with automatic Markdown synchronization
17
- * - Automatic project health scoring integration
18
- * - Knowledge graph intent tracking
19
- * - Bidirectional TODO.md compatibility
20
- */
21
- import { z } from 'zod';
22
- import { McpAdrError } from '../types/index.js';
23
- import { TodoJsonManager } from '../utils/todo-json-manager.js';
24
- import { KnowledgeGraphManager } from '../utils/knowledge-graph-manager.js';
25
- // Remove unused import
26
- // Task operations schema
27
- const CreateTaskSchema = z.object({
28
- operation: z.literal('create_task'),
29
- projectPath: z.string().describe('Project root path'),
30
- title: z.string().describe('Task title'),
31
- description: z.string().optional().describe('Task description'),
32
- priority: z.enum(['low', 'medium', 'high', 'critical']).default('medium'),
33
- assignee: z.string().optional().describe('Task assignee'),
34
- dueDate: z.string().optional().describe('Due date (ISO string)'),
35
- category: z.string().optional().describe('Task category'),
36
- tags: z.array(z.string()).default([]).describe('Task tags'),
37
- dependencies: z.array(z.string()).default([]).describe('Task dependencies (IDs)'),
38
- intentId: z.string().optional().describe('Link to knowledge graph intent'),
39
- linkedAdrs: z.array(z.string()).default([]).describe('Related ADR files'),
40
- autoComplete: z.boolean().default(false).describe('Auto-complete when criteria met'),
41
- completionCriteria: z.string().optional().describe('Auto-completion rules')
42
- });
43
- const UpdateTaskSchema = z.object({
44
- operation: z.literal('update_task'),
45
- projectPath: z.string().describe('Project root path'),
46
- taskId: z.string().describe('Task ID to update'),
47
- updates: z.object({
48
- title: z.string().optional(),
49
- description: z.string().optional(),
50
- status: z.enum(['pending', 'in_progress', 'completed', 'blocked', 'cancelled']).optional(),
51
- priority: z.enum(['low', 'medium', 'high', 'critical']).optional(),
52
- assignee: z.string().optional(),
53
- dueDate: z.string().optional(),
54
- progressPercentage: z.number().min(0).max(100).optional(),
55
- notes: z.string().optional(),
56
- tags: z.array(z.string()).optional()
57
- }).describe('Fields to update'),
58
- reason: z.string().describe('Reason for update (for changelog)')
59
- });
60
- const BulkUpdateSchema = z.object({
61
- operation: z.literal('bulk_update'),
62
- projectPath: z.string().describe('Project root path'),
63
- updates: z.array(z.object({
64
- taskId: z.string(),
65
- status: z.enum(['pending', 'in_progress', 'completed', 'blocked', 'cancelled']).optional(),
66
- priority: z.enum(['low', 'medium', 'high', 'critical']).optional(),
67
- assignee: z.string().optional(),
68
- notes: z.string().optional()
69
- })).describe('Bulk status updates'),
70
- reason: z.string().describe('Reason for bulk update')
71
- });
72
- const GetTasksSchema = z.object({
73
- operation: z.literal('get_tasks'),
74
- projectPath: z.string().describe('Project root path'),
75
- filters: z.object({
76
- status: z.enum(['pending', 'in_progress', 'completed', 'blocked', 'cancelled']).optional(),
77
- priority: z.enum(['low', 'medium', 'high', 'critical']).optional(),
78
- assignee: z.string().optional(),
79
- category: z.string().optional(),
80
- hasDeadline: z.boolean().optional(),
81
- overdue: z.boolean().optional(),
82
- tags: z.array(z.string()).optional()
83
- }).optional().describe('Filter criteria'),
84
- sortBy: z.enum(['priority', 'dueDate', 'createdAt', 'updatedAt']).default('priority'),
85
- sortOrder: z.enum(['asc', 'desc']).default('desc'),
86
- limit: z.number().optional().describe('Maximum number of tasks to return'),
87
- showFullIds: z.boolean().optional().default(false).describe('Show full UUIDs instead of short IDs')
88
- });
89
- const GetAnalyticsSchema = z.object({
90
- operation: z.literal('get_analytics'),
91
- projectPath: z.string().describe('Project root path'),
92
- timeframe: z.enum(['day', 'week', 'month', 'all']).default('week').describe('Analysis timeframe'),
93
- includeVelocity: z.boolean().default(true).describe('Include velocity metrics'),
94
- includeScoring: z.boolean().default(true).describe('Include scoring metrics')
95
- });
96
- const ImportAdrTasksSchema = z.object({
97
- operation: z.literal('import_adr_tasks'),
98
- projectPath: z.string().describe('Project root path'),
99
- adrDirectory: z.string().default('docs/adrs').describe('ADR directory path'),
100
- intentId: z.string().optional().describe('Link imported tasks to intent'),
101
- preserveExisting: z.boolean().default(true).describe('Keep existing tasks'),
102
- autoLinkDependencies: z.boolean().default(true).describe('Auto-detect task dependencies')
103
- });
104
- const SyncWithKnowledgeGraphSchema = z.object({
105
- operation: z.literal('sync_knowledge_graph'),
106
- projectPath: z.string().describe('Project root path'),
107
- direction: z.enum(['to_kg', 'from_kg', 'bidirectional']).default('bidirectional'),
108
- intentId: z.string().optional().describe('Specific intent to sync with')
109
- });
110
- const SyncToMarkdownSchema = z.object({
111
- operation: z.literal('sync_to_markdown'),
112
- projectPath: z.string().describe('Project root path'),
113
- force: z.boolean().default(false).describe('Force sync even if markdown is newer')
114
- });
115
- const ImportFromMarkdownSchema = z.object({
116
- operation: z.literal('import_from_markdown'),
117
- projectPath: z.string().describe('Project root path'),
118
- mergeStrategy: z.enum(['overwrite', 'merge', 'preserve_json']).default('merge'),
119
- backupExisting: z.boolean().default(true).describe('Create backup before import')
120
- });
121
- const FindTaskSchema = z.object({
122
- operation: z.literal('find_task'),
123
- projectPath: z.string().describe('Project root path'),
124
- query: z.string().describe('Search query: partial ID, title, or description'),
125
- searchType: z.enum(['id', 'title', 'description', 'all']).default('all').describe('What to search in')
126
- });
127
- const ResumeTodoListSchema = z.object({
128
- operation: z.literal('resume_todo_list'),
129
- projectPath: z.string().describe('Project root path'),
130
- analyzeRecent: z.boolean().default(true).describe('Analyze recent changes and git commits'),
131
- includeContext: z.boolean().default(true).describe('Include project context and ADR status'),
132
- showNextActions: z.boolean().default(true).describe('Suggest next actionable steps'),
133
- checkDeploymentReadiness: z.boolean().default(true).describe('Check if any tasks are deployment-ready')
134
- });
135
- // Main operation schema
136
- const TodoManagementV2Schema = z.union([
137
- CreateTaskSchema,
138
- UpdateTaskSchema,
139
- BulkUpdateSchema,
140
- GetTasksSchema,
141
- GetAnalyticsSchema,
142
- ImportAdrTasksSchema,
143
- SyncWithKnowledgeGraphSchema,
144
- SyncToMarkdownSchema,
145
- ImportFromMarkdownSchema,
146
- FindTaskSchema,
147
- ResumeTodoListSchema
148
- ]);
149
- /**
150
- * Main TODO management function with JSON backend
151
- */
152
- export async function manageTodoV2(args) {
153
- try {
154
- const validatedArgs = TodoManagementV2Schema.parse(args);
155
- const todoManager = new TodoJsonManager(validatedArgs.projectPath);
156
- const kgManager = new KnowledgeGraphManager();
157
- switch (validatedArgs.operation) {
158
- case 'create_task': {
159
- const taskId = await todoManager.createTask({
160
- title: validatedArgs.title,
161
- description: validatedArgs.description,
162
- priority: validatedArgs.priority,
163
- assignee: validatedArgs.assignee,
164
- dueDate: validatedArgs.dueDate,
165
- category: validatedArgs.category,
166
- tags: validatedArgs.tags,
167
- dependencies: validatedArgs.dependencies,
168
- intentId: validatedArgs.intentId,
169
- linkedAdrs: validatedArgs.linkedAdrs,
170
- autoComplete: validatedArgs.autoComplete,
171
- completionCriteria: validatedArgs.completionCriteria
172
- });
173
- return {
174
- content: [{
175
- type: 'text',
176
- text: `✅ Task created successfully!\n\n**Task ID**: ${taskId}\n**Title**: ${validatedArgs.title}\n**Priority**: ${validatedArgs.priority}\n**Status**: pending\n\n*Task has been added to JSON backend and will sync to TODO.md automatically.*`
177
- }]
178
- };
179
- }
180
- case 'update_task': {
181
- // Resolve partial ID to full ID if needed
182
- let taskId = validatedArgs.taskId;
183
- // If taskId looks like a partial ID (less than full UUID length), try to find the full ID
184
- if (taskId.length < 36) {
185
- const data = await todoManager.loadTodoData();
186
- const tasks = Object.values(data.tasks);
187
- const matchingTasks = tasks.filter(task => task.id.startsWith(taskId.toLowerCase()));
188
- if (matchingTasks.length === 0) {
189
- return {
190
- content: [{
191
- type: 'text',
192
- text: `❌ No task found with ID starting with "${taskId}"\n\n**Suggestions:**\n1. Use the \`find_task\` operation to search for tasks\n2. Use \`get_tasks\` with \`showFullIds: true\` to see all full IDs\n3. Check that the task ID is correct`
193
- }]
194
- };
195
- }
196
- else if (matchingTasks.length > 1) {
197
- const taskList = matchingTasks.map(task => `- **${task.title}** (ID: \`${task.id}\`)`).join('\n');
198
- return {
199
- content: [{
200
- type: 'text',
201
- text: `❌ Multiple tasks found with ID starting with "${taskId}"\n\n**Matching tasks:**\n${taskList}\n\n**Please use a more specific ID or the full UUID.**`
202
- }]
203
- };
204
- }
205
- taskId = matchingTasks[0].id;
206
- }
207
- // Filter out undefined values
208
- const cleanUpdates = {};
209
- if (validatedArgs.updates.title !== undefined)
210
- cleanUpdates.title = validatedArgs.updates.title;
211
- if (validatedArgs.updates.description !== undefined)
212
- cleanUpdates.description = validatedArgs.updates.description;
213
- if (validatedArgs.updates.status !== undefined)
214
- cleanUpdates.status = validatedArgs.updates.status;
215
- if (validatedArgs.updates.priority !== undefined)
216
- cleanUpdates.priority = validatedArgs.updates.priority;
217
- if (validatedArgs.updates.assignee !== undefined)
218
- cleanUpdates.assignee = validatedArgs.updates.assignee;
219
- if (validatedArgs.updates.dueDate !== undefined)
220
- cleanUpdates.dueDate = validatedArgs.updates.dueDate;
221
- if (validatedArgs.updates.progressPercentage !== undefined)
222
- cleanUpdates.progressPercentage = validatedArgs.updates.progressPercentage;
223
- if (validatedArgs.updates.notes !== undefined)
224
- cleanUpdates.notes = validatedArgs.updates.notes;
225
- if (validatedArgs.updates.tags !== undefined)
226
- cleanUpdates.tags = validatedArgs.updates.tags;
227
- await todoManager.updateTask({
228
- taskId: taskId,
229
- updates: cleanUpdates,
230
- reason: validatedArgs.reason,
231
- triggeredBy: 'tool'
232
- });
233
- return {
234
- content: [{
235
- type: 'text',
236
- text: `✅ Task updated successfully!\n\n**Task ID**: ${taskId}\n**Original Input**: ${validatedArgs.taskId}\n**Updates**: ${Object.keys(validatedArgs.updates).filter(k => validatedArgs.updates[k] !== undefined).join(', ')}\n**Reason**: ${validatedArgs.reason}\n\n*Changes synced to JSON backend and TODO.md.*`
237
- }]
238
- };
239
- }
240
- case 'bulk_update': {
241
- let updateCount = 0;
242
- for (const update of validatedArgs.updates) {
243
- // Filter out undefined values
244
- const cleanUpdates = {};
245
- if (update.status !== undefined)
246
- cleanUpdates.status = update.status;
247
- if (update.priority !== undefined)
248
- cleanUpdates.priority = update.priority;
249
- if (update.assignee !== undefined)
250
- cleanUpdates.assignee = update.assignee;
251
- if (update.notes !== undefined)
252
- cleanUpdates.notes = update.notes;
253
- await todoManager.updateTask({
254
- taskId: update.taskId,
255
- updates: cleanUpdates,
256
- reason: validatedArgs.reason,
257
- triggeredBy: 'tool'
258
- });
259
- updateCount++;
260
- }
261
- return {
262
- content: [{
263
- type: 'text',
264
- text: `✅ Bulk update completed!\n\n**Tasks Updated**: ${updateCount}\n**Reason**: ${validatedArgs.reason}\n\n*All changes synced to JSON backend and TODO.md.*`
265
- }]
266
- };
267
- }
268
- case 'get_tasks': {
269
- const data = await todoManager.loadTodoData();
270
- let tasks = Object.values(data.tasks);
271
- // Apply filters
272
- if (validatedArgs.filters) {
273
- const filters = validatedArgs.filters;
274
- if (filters.status) {
275
- tasks = tasks.filter(t => t.status === filters.status);
276
- }
277
- if (filters.priority) {
278
- tasks = tasks.filter(t => t.priority === filters.priority);
279
- }
280
- if (filters.assignee) {
281
- tasks = tasks.filter(t => t.assignee === filters.assignee);
282
- }
283
- if (filters.category) {
284
- tasks = tasks.filter(t => t.category === filters.category);
285
- }
286
- if (filters.hasDeadline) {
287
- tasks = tasks.filter(t => Boolean(t.dueDate));
288
- }
289
- if (filters.overdue) {
290
- const now = new Date();
291
- tasks = tasks.filter(t => t.dueDate && new Date(t.dueDate) < now && t.status !== 'completed');
292
- }
293
- if (filters.tags && filters.tags.length > 0) {
294
- tasks = tasks.filter(t => filters.tags.some(tag => t.tags.includes(tag)));
295
- }
296
- }
297
- // Sort tasks
298
- tasks.sort((a, b) => {
299
- const priorityOrder = { critical: 4, high: 3, medium: 2, low: 1 };
300
- switch (validatedArgs.sortBy) {
301
- case 'priority':
302
- return validatedArgs.sortOrder === 'desc'
303
- ? priorityOrder[b.priority] - priorityOrder[a.priority]
304
- : priorityOrder[a.priority] - priorityOrder[b.priority];
305
- case 'dueDate':
306
- if (!a.dueDate && !b.dueDate)
307
- return 0;
308
- if (!a.dueDate)
309
- return 1;
310
- if (!b.dueDate)
311
- return -1;
312
- return validatedArgs.sortOrder === 'desc'
313
- ? new Date(b.dueDate).getTime() - new Date(a.dueDate).getTime()
314
- : new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime();
315
- case 'createdAt':
316
- return validatedArgs.sortOrder === 'desc'
317
- ? new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
318
- : new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
319
- case 'updatedAt':
320
- return validatedArgs.sortOrder === 'desc'
321
- ? new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
322
- : new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
323
- default:
324
- return 0;
325
- }
326
- });
327
- // Apply limit
328
- if (validatedArgs.limit) {
329
- tasks = tasks.slice(0, validatedArgs.limit);
330
- }
331
- const taskList = tasks.map(task => {
332
- const dueDateStr = task.dueDate ? new Date(task.dueDate).toLocaleDateString() : 'No due date';
333
- const isOverdue = task.dueDate && new Date(task.dueDate) < new Date() && task.status !== 'completed';
334
- const taskId = (validatedArgs.showFullIds ?? false) ? task.id : task.id.substring(0, 8);
335
- return `**${task.title}** (ID: ${taskId})\n` +
336
- ` Status: ${task.status} | Priority: ${task.priority}\n` +
337
- ` ${task.assignee ? `Assignee: ${task.assignee} | ` : ''}Due: ${dueDateStr} ${isOverdue ? '🔴 OVERDUE' : ''}\n` +
338
- ` ${task.tags.length > 0 ? `Tags: ${task.tags.join(', ')} | ` : ''}Progress: ${task.progressPercentage}%\n` +
339
- ` ${task.description || 'No description'}\n`;
340
- }).join('\n');
341
- return {
342
- content: [{
343
- type: 'text',
344
- text: `# 📋 Task List (${tasks.length} tasks)\n\n${taskList || 'No tasks match the criteria.'}`
345
- }]
346
- };
347
- }
348
- case 'get_analytics': {
349
- const analytics = await todoManager.getAnalytics();
350
- const { metrics, trends, recommendations } = analytics;
351
- let analyticsText = `# 📊 TODO Analytics\n\n`;
352
- analyticsText += `## Task Metrics\n`;
353
- analyticsText += `- **Total Tasks**: ${metrics.totalTasks}\n`;
354
- analyticsText += `- **Completed**: ${metrics.completedTasks} (${metrics.completionPercentage.toFixed(1)}%)\n`;
355
- analyticsText += `- **Priority Score**: ${metrics.priorityWeightedScore.toFixed(1)}%\n`;
356
- analyticsText += `- **Critical Remaining**: ${metrics.criticalTasksRemaining}\n`;
357
- analyticsText += `- **Blocked Tasks**: ${metrics.blockedTasksCount}\n`;
358
- analyticsText += `- **Average Task Age**: ${metrics.averageTaskAge.toFixed(1)} days\n\n`;
359
- if (validatedArgs.includeVelocity) {
360
- analyticsText += `## Velocity Metrics\n`;
361
- analyticsText += `- **Tasks/Week**: ${metrics.velocityMetrics.tasksCompletedLastWeek}\n`;
362
- analyticsText += `- **Avg Completion Time**: ${metrics.velocityMetrics.averageCompletionTime.toFixed(1)} hours\n\n`;
363
- }
364
- if (recommendations.length > 0) {
365
- analyticsText += `## Recommendations\n`;
366
- analyticsText += recommendations.map(rec => `- ${rec}`).join('\n');
367
- analyticsText += '\n\n';
368
- }
369
- if (trends.length > 0) {
370
- analyticsText += `## Recent Score History\n`;
371
- analyticsText += trends.slice(-5).map(trend => `- ${new Date(trend.timestamp).toLocaleDateString()}: ${trend.score.toFixed(1)}% (${trend.trigger})`).join('\n');
372
- }
373
- return {
374
- content: [{
375
- type: 'text',
376
- text: analyticsText
377
- }]
378
- };
379
- }
380
- case 'import_adr_tasks': {
381
- const adrDirectory = validatedArgs.adrDirectory;
382
- const intentId = validatedArgs.intentId;
383
- const preserveExisting = validatedArgs.preserveExisting;
384
- const autoLinkDependencies = validatedArgs.autoLinkDependencies;
385
- // Discover ADRs in the directory
386
- const { discoverAdrsInDirectory } = await import('../utils/adr-discovery.js');
387
- const discoveryResult = await discoverAdrsInDirectory(adrDirectory, true, // include content for task extraction
388
- validatedArgs.projectPath);
389
- if (discoveryResult.totalAdrs === 0) {
390
- return {
391
- content: [{
392
- type: 'text',
393
- text: `⚠️ No ADRs found in directory: ${adrDirectory}\n\n**Recommendations:**\n${discoveryResult.recommendations.join('\n')}`
394
- }]
395
- };
396
- }
397
- // Smart completion preservation: Load existing data before any operations
398
- // This must happen BEFORE any data wiping for preserveExisting: false
399
- const existingData = await todoManager.loadTodoData();
400
- const existingTasksByTitle = new Map();
401
- // Create a lookup map of existing tasks by title for smart matching
402
- Object.values(existingData.tasks).forEach(task => {
403
- const normalizedTitle = task.title.toLowerCase().trim();
404
- existingTasksByTitle.set(normalizedTitle, task);
405
- });
406
- // If preserveExisting is false, we need to clear existing data first
407
- // but we've already captured the completion states above
408
- if (!preserveExisting) {
409
- // Clear existing tasks but preserve the sections structure
410
- const freshData = await todoManager.loadTodoData();
411
- freshData.tasks = {};
412
- freshData.sections.forEach(section => {
413
- section.tasks = [];
414
- });
415
- await todoManager.saveTodoData(freshData, false); // Don't sync to markdown yet
416
- }
417
- // Extract tasks from each ADR
418
- const extractedTasks = await extractTasksFromAdrs(discoveryResult.adrs, adrDirectory, intentId, autoLinkDependencies);
419
- // Import tasks into JSON backend with smart completion preservation
420
- let importedCount = 0;
421
- let skippedCount = 0;
422
- let preservedCompletions = 0;
423
- const importResults = [];
424
- for (const task of extractedTasks) {
425
- try {
426
- // Check if task already exists (by title and ADR reference) - only relevant when preserveExisting is true
427
- let existingTask = null;
428
- if (preserveExisting) {
429
- const currentData = await todoManager.loadTodoData();
430
- existingTask = Object.values(currentData.tasks).find(t => t.title === task.title &&
431
- t.linkedAdrs.some(adr => task.linkedAdrs.includes(adr)));
432
- }
433
- if (existingTask && preserveExisting) {
434
- skippedCount++;
435
- importResults.push(`⏭️ Skipped: "${task.title}" (already exists)`);
436
- continue;
437
- }
438
- // Smart completion preservation: match by title even if preserveExisting is false
439
- const normalizedTitle = task.title.toLowerCase().trim();
440
- const previousTask = existingTasksByTitle.get(normalizedTitle);
441
- let taskToCreate = { ...task };
442
- if (previousTask && (previousTask.status === 'completed' || previousTask.progressPercentage > 0)) {
443
- // Preserve completion status and progress from previous task
444
- taskToCreate = {
445
- ...task,
446
- status: previousTask.status,
447
- progressPercentage: previousTask.progressPercentage,
448
- completedAt: previousTask.completedAt,
449
- notes: previousTask.notes,
450
- assignee: previousTask.assignee || task.assignee,
451
- };
452
- preservedCompletions++;
453
- importResults.push(`🔄 Imported with preserved completion: "${task.title}" (${previousTask.status}, ${previousTask.progressPercentage}%)`);
454
- }
455
- else {
456
- importResults.push(`✅ Imported: "${task.title}" (${task.priority} priority)`);
457
- }
458
- // Create the task with preserved completion if applicable
459
- await todoManager.createTask({
460
- title: taskToCreate.title,
461
- description: taskToCreate.description,
462
- status: taskToCreate.status,
463
- priority: taskToCreate.priority,
464
- category: taskToCreate.category,
465
- tags: taskToCreate.tags,
466
- dependencies: taskToCreate.dependencies,
467
- linkedAdrs: taskToCreate.linkedAdrs,
468
- assignee: taskToCreate.assignee,
469
- progressPercentage: taskToCreate.progressPercentage,
470
- notes: taskToCreate.notes,
471
- completedAt: taskToCreate.completedAt,
472
- ...(intentId && { intentId })
473
- });
474
- importedCount++;
475
- }
476
- catch (error) {
477
- importResults.push(`❌ Failed: "${task.title}" - ${error instanceof Error ? error.message : String(error)}`);
478
- }
479
- }
480
- return {
481
- content: [{
482
- type: 'text',
483
- text: `# ✅ ADR Task Import Completed
484
-
485
- ## Import Summary
486
- - **ADRs Scanned**: ${discoveryResult.totalAdrs}
487
- - **Tasks Extracted**: ${extractedTasks.length}
488
- - **Tasks Imported**: ${importedCount}
489
- - **Tasks Skipped**: ${skippedCount}
490
- - **Completions Preserved**: ${preservedCompletions}
491
- - **Preserve Existing**: ${preserveExisting}
492
- - **Auto-Link Dependencies**: ${autoLinkDependencies}
493
-
494
- ## ADR Status Overview
495
- ${Object.entries(discoveryResult.summary.byStatus)
496
- .map(([status, count]) => `- **${status}**: ${count} ADRs`)
497
- .join('\n')}
498
-
499
- ## Import Results
500
- ${importResults.join('\n')}
501
-
502
- ${preservedCompletions > 0 ? `
503
- ## 🎯 Smart Completion Preservation
504
- ✅ **${preservedCompletions} task completions preserved** during import!
505
- Tasks with the same title retained their completion status and progress.
506
- ` : ''}
507
-
508
- ## Next Steps
509
- 1. **View Tasks**: Use \`get_tasks\` operation to see imported tasks
510
- 2. **Sync to Markdown**: Tasks will be automatically synced to TODO.md
511
- 3. **Update Status**: Use \`update_task\` operation to track progress
512
- 4. **Link Knowledge Graph**: Tasks are ${intentId ? `linked to intent ${intentId}` : 'ready for intent linking'}
513
-
514
- *All tasks have been imported into the JSON backend and are ready for the complete TODO management workflow.*`
515
- }]
516
- };
517
- }
518
- case 'sync_knowledge_graph': {
519
- const data = await todoManager.loadTodoData();
520
- // Sync task completion status to knowledge graph
521
- for (const task of Object.values(data.tasks)) {
522
- if (task.intentId) {
523
- await kgManager.updateTodoSnapshot(task.intentId, `Task ${task.status}: ${task.title} (${task.progressPercentage}%)`);
524
- }
525
- }
526
- return {
527
- content: [{
528
- type: 'text',
529
- text: `✅ Knowledge graph sync completed!\n\n**Direction**: ${validatedArgs.direction}\n**Tasks with Intent Links**: ${Object.values(data.tasks).filter(t => t.intentId).length}\n\n*Task progress has been synced to the knowledge graph.*`
530
- }]
531
- };
532
- }
533
- case 'sync_to_markdown': {
534
- await todoManager.convertToMarkdown();
535
- return {
536
- content: [{
537
- type: 'text',
538
- text: `✅ Markdown sync completed!\n\n*TODO.md has been updated with the latest JSON data including health dashboard and formatted task lists.*`
539
- }]
540
- };
541
- }
542
- case 'import_from_markdown': {
543
- if (validatedArgs.backupExisting) {
544
- // Create backup of existing JSON
545
- const data = await todoManager.loadTodoData();
546
- const backupPath = `${validatedArgs.projectPath}/.mcp-adr-cache/todo-data-backup-${Date.now()}.json`;
547
- const fs = await import('fs/promises');
548
- await fs.writeFile(backupPath, JSON.stringify(data, null, 2));
549
- }
550
- await todoManager.importFromMarkdown();
551
- return {
552
- content: [{
553
- type: 'text',
554
- text: `✅ Markdown import completed!\n\n**Strategy**: ${validatedArgs.mergeStrategy}\n**Backup Created**: ${validatedArgs.backupExisting}\n\n*TODO.md has been parsed and imported into the JSON backend.*`
555
- }]
556
- };
557
- }
558
- case 'find_task': {
559
- const data = await todoManager.loadTodoData();
560
- const tasks = Object.values(data.tasks);
561
- const query = validatedArgs.query.toLowerCase();
562
- let matchingTasks = tasks.filter(task => {
563
- switch (validatedArgs.searchType) {
564
- case 'id':
565
- return task.id.toLowerCase().includes(query);
566
- case 'title':
567
- return task.title.toLowerCase().includes(query);
568
- case 'description':
569
- return task.description?.toLowerCase().includes(query);
570
- case 'all':
571
- default:
572
- return task.id.toLowerCase().includes(query) ||
573
- task.title.toLowerCase().includes(query) ||
574
- task.description?.toLowerCase().includes(query) ||
575
- task.tags.some(tag => tag.toLowerCase().includes(query));
576
- }
577
- });
578
- if (matchingTasks.length === 0) {
579
- return {
580
- content: [{
581
- type: 'text',
582
- text: `❌ No tasks found matching "${validatedArgs.query}"\n\n**Search Type**: ${validatedArgs.searchType}\n**Total Tasks**: ${tasks.length}\n\n*Try using a different query or search type.*`
583
- }]
584
- };
585
- }
586
- const taskList = matchingTasks.map(task => {
587
- const dueDateStr = task.dueDate ? new Date(task.dueDate).toLocaleDateString() : 'No due date';
588
- const isOverdue = task.dueDate && new Date(task.dueDate) < new Date() && task.status !== 'completed';
589
- return `**${task.title}**\n` +
590
- ` 🆔 **Full ID**: \`${task.id}\`\n` +
591
- ` 📋 **Short ID**: \`${task.id.substring(0, 8)}\`\n` +
592
- ` 📊 Status: ${task.status} | Priority: ${task.priority}\n` +
593
- ` ${task.assignee ? `👤 Assignee: ${task.assignee} | ` : ''}📅 Due: ${dueDateStr} ${isOverdue ? '🔴 OVERDUE' : ''}\n` +
594
- ` ${task.tags.length > 0 ? `🏷️ Tags: ${task.tags.join(', ')} | ` : ''}📈 Progress: ${task.progressPercentage}%\n` +
595
- ` 📝 ${task.description || 'No description'}\n`;
596
- }).join('\n');
597
- return {
598
- content: [{
599
- type: 'text',
600
- text: `# 🔍 Search Results (${matchingTasks.length} found)\n\n**Query**: "${validatedArgs.query}"\n**Search Type**: ${validatedArgs.searchType}\n\n${taskList}\n\n💡 **Tip**: Copy the Full ID to use with update_task operation.`
601
- }]
602
- };
603
- }
604
- case 'resume_todo_list': {
605
- const data = await todoManager.loadTodoData();
606
- const tasks = Object.values(data.tasks);
607
- const analytics = await todoManager.getAnalytics();
608
- // Get recent activity from task change logs
609
- const recentActivity = Object.values(data.tasks)
610
- .flatMap(task => task.changeLog || [])
611
- .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
612
- .slice(0, 10)
613
- .map((entry) => `- ${new Date(entry.timestamp).toLocaleDateString()}: ${entry.action} - ${entry.details}`)
614
- .join('\n');
615
- // Analyze current state
616
- const inProgressTasks = tasks.filter(t => t.status === 'in_progress');
617
- const pendingHighPriority = tasks.filter(t => t.status === 'pending' && ['high', 'critical'].includes(t.priority));
618
- const overdueTasks = tasks.filter(t => t.dueDate && new Date(t.dueDate) < new Date() && t.status !== 'completed');
619
- const blockedTasks = tasks.filter(t => t.status === 'blocked');
620
- // Check deployment readiness
621
- let deploymentReadyTasks = [];
622
- let deploymentGuidance = '';
623
- if (validatedArgs.checkDeploymentReadiness) {
624
- deploymentReadyTasks = tasks.filter(t => t.status === 'completed' &&
625
- (t.tags.includes('deployment') || t.category === 'Deployment' ||
626
- t.title.toLowerCase().includes('deploy') || t.description?.toLowerCase().includes('deploy')));
627
- if (deploymentReadyTasks.length > 0) {
628
- deploymentGuidance = `\n## 🚀 Deployment Status\n**${deploymentReadyTasks.length} deployment-ready tasks found!**\n` +
629
- deploymentReadyTasks.map(t => `- ✅ ${t.title}`).join('\n') +
630
- `\n\n💡 **Tip**: Consider running deployment validation and using smart git push for these completed tasks.`;
631
- }
632
- }
633
- // Generate context summary
634
- let contextSummary = '';
635
- if (validatedArgs.includeContext) {
636
- const fs = await import('fs/promises');
637
- const path = await import('path');
638
- // Check for recent git commits
639
- try {
640
- const { execSync } = await import('child_process');
641
- const recentCommits = execSync('git log --oneline -5', {
642
- cwd: validatedArgs.projectPath,
643
- encoding: 'utf8'
644
- }).trim().split('\n').slice(0, 3);
645
- contextSummary += `\n## 📝 Recent Git Activity\n${recentCommits.map(commit => `- ${commit}`).join('\n')}\n`;
646
- }
647
- catch (error) {
648
- // Git not available or no commits
649
- }
650
- // Check ADR status
651
- try {
652
- const adrPath = path.join(validatedArgs.projectPath, 'docs/adrs');
653
- const adrFiles = await fs.readdir(adrPath).catch(() => []);
654
- if (adrFiles.length > 0) {
655
- contextSummary += `\n## 📋 ADR Context\n- **${adrFiles.length} ADRs** found in docs/adrs\n- Last TODO/ADR sync: ${data.metadata.lastAdrSync || 'Never'}\n`;
656
- }
657
- }
658
- catch (error) {
659
- // ADR directory not found
660
- }
661
- }
662
- // Generate next actions
663
- let nextActions = '';
664
- if (validatedArgs.showNextActions) {
665
- const suggestions = [];
666
- if (inProgressTasks.length > 0) {
667
- suggestions.push(`Continue working on ${inProgressTasks.length} in-progress task(s)`);
668
- }
669
- if (overdueTasks.length > 0) {
670
- suggestions.push(`Address ${overdueTasks.length} overdue task(s) - these need immediate attention`);
671
- }
672
- if (blockedTasks.length > 0) {
673
- suggestions.push(`Unblock ${blockedTasks.length} blocked task(s) - resolve dependencies`);
674
- }
675
- if (pendingHighPriority.length > 0) {
676
- suggestions.push(`Start ${pendingHighPriority.length} high-priority pending task(s)`);
677
- }
678
- if (analytics.metrics.completionPercentage > 80) {
679
- suggestions.push('Project is nearing completion - consider deployment preparation');
680
- }
681
- if (deploymentReadyTasks.length > 0) {
682
- suggestions.push('Review and deploy completed tasks using smart git push');
683
- }
684
- if (suggestions.length > 0) {
685
- nextActions = `\n## 🎯 Recommended Next Actions\n${suggestions.map((s, i) => `${i + 1}. ${s}`).join('\n')}\n`;
686
- }
687
- }
688
- const resumeReport = `# 🔄 Resume TODO List - Session Context
689
-
690
- ## 📊 Current Status Summary
691
- - **Total Tasks**: ${tasks.length}
692
- - **Completion Rate**: ${analytics.metrics.completionPercentage.toFixed(1)}%
693
- - **In Progress**: ${inProgressTasks.length} tasks
694
- - **Pending High Priority**: ${pendingHighPriority.length} tasks
695
- - **Overdue**: ${overdueTasks.length} tasks ${overdueTasks.length > 0 ? '🔴' : '✅'}
696
- - **Blocked**: ${blockedTasks.length} tasks ${blockedTasks.length > 0 ? '⚠️' : '✅'}
697
-
698
- ## 🔥 Immediate Attention Required
699
- ${overdueTasks.length > 0 ?
700
- overdueTasks.map(t => `- **${t.title}** (Due: ${new Date(t.dueDate).toLocaleDateString()}) - ${t.priority} priority`).join('\n') :
701
- '✅ No overdue tasks'}
702
-
703
- ## 🚧 Currently In Progress
704
- ${inProgressTasks.length > 0 ?
705
- inProgressTasks.map(t => `- **${t.title}** (${t.progressPercentage}% complete) - ${t.assignee || 'Unassigned'}`).join('\n') :
706
- '📝 No tasks currently in progress'}
707
-
708
- ## ⚠️ Blocked Tasks
709
- ${blockedTasks.length > 0 ?
710
- blockedTasks.map(t => `- **${t.title}** - ${t.notes || 'No blocking reason specified'}`).join('\n') :
711
- '✅ No blocked tasks'}
712
-
713
- ${contextSummary}
714
-
715
- ## 📈 Recent Activity
716
- ${recentActivity || 'No recent TODO activity'}
717
-
718
- ${nextActions}
719
-
720
- ${deploymentGuidance}
721
-
722
- ## 💡 Session Resume Tips
723
- 1. Use \`get_tasks\` with filters to see specific task categories
724
- 2. Use \`find_task\` to quickly locate tasks by title or partial ID
725
- 3. Update task status as you work: \`update_task\` with progress notes
726
- 4. Check \`get_analytics\` for detailed progress metrics
727
- 5. Run smart git push when tasks are deployment-ready
728
-
729
- ---
730
- *Ready to continue where you left off! Use the recommended actions above to prioritize your work.*`;
731
- return {
732
- content: [{
733
- type: 'text',
734
- text: resumeReport
735
- }]
736
- };
737
- }
738
- default:
739
- throw new McpAdrError(`Unknown operation: ${validatedArgs.operation}`, 'INVALID_INPUT');
740
- }
741
- }
742
- catch (error) {
743
- if (error instanceof z.ZodError) {
744
- throw new McpAdrError(`Invalid input: ${error.errors.map(e => e.message).join(', ')}`, 'INVALID_INPUT');
745
- }
746
- throw new McpAdrError(`TODO management failed: ${error instanceof Error ? error.message : String(error)}`, 'TODO_MANAGEMENT_ERROR');
747
- }
748
- }
749
- /**
750
- * Extract implementation tasks from ADR content
751
- */
752
- async function extractTasksFromAdrs(adrs, _adrDirectory, _intentId, autoLinkDependencies = true) {
753
- const extractedTasks = [];
754
- for (const adr of adrs) {
755
- if (!adr.content)
756
- continue;
757
- // Extract tasks from Decision and Consequences sections
758
- const tasks = extractTasksFromAdrContent(adr);
759
- // Add ADR metadata to each task
760
- for (const task of tasks) {
761
- task.linkedAdrs = [adr.path];
762
- task.category = task.category || 'ADR Implementation';
763
- task.tags = task.tags || [];
764
- // Add ADR-specific tags
765
- if (adr.metadata?.number) {
766
- task.tags.push(`adr-${adr.metadata.number}`);
767
- }
768
- if (adr.status) {
769
- task.tags.push(`status-${adr.status}`);
770
- }
771
- // Set priority based on ADR status and content
772
- if (!task.priority) {
773
- task.priority = determinePriorityFromAdr(adr);
774
- }
775
- extractedTasks.push(task);
776
- }
777
- }
778
- // Link dependencies between ADRs if requested
779
- if (autoLinkDependencies) {
780
- linkAdrDependencies(extractedTasks, adrs);
781
- }
782
- return extractedTasks;
783
- }
784
- /**
785
- * Extract tasks from ADR content sections
786
- */
787
- function extractTasksFromAdrContent(adr) {
788
- const tasks = [];
789
- const content = adr.content || '';
790
- // Look for implementation tasks in Decision section
791
- if (adr.decision && typeof adr.decision === 'string') {
792
- const decisionTasks = extractTasksFromText(adr.decision, 'Implementation', 'high');
793
- tasks.push(...decisionTasks);
794
- }
795
- // Look for tasks in Consequences section
796
- if (adr.consequences && typeof adr.consequences === 'string') {
797
- const consequenceTasks = extractTasksFromText(adr.consequences, 'Validation', 'medium');
798
- tasks.push(...consequenceTasks);
799
- }
800
- // Look for explicit task lists in content
801
- const taskListRegex = /(?:##?\s*(?:tasks?|todo|implementation|action items?)\s*\n)([\s\S]*?)(?=\n##|\n#|$)/gi;
802
- let match;
803
- while ((match = taskListRegex.exec(content)) !== null) {
804
- const taskSection = match[1];
805
- if (taskSection) {
806
- const sectionTasks = extractTasksFromText(taskSection, 'Task', 'medium');
807
- tasks.push(...sectionTasks);
808
- }
809
- }
810
- // If no explicit tasks found, create a general implementation task
811
- if (tasks.length === 0) {
812
- tasks.push({
813
- title: `Implement ${adr.title}`,
814
- description: `Implement the architectural decision: ${adr.title}`,
815
- priority: 'medium',
816
- category: 'ADR Implementation',
817
- tags: ['implementation'],
818
- dependencies: [],
819
- linkedAdrs: []
820
- });
821
- }
822
- return tasks;
823
- }
824
- /**
825
- * Extract tasks from text content using patterns
826
- */
827
- function extractTasksFromText(text, defaultCategory, defaultPriority) {
828
- const tasks = [];
829
- // Look for bullet points that look like tasks
830
- const taskPatterns = [
831
- /[-*+]\s+(.+?)(?:\n|$)/g,
832
- /\d+\.\s+(.+?)(?:\n|$)/g,
833
- /(?:must|should|will|need to|implement|create|build|develop|configure|setup|establish)\s+(.+?)(?:\.|$)/gi
834
- ];
835
- for (const pattern of taskPatterns) {
836
- let match;
837
- while ((match = pattern.exec(text)) !== null) {
838
- const taskText = match[1]?.trim();
839
- if (!taskText || taskText.length < 10 || taskText.length > 200)
840
- continue; // Filter out very short/long matches
841
- // Determine priority from keywords
842
- let priority = defaultPriority;
843
- if (/critical|urgent|must|security|breaking/.test(taskText.toLowerCase())) {
844
- priority = 'critical';
845
- }
846
- else if (/important|should|key|major/.test(taskText.toLowerCase())) {
847
- priority = 'high';
848
- }
849
- else if (/nice|could|minor|optional/.test(taskText.toLowerCase())) {
850
- priority = 'low';
851
- }
852
- // Extract assignee if mentioned
853
- let assignee;
854
- const assigneeMatch = taskText.match(/@(\w+)|assigned to (\w+)|by (\w+)/i);
855
- if (assigneeMatch) {
856
- assignee = assigneeMatch[1] || assigneeMatch[2] || assigneeMatch[3];
857
- }
858
- tasks.push({
859
- title: taskText.charAt(0).toUpperCase() + taskText.slice(1), // Capitalize first letter
860
- description: `Task extracted from ADR: ${taskText}`,
861
- priority,
862
- category: defaultCategory,
863
- tags: [],
864
- dependencies: [],
865
- linkedAdrs: [],
866
- ...(assignee && { assignee })
867
- });
868
- }
869
- }
870
- return tasks;
871
- }
872
- /**
873
- * Determine priority based on ADR status and content
874
- */
875
- function determinePriorityFromAdr(adr) {
876
- const status = adr.status?.toLowerCase() || '';
877
- const content = (adr.content || '').toLowerCase();
878
- // High priority for accepted/active ADRs
879
- if (['accepted', 'active', 'approved'].includes(status)) {
880
- return 'high';
881
- }
882
- // Critical for security/breaking changes
883
- if (/security|breaking|critical|urgent/.test(content)) {
884
- return 'critical';
885
- }
886
- // Low priority for deprecated/superseded
887
- if (['deprecated', 'superseded', 'rejected'].includes(status)) {
888
- return 'low';
889
- }
890
- // Default to medium
891
- return 'medium';
892
- }
893
- /**
894
- * Link dependencies between ADR tasks
895
- */
896
- function linkAdrDependencies(tasks, adrs) {
897
- // Simple dependency linking based on ADR numbers and references
898
- for (const task of tasks) {
899
- const taskAdr = adrs.find(adr => task.linkedAdrs.includes(adr.path));
900
- if (!taskAdr)
901
- continue;
902
- // Look for references to other ADRs in the content
903
- const content = taskAdr.content || '';
904
- const adrReferences = content.match(/adr[-_]?(\d+)/gi) || [];
905
- for (const ref of adrReferences) {
906
- const refNumber = ref.match(/(\d+)/)?.[1];
907
- if (!refNumber || refNumber === taskAdr.metadata?.number)
908
- continue;
909
- // Find tasks from the referenced ADR
910
- const referencedAdr = adrs.find(adr => adr.metadata?.number === refNumber);
911
- if (!referencedAdr)
912
- continue;
913
- const referencedTasks = tasks.filter(t => t.linkedAdrs.includes(referencedAdr.path));
914
- for (const refTask of referencedTasks) {
915
- if (!task.dependencies.includes(refTask.title)) {
916
- task.dependencies.push(refTask.title);
917
- }
918
- }
919
- }
920
- }
921
- }
922
- //# sourceMappingURL=todo-management-tool-v2.js.map