@pixelbyte-software/pixcode 1.34.0 → 1.35.1

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 (247) hide show
  1. package/LICENSE +718 -718
  2. package/README.de.md +248 -248
  3. package/README.ja.md +240 -240
  4. package/README.ko.md +240 -240
  5. package/README.md +303 -303
  6. package/README.ru.md +248 -248
  7. package/README.tr.md +250 -250
  8. package/README.zh-CN.md +240 -240
  9. package/dist/api-docs.html +548 -395
  10. package/dist/assets/index-B8w57E1r.css +32 -0
  11. package/dist/assets/index-CBdsvGSR.js +854 -0
  12. package/dist/clear-cache.html +85 -85
  13. package/dist/convert-icons.md +52 -52
  14. package/dist/favicon.svg +8 -8
  15. package/dist/generate-icons.js +48 -48
  16. package/dist/icons/codex-white.svg +3 -3
  17. package/dist/icons/codex.svg +3 -3
  18. package/dist/icons/cursor-white.svg +11 -11
  19. package/dist/icons/icon-128x128.svg +9 -9
  20. package/dist/icons/icon-144x144.svg +9 -9
  21. package/dist/icons/icon-152x152.svg +9 -9
  22. package/dist/icons/icon-192x192.svg +9 -9
  23. package/dist/icons/icon-384x384.svg +9 -9
  24. package/dist/icons/icon-512x512.svg +9 -9
  25. package/dist/icons/icon-72x72.svg +9 -9
  26. package/dist/icons/icon-96x96.svg +9 -9
  27. package/dist/icons/icon-template.svg +9 -9
  28. package/dist/icons/qwen-logo.svg +14 -14
  29. package/dist/index.html +59 -59
  30. package/dist/logo.svg +12 -12
  31. package/dist/manifest.json +60 -60
  32. package/dist/openapi.yaml +1693 -1311
  33. package/dist/sw.js +124 -124
  34. package/dist-server/server/claude-sdk.js +38 -7
  35. package/dist-server/server/claude-sdk.js.map +1 -1
  36. package/dist-server/server/cli.js +107 -112
  37. package/dist-server/server/cli.js.map +1 -1
  38. package/dist-server/server/daemon/manager.js +33 -33
  39. package/dist-server/server/daemon-manager.js +159 -112
  40. package/dist-server/server/daemon-manager.js.map +1 -1
  41. package/dist-server/server/database/json-store.js +8 -5
  42. package/dist-server/server/database/json-store.js.map +1 -1
  43. package/dist-server/server/index.js +31 -10
  44. package/dist-server/server/index.js.map +1 -1
  45. package/dist-server/server/modules/orchestration/a2a/adapter-registry.js +45 -19
  46. package/dist-server/server/modules/orchestration/a2a/adapter-registry.js.map +1 -1
  47. package/dist-server/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.js.map +1 -1
  48. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js +1 -0
  49. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js.map +1 -1
  50. package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js +202 -0
  51. package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js.map +1 -0
  52. package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js +205 -0
  53. package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js.map +1 -0
  54. package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js +205 -0
  55. package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js.map +1 -0
  56. package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js +205 -0
  57. package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js.map +1 -0
  58. package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js +205 -0
  59. package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js.map +1 -0
  60. package/dist-server/server/modules/orchestration/a2a/routes.js +298 -34
  61. package/dist-server/server/modules/orchestration/a2a/routes.js.map +1 -1
  62. package/dist-server/server/modules/orchestration/a2a/task-store.js +144 -0
  63. package/dist-server/server/modules/orchestration/a2a/task-store.js.map +1 -0
  64. package/dist-server/server/modules/orchestration/a2a/validator.js +16 -0
  65. package/dist-server/server/modules/orchestration/a2a/validator.js.map +1 -1
  66. package/dist-server/server/modules/orchestration/index.js +14 -0
  67. package/dist-server/server/modules/orchestration/index.js.map +1 -1
  68. package/dist-server/server/modules/orchestration/preview/port-watcher.js +90 -0
  69. package/dist-server/server/modules/orchestration/preview/port-watcher.js.map +1 -0
  70. package/dist-server/server/modules/orchestration/preview/preview-proxy.js +58 -0
  71. package/dist-server/server/modules/orchestration/preview/preview-proxy.js.map +1 -0
  72. package/dist-server/server/modules/orchestration/preview/types.js +2 -0
  73. package/dist-server/server/modules/orchestration/preview/types.js.map +1 -0
  74. package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js +37 -0
  75. package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js.map +1 -0
  76. package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js +68 -0
  77. package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js.map +1 -0
  78. package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js +128 -0
  79. package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js.map +1 -0
  80. package/dist-server/server/modules/orchestration/tasks/orchestration-task.types.js +2 -0
  81. package/dist-server/server/modules/orchestration/tasks/orchestration-task.types.js.map +1 -0
  82. package/dist-server/server/modules/orchestration/workflows/built-in-workflows.js +126 -0
  83. package/dist-server/server/modules/orchestration/workflows/built-in-workflows.js.map +1 -0
  84. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +1047 -0
  85. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -0
  86. package/dist-server/server/modules/orchestration/workflows/workflow-store.js +76 -0
  87. package/dist-server/server/modules/orchestration/workflows/workflow-store.js.map +1 -0
  88. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js +151 -0
  89. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js.map +1 -0
  90. package/dist-server/server/modules/orchestration/workflows/workflow.types.js +2 -0
  91. package/dist-server/server/modules/orchestration/workflows/workflow.types.js.map +1 -0
  92. package/dist-server/server/modules/orchestration/workflows/workspace-target.js +98 -0
  93. package/dist-server/server/modules/orchestration/workflows/workspace-target.js.map +1 -0
  94. package/dist-server/server/modules/orchestration/workspace/docker-workspace.js +122 -0
  95. package/dist-server/server/modules/orchestration/workspace/docker-workspace.js.map +1 -0
  96. package/dist-server/server/modules/orchestration/workspace/path-safety.js +48 -0
  97. package/dist-server/server/modules/orchestration/workspace/path-safety.js.map +1 -0
  98. package/dist-server/server/modules/orchestration/workspace/types.js +11 -0
  99. package/dist-server/server/modules/orchestration/workspace/types.js.map +1 -0
  100. package/dist-server/server/modules/orchestration/workspace/workspace-manager.js +80 -0
  101. package/dist-server/server/modules/orchestration/workspace/workspace-manager.js.map +1 -0
  102. package/dist-server/server/modules/orchestration/workspace/worktree-workspace.js +96 -0
  103. package/dist-server/server/modules/orchestration/workspace/worktree-workspace.js.map +1 -0
  104. package/dist-server/server/modules/providers/index.js +3 -0
  105. package/dist-server/server/modules/providers/index.js.map +1 -0
  106. package/dist-server/server/openai-codex.js +35 -4
  107. package/dist-server/server/openai-codex.js.map +1 -1
  108. package/dist-server/server/routes/commands.js +25 -25
  109. package/dist-server/server/routes/git.js +17 -17
  110. package/dist-server/server/routes/taskmaster.js +525 -508
  111. package/dist-server/server/routes/taskmaster.js.map +1 -1
  112. package/package.json +180 -178
  113. package/scripts/fix-node-pty.js +67 -67
  114. package/scripts/smoke/a2a-roundtrip.mjs +86 -17
  115. package/scripts/smoke/orchestration-api.mjs +172 -0
  116. package/scripts/smoke/orchestration-live-run.mjs +176 -0
  117. package/server/claude-sdk.js +898 -857
  118. package/server/cli.js +935 -940
  119. package/server/constants/config.js +4 -4
  120. package/server/cursor-cli.js +342 -342
  121. package/server/daemon/manager.js +564 -564
  122. package/server/daemon-manager.js +959 -920
  123. package/server/database/db.js +794 -794
  124. package/server/database/json-store.js +197 -194
  125. package/server/gemini-cli.js +535 -535
  126. package/server/gemini-response-handler.js +79 -79
  127. package/server/index.js +3135 -3104
  128. package/server/load-env.js +34 -34
  129. package/server/middleware/auth.js +173 -173
  130. package/server/modules/orchestration/a2a/adapter-registry.ts +72 -22
  131. package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +9 -3
  132. package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +1 -0
  133. package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -0
  134. package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -0
  135. package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -0
  136. package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -0
  137. package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -0
  138. package/server/modules/orchestration/a2a/routes.ts +349 -36
  139. package/server/modules/orchestration/a2a/task-store.ts +178 -0
  140. package/server/modules/orchestration/a2a/types.ts +14 -0
  141. package/server/modules/orchestration/a2a/validator.ts +25 -2
  142. package/server/modules/orchestration/index.ts +40 -0
  143. package/server/modules/orchestration/preview/port-watcher.ts +112 -0
  144. package/server/modules/orchestration/preview/preview-proxy.ts +60 -0
  145. package/server/modules/orchestration/preview/types.ts +19 -0
  146. package/server/modules/orchestration/tasks/orchestration-task-store.ts +45 -0
  147. package/server/modules/orchestration/tasks/orchestration-task.routes.ts +73 -0
  148. package/server/modules/orchestration/tasks/orchestration-task.service.ts +145 -0
  149. package/server/modules/orchestration/tasks/orchestration-task.types.ts +29 -0
  150. package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -0
  151. package/server/modules/orchestration/workflows/workflow-runner.ts +1206 -0
  152. package/server/modules/orchestration/workflows/workflow-store.ts +97 -0
  153. package/server/modules/orchestration/workflows/workflow.routes.ts +169 -0
  154. package/server/modules/orchestration/workflows/workflow.types.ts +70 -0
  155. package/server/modules/orchestration/workflows/workspace-target.ts +120 -0
  156. package/server/modules/orchestration/workspace/docker-workspace.ts +135 -0
  157. package/server/modules/orchestration/workspace/path-safety.ts +55 -0
  158. package/server/modules/orchestration/workspace/types.ts +52 -0
  159. package/server/modules/orchestration/workspace/workspace-manager.ts +97 -0
  160. package/server/modules/orchestration/workspace/worktree-workspace.ts +125 -0
  161. package/server/modules/providers/index.ts +2 -0
  162. package/server/modules/providers/list/claude/claude-auth.provider.ts +145 -145
  163. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
  164. package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
  165. package/server/modules/providers/list/claude/claude.provider.ts +15 -15
  166. package/server/modules/providers/list/codex/codex-auth.provider.ts +115 -115
  167. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
  168. package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
  169. package/server/modules/providers/list/codex/codex.provider.ts +15 -15
  170. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
  171. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
  172. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
  173. package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
  174. package/server/modules/providers/list/gemini/gemini-auth.provider.ts +163 -163
  175. package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
  176. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
  177. package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
  178. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +130 -130
  179. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
  180. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +232 -232
  181. package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
  182. package/server/modules/providers/list/qwen/qwen-auth.provider.ts +145 -145
  183. package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
  184. package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
  185. package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
  186. package/server/modules/providers/provider.registry.ts +40 -40
  187. package/server/modules/providers/provider.routes.ts +819 -819
  188. package/server/modules/providers/services/mcp.service.ts +86 -86
  189. package/server/modules/providers/services/provider-auth.service.ts +26 -26
  190. package/server/modules/providers/services/sessions.service.ts +45 -45
  191. package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
  192. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
  193. package/server/modules/providers/shared/provider-configs.ts +142 -142
  194. package/server/modules/providers/tests/mcp.test.ts +293 -293
  195. package/server/openai-codex.js +462 -426
  196. package/server/opencode-cli.js +459 -459
  197. package/server/opencode-response-handler.js +107 -107
  198. package/server/projects.js +3105 -3105
  199. package/server/qwen-code-cli.js +395 -395
  200. package/server/qwen-response-handler.js +73 -73
  201. package/server/routes/agent.js +1365 -1365
  202. package/server/routes/auth.js +138 -138
  203. package/server/routes/codex.js +19 -19
  204. package/server/routes/commands.js +554 -554
  205. package/server/routes/cursor.js +52 -52
  206. package/server/routes/gemini.js +24 -24
  207. package/server/routes/git.js +1488 -1488
  208. package/server/routes/mcp-utils.js +31 -31
  209. package/server/routes/messages.js +61 -61
  210. package/server/routes/network.js +120 -120
  211. package/server/routes/plugins.js +318 -318
  212. package/server/routes/projects.js +915 -915
  213. package/server/routes/qwen.js +27 -27
  214. package/server/routes/settings.js +286 -286
  215. package/server/routes/taskmaster.js +1496 -1471
  216. package/server/routes/telegram.js +125 -125
  217. package/server/routes/user.js +123 -123
  218. package/server/services/external-access.js +171 -171
  219. package/server/services/install-jobs.js +571 -571
  220. package/server/services/notification-orchestrator.js +242 -242
  221. package/server/services/provider-credentials.js +189 -189
  222. package/server/services/provider-models.js +381 -381
  223. package/server/services/telegram/bot.js +279 -279
  224. package/server/services/telegram/telegram-http-client.js +130 -130
  225. package/server/services/telegram/translations.js +170 -170
  226. package/server/services/vapid-keys.js +36 -36
  227. package/server/sessionManager.js +225 -225
  228. package/server/shared/interfaces.ts +54 -54
  229. package/server/shared/types.ts +172 -172
  230. package/server/shared/utils.ts +193 -193
  231. package/server/tsconfig.json +36 -36
  232. package/server/utils/colors.js +21 -21
  233. package/server/utils/commandParser.js +303 -303
  234. package/server/utils/frontmatter.js +18 -18
  235. package/server/utils/gitConfig.js +34 -34
  236. package/server/utils/mcp-detector.js +147 -147
  237. package/server/utils/plugin-loader.js +457 -457
  238. package/server/utils/plugin-process-manager.js +184 -184
  239. package/server/utils/port-access.js +209 -209
  240. package/server/utils/runtime-paths.js +37 -37
  241. package/server/utils/taskmaster-websocket.js +128 -128
  242. package/server/utils/url-detection.js +71 -71
  243. package/server/vite-daemon.js +78 -78
  244. package/shared/modelConstants.js +162 -162
  245. package/shared/networkHosts.js +22 -22
  246. package/dist/assets/index-B1ghfb4w.css +0 -32
  247. package/dist/assets/index-BvClqlMf.js +0 -852
@@ -1,1471 +1,1496 @@
1
- /**
2
- * TASKMASTER API ROUTES
3
- * ====================
4
- *
5
- * This module provides API endpoints for TaskMaster integration including:
6
- * - .taskmaster folder detection in project directories
7
- * - MCP server configuration detection
8
- * - TaskMaster state and metadata management
9
- */
10
-
11
- import express from 'express';
12
- import fs from 'fs';
13
- import path from 'path';
14
- import { promises as fsPromises } from 'fs';
15
- import { spawn } from 'child_process';
16
- import { extractProjectDirectory } from '../projects.js';
17
- import { detectTaskMasterMCPServer } from '../utils/mcp-detector.js';
18
- import { broadcastTaskMasterProjectUpdate, broadcastTaskMasterTasksUpdate } from '../utils/taskmaster-websocket.js';
19
-
20
- const router = express.Router();
21
-
22
- /**
23
- * Check if TaskMaster CLI is installed globally
24
- * @returns {Promise<Object>} Installation status result
25
- */
26
- async function checkTaskMasterInstallation() {
27
- return new Promise((resolve) => {
28
- // Check if task-master command is available
29
- const child = spawn('which', ['task-master'], {
30
- stdio: ['ignore', 'pipe', 'pipe'],
31
- shell: true
32
- });
33
-
34
- let output = '';
35
- let errorOutput = '';
36
-
37
- child.stdout.on('data', (data) => {
38
- output += data.toString();
39
- });
40
-
41
- child.stderr.on('data', (data) => {
42
- errorOutput += data.toString();
43
- });
44
-
45
- child.on('close', (code) => {
46
- if (code === 0 && output.trim()) {
47
- // TaskMaster is installed, get version
48
- const versionChild = spawn('task-master', ['--version'], {
49
- stdio: ['ignore', 'pipe', 'pipe'],
50
- shell: true
51
- });
52
-
53
- let versionOutput = '';
54
-
55
- versionChild.stdout.on('data', (data) => {
56
- versionOutput += data.toString();
57
- });
58
-
59
- versionChild.on('close', (versionCode) => {
60
- resolve({
61
- isInstalled: true,
62
- installPath: output.trim(),
63
- version: versionCode === 0 ? versionOutput.trim() : 'unknown',
64
- reason: null
65
- });
66
- });
67
-
68
- versionChild.on('error', () => {
69
- resolve({
70
- isInstalled: true,
71
- installPath: output.trim(),
72
- version: 'unknown',
73
- reason: null
74
- });
75
- });
76
- } else {
77
- resolve({
78
- isInstalled: false,
79
- installPath: null,
80
- version: null,
81
- reason: 'TaskMaster CLI not found in PATH'
82
- });
83
- }
84
- });
85
-
86
- child.on('error', (error) => {
87
- resolve({
88
- isInstalled: false,
89
- installPath: null,
90
- version: null,
91
- reason: `Error checking installation: ${error.message}`
92
- });
93
- });
94
- });
95
- }
96
-
97
- // API Routes
98
-
99
- /**
100
- * GET /api/taskmaster/installation-status
101
- * Check if TaskMaster CLI is installed on the system
102
- */
103
- router.get('/installation-status', async (req, res) => {
104
- try {
105
- const installationStatus = await checkTaskMasterInstallation();
106
-
107
- // Also check for MCP server configuration
108
- const mcpStatus = await detectTaskMasterMCPServer();
109
-
110
- res.json({
111
- success: true,
112
- installation: installationStatus,
113
- mcpServer: mcpStatus,
114
- isReady: installationStatus.isInstalled && mcpStatus.hasMCPServer
115
- });
116
- } catch (error) {
117
- console.error('Error checking TaskMaster installation:', error);
118
- res.status(500).json({
119
- success: false,
120
- error: 'Failed to check TaskMaster installation status',
121
- installation: {
122
- isInstalled: false,
123
- reason: `Server error: ${error.message}`
124
- },
125
- mcpServer: {
126
- hasMCPServer: false,
127
- reason: `Server error: ${error.message}`
128
- },
129
- isReady: false
130
- });
131
- }
132
- });
133
-
134
- /**
135
- * GET /api/taskmaster/tasks/:projectName
136
- * Load actual tasks from .taskmaster/tasks/tasks.json
137
- */
138
- router.get('/tasks/:projectName', async (req, res) => {
139
- try {
140
- const { projectName } = req.params;
141
-
142
- // Get project path
143
- let projectPath;
144
- try {
145
- projectPath = await extractProjectDirectory(projectName);
146
- } catch (error) {
147
- return res.status(404).json({
148
- error: 'Project not found',
149
- message: `Project "${projectName}" does not exist`
150
- });
151
- }
152
-
153
- const taskMasterPath = path.join(projectPath, '.taskmaster');
154
- const tasksFilePath = path.join(taskMasterPath, 'tasks', 'tasks.json');
155
-
156
- // Check if tasks file exists
157
- try {
158
- await fsPromises.access(tasksFilePath);
159
- } catch (error) {
160
- return res.json({
161
- projectName,
162
- tasks: [],
163
- message: 'No tasks.json file found'
164
- });
165
- }
166
-
167
- // Read and parse tasks file
168
- try {
169
- const tasksContent = await fsPromises.readFile(tasksFilePath, 'utf8');
170
- const tasksData = JSON.parse(tasksContent);
171
-
172
- let tasks = [];
173
- let currentTag = 'master';
174
-
175
- // Handle both tagged and legacy formats
176
- if (Array.isArray(tasksData)) {
177
- // Legacy format
178
- tasks = tasksData;
179
- } else if (tasksData.tasks) {
180
- // Simple format with tasks array
181
- tasks = tasksData.tasks;
182
- } else {
183
- // Tagged format - get tasks from current tag or master
184
- if (tasksData[currentTag] && tasksData[currentTag].tasks) {
185
- tasks = tasksData[currentTag].tasks;
186
- } else if (tasksData.master && tasksData.master.tasks) {
187
- tasks = tasksData.master.tasks;
188
- } else {
189
- // Get tasks from first available tag
190
- const firstTag = Object.keys(tasksData).find(key =>
191
- tasksData[key].tasks && Array.isArray(tasksData[key].tasks)
192
- );
193
- if (firstTag) {
194
- tasks = tasksData[firstTag].tasks;
195
- currentTag = firstTag;
196
- }
197
- }
198
- }
199
-
200
- // Transform tasks to ensure all have required fields
201
- const transformedTasks = tasks.map(task => ({
202
- id: task.id,
203
- title: task.title || 'Untitled Task',
204
- description: task.description || '',
205
- status: task.status || 'pending',
206
- priority: task.priority || 'medium',
207
- dependencies: task.dependencies || [],
208
- createdAt: task.createdAt || task.created || new Date().toISOString(),
209
- updatedAt: task.updatedAt || task.updated || new Date().toISOString(),
210
- details: task.details || '',
211
- testStrategy: task.testStrategy || task.test_strategy || '',
212
- subtasks: task.subtasks || []
213
- }));
214
-
215
- res.json({
216
- projectName,
217
- projectPath,
218
- tasks: transformedTasks,
219
- currentTag,
220
- totalTasks: transformedTasks.length,
221
- tasksByStatus: {
222
- pending: transformedTasks.filter(t => t.status === 'pending').length,
223
- 'in-progress': transformedTasks.filter(t => t.status === 'in-progress').length,
224
- done: transformedTasks.filter(t => t.status === 'done').length,
225
- review: transformedTasks.filter(t => t.status === 'review').length,
226
- deferred: transformedTasks.filter(t => t.status === 'deferred').length,
227
- cancelled: transformedTasks.filter(t => t.status === 'cancelled').length
228
- },
229
- timestamp: new Date().toISOString()
230
- });
231
-
232
- } catch (parseError) {
233
- console.error('Failed to parse tasks.json:', parseError);
234
- return res.status(500).json({
235
- error: 'Failed to parse tasks file',
236
- message: parseError.message
237
- });
238
- }
239
-
240
- } catch (error) {
241
- console.error('TaskMaster tasks loading error:', error);
242
- res.status(500).json({
243
- error: 'Failed to load TaskMaster tasks',
244
- message: error.message
245
- });
246
- }
247
- });
248
-
249
- /**
250
- * GET /api/taskmaster/prd/:projectName
251
- * List all PRD files in the project's .taskmaster/docs directory
252
- */
253
- router.get('/prd/:projectName', async (req, res) => {
254
- try {
255
- const { projectName } = req.params;
256
-
257
- // Get project path
258
- let projectPath;
259
- try {
260
- projectPath = await extractProjectDirectory(projectName);
261
- } catch (error) {
262
- return res.status(404).json({
263
- error: 'Project not found',
264
- message: `Project "${projectName}" does not exist`
265
- });
266
- }
267
-
268
- const docsPath = path.join(projectPath, '.taskmaster', 'docs');
269
-
270
- // Check if docs directory exists
271
- try {
272
- await fsPromises.access(docsPath, fs.constants.R_OK);
273
- } catch (error) {
274
- return res.json({
275
- projectName,
276
- prdFiles: [],
277
- message: 'No .taskmaster/docs directory found'
278
- });
279
- }
280
-
281
- // Read directory and filter for PRD files
282
- try {
283
- const files = await fsPromises.readdir(docsPath);
284
- const prdFiles = [];
285
-
286
- for (const file of files) {
287
- const filePath = path.join(docsPath, file);
288
- const stats = await fsPromises.stat(filePath);
289
-
290
- if (stats.isFile() && (file.endsWith('.txt') || file.endsWith('.md'))) {
291
- prdFiles.push({
292
- name: file,
293
- path: path.relative(projectPath, filePath),
294
- size: stats.size,
295
- modified: stats.mtime.toISOString(),
296
- created: stats.birthtime.toISOString()
297
- });
298
- }
299
- }
300
-
301
- res.json({
302
- projectName,
303
- projectPath,
304
- prdFiles: prdFiles.sort((a, b) => new Date(b.modified) - new Date(a.modified)),
305
- timestamp: new Date().toISOString()
306
- });
307
-
308
- } catch (readError) {
309
- console.error('Error reading docs directory:', readError);
310
- return res.status(500).json({
311
- error: 'Failed to read PRD files',
312
- message: readError.message
313
- });
314
- }
315
-
316
- } catch (error) {
317
- console.error('PRD list error:', error);
318
- res.status(500).json({
319
- error: 'Failed to list PRD files',
320
- message: error.message
321
- });
322
- }
323
- });
324
-
325
- /**
326
- * POST /api/taskmaster/prd/:projectName
327
- * Create or update a PRD file in the project's .taskmaster/docs directory
328
- */
329
- router.post('/prd/:projectName', async (req, res) => {
330
- try {
331
- const { projectName } = req.params;
332
- const { fileName, content } = req.body;
333
-
334
- if (!fileName || !content) {
335
- return res.status(400).json({
336
- error: 'Missing required fields',
337
- message: 'fileName and content are required'
338
- });
339
- }
340
-
341
- // Validate filename
342
- if (!fileName.match(/^[\w\-. ]+\.(txt|md)$/)) {
343
- return res.status(400).json({
344
- error: 'Invalid filename',
345
- message: 'Filename must end with .txt or .md and contain only alphanumeric characters, spaces, dots, and dashes'
346
- });
347
- }
348
-
349
- // Get project path
350
- let projectPath;
351
- try {
352
- projectPath = await extractProjectDirectory(projectName);
353
- } catch (error) {
354
- return res.status(404).json({
355
- error: 'Project not found',
356
- message: `Project "${projectName}" does not exist`
357
- });
358
- }
359
-
360
- const docsPath = path.join(projectPath, '.taskmaster', 'docs');
361
- const filePath = path.join(docsPath, fileName);
362
-
363
- // Ensure docs directory exists
364
- try {
365
- await fsPromises.mkdir(docsPath, { recursive: true });
366
- } catch (error) {
367
- console.error('Failed to create docs directory:', error);
368
- return res.status(500).json({
369
- error: 'Failed to create directory',
370
- message: error.message
371
- });
372
- }
373
-
374
- // Write the PRD file
375
- try {
376
- await fsPromises.writeFile(filePath, content, 'utf8');
377
-
378
- // Get file stats
379
- const stats = await fsPromises.stat(filePath);
380
-
381
- res.json({
382
- projectName,
383
- projectPath,
384
- fileName,
385
- filePath: path.relative(projectPath, filePath),
386
- size: stats.size,
387
- created: stats.birthtime.toISOString(),
388
- modified: stats.mtime.toISOString(),
389
- message: 'PRD file saved successfully',
390
- timestamp: new Date().toISOString()
391
- });
392
-
393
- } catch (writeError) {
394
- console.error('Failed to write PRD file:', writeError);
395
- return res.status(500).json({
396
- error: 'Failed to write PRD file',
397
- message: writeError.message
398
- });
399
- }
400
-
401
- } catch (error) {
402
- console.error('PRD create/update error:', error);
403
- res.status(500).json({
404
- error: 'Failed to create/update PRD file',
405
- message: error.message
406
- });
407
- }
408
- });
409
-
410
- /**
411
- * GET /api/taskmaster/prd/:projectName/:fileName
412
- * Get content of a specific PRD file
413
- */
414
- router.get('/prd/:projectName/:fileName', async (req, res) => {
415
- try {
416
- const { projectName, fileName } = req.params;
417
-
418
- // Get project path
419
- let projectPath;
420
- try {
421
- projectPath = await extractProjectDirectory(projectName);
422
- } catch (error) {
423
- return res.status(404).json({
424
- error: 'Project not found',
425
- message: `Project "${projectName}" does not exist`
426
- });
427
- }
428
-
429
- const filePath = path.join(projectPath, '.taskmaster', 'docs', fileName);
430
-
431
- // Check if file exists
432
- try {
433
- await fsPromises.access(filePath, fs.constants.R_OK);
434
- } catch (error) {
435
- return res.status(404).json({
436
- error: 'PRD file not found',
437
- message: `File "${fileName}" does not exist`
438
- });
439
- }
440
-
441
- // Read file content
442
- try {
443
- const content = await fsPromises.readFile(filePath, 'utf8');
444
- const stats = await fsPromises.stat(filePath);
445
-
446
- res.json({
447
- projectName,
448
- projectPath,
449
- fileName,
450
- filePath: path.relative(projectPath, filePath),
451
- content,
452
- size: stats.size,
453
- created: stats.birthtime.toISOString(),
454
- modified: stats.mtime.toISOString(),
455
- timestamp: new Date().toISOString()
456
- });
457
-
458
- } catch (readError) {
459
- console.error('Failed to read PRD file:', readError);
460
- return res.status(500).json({
461
- error: 'Failed to read PRD file',
462
- message: readError.message
463
- });
464
- }
465
-
466
- } catch (error) {
467
- console.error('PRD read error:', error);
468
- res.status(500).json({
469
- error: 'Failed to read PRD file',
470
- message: error.message
471
- });
472
- }
473
- });
474
-
475
- /**
476
- * POST /api/taskmaster/init/:projectName
477
- * Initialize TaskMaster in a project
478
- */
479
- router.post('/init/:projectName', async (req, res) => {
480
- try {
481
- const { projectName } = req.params;
482
-
483
- // Get project path
484
- let projectPath;
485
- try {
486
- projectPath = await extractProjectDirectory(projectName);
487
- } catch (error) {
488
- return res.status(404).json({
489
- error: 'Project not found',
490
- message: `Project "${projectName}" does not exist`
491
- });
492
- }
493
-
494
- // Check if TaskMaster is already initialized
495
- const taskMasterPath = path.join(projectPath, '.taskmaster');
496
- try {
497
- await fsPromises.access(taskMasterPath, fs.constants.F_OK);
498
- return res.status(400).json({
499
- error: 'TaskMaster already initialized',
500
- message: 'TaskMaster is already configured for this project'
501
- });
502
- } catch (error) {
503
- // Directory doesn't exist, we can proceed
504
- }
505
-
506
- // Run taskmaster init command
507
- const initProcess = spawn('npx', ['task-master', 'init'], {
508
- cwd: projectPath,
509
- stdio: ['pipe', 'pipe', 'pipe']
510
- });
511
-
512
- let stdout = '';
513
- let stderr = '';
514
-
515
- initProcess.stdout.on('data', (data) => {
516
- stdout += data.toString();
517
- });
518
-
519
- initProcess.stderr.on('data', (data) => {
520
- stderr += data.toString();
521
- });
522
-
523
- initProcess.on('close', (code) => {
524
- if (code === 0) {
525
- // Broadcast TaskMaster project update via WebSocket
526
- if (req.app.locals.wss) {
527
- broadcastTaskMasterProjectUpdate(
528
- req.app.locals.wss,
529
- projectName,
530
- { hasTaskmaster: true, status: 'initialized' }
531
- );
532
- }
533
-
534
- res.json({
535
- projectName,
536
- projectPath,
537
- message: 'TaskMaster initialized successfully',
538
- output: stdout,
539
- timestamp: new Date().toISOString()
540
- });
541
- } else {
542
- console.error('TaskMaster init failed:', stderr);
543
- res.status(500).json({
544
- error: 'Failed to initialize TaskMaster',
545
- message: stderr || stdout,
546
- code
547
- });
548
- }
549
- });
550
-
551
- // Send 'yes' responses to automated prompts
552
- initProcess.stdin.write('yes\n');
553
- initProcess.stdin.end();
554
-
555
- } catch (error) {
556
- console.error('TaskMaster init error:', error);
557
- res.status(500).json({
558
- error: 'Failed to initialize TaskMaster',
559
- message: error.message
560
- });
561
- }
562
- });
563
-
564
- /**
565
- * POST /api/taskmaster/add-task/:projectName
566
- * Add a new task to the project
567
- */
568
- router.post('/add-task/:projectName', async (req, res) => {
569
- try {
570
- const { projectName } = req.params;
571
- const { prompt, title, description, priority = 'medium', dependencies } = req.body;
572
-
573
- if (!prompt && (!title || !description)) {
574
- return res.status(400).json({
575
- error: 'Missing required parameters',
576
- message: 'Either "prompt" or both "title" and "description" are required'
577
- });
578
- }
579
-
580
- // Get project path
581
- let projectPath;
582
- try {
583
- projectPath = await extractProjectDirectory(projectName);
584
- } catch (error) {
585
- return res.status(404).json({
586
- error: 'Project not found',
587
- message: `Project "${projectName}" does not exist`
588
- });
589
- }
590
-
591
- // Build the task-master add-task command
592
- const args = ['task-master-ai', 'add-task'];
593
-
594
- if (prompt) {
595
- args.push('--prompt', prompt);
596
- args.push('--research'); // Use research for AI-generated tasks
597
- } else {
598
- args.push('--prompt', `Create a task titled "${title}" with description: ${description}`);
599
- }
600
-
601
- if (priority) {
602
- args.push('--priority', priority);
603
- }
604
-
605
- if (dependencies) {
606
- args.push('--dependencies', dependencies);
607
- }
608
-
609
- // Run task-master add-task command
610
- const addTaskProcess = spawn('npx', args, {
611
- cwd: projectPath,
612
- stdio: ['pipe', 'pipe', 'pipe']
613
- });
614
-
615
- let stdout = '';
616
- let stderr = '';
617
-
618
- addTaskProcess.stdout.on('data', (data) => {
619
- stdout += data.toString();
620
- });
621
-
622
- addTaskProcess.stderr.on('data', (data) => {
623
- stderr += data.toString();
624
- });
625
-
626
- addTaskProcess.on('close', (code) => {
627
- console.log('Add task process completed with code:', code);
628
- console.log('Stdout:', stdout);
629
- console.log('Stderr:', stderr);
630
-
631
- if (code === 0) {
632
- // Broadcast task update via WebSocket
633
- if (req.app.locals.wss) {
634
- broadcastTaskMasterTasksUpdate(
635
- req.app.locals.wss,
636
- projectName
637
- );
638
- }
639
-
640
- res.json({
641
- projectName,
642
- projectPath,
643
- message: 'Task added successfully',
644
- output: stdout,
645
- timestamp: new Date().toISOString()
646
- });
647
- } else {
648
- console.error('Add task failed:', stderr);
649
- res.status(500).json({
650
- error: 'Failed to add task',
651
- message: stderr || stdout,
652
- code
653
- });
654
- }
655
- });
656
-
657
- addTaskProcess.stdin.end();
658
-
659
- } catch (error) {
660
- console.error('Add task error:', error);
661
- res.status(500).json({
662
- error: 'Failed to add task',
663
- message: error.message
664
- });
665
- }
666
- });
667
-
668
- /**
669
- * PUT /api/taskmaster/update-task/:projectName/:taskId
670
- * Update a specific task using TaskMaster CLI
671
- */
672
- router.put('/update-task/:projectName/:taskId', async (req, res) => {
673
- try {
674
- const { projectName, taskId } = req.params;
675
- const { title, description, status, priority, details } = req.body;
676
-
677
- // Get project path
678
- let projectPath;
679
- try {
680
- projectPath = await extractProjectDirectory(projectName);
681
- } catch (error) {
682
- return res.status(404).json({
683
- error: 'Project not found',
684
- message: `Project "${projectName}" does not exist`
685
- });
686
- }
687
-
688
- // If only updating status, use set-status command
689
- if (status && Object.keys(req.body).length === 1) {
690
- const setStatusProcess = spawn('npx', ['task-master-ai', 'set-status', `--id=${taskId}`, `--status=${status}`], {
691
- cwd: projectPath,
692
- stdio: ['pipe', 'pipe', 'pipe']
693
- });
694
-
695
- let stdout = '';
696
- let stderr = '';
697
-
698
- setStatusProcess.stdout.on('data', (data) => {
699
- stdout += data.toString();
700
- });
701
-
702
- setStatusProcess.stderr.on('data', (data) => {
703
- stderr += data.toString();
704
- });
705
-
706
- setStatusProcess.on('close', (code) => {
707
- if (code === 0) {
708
- // Broadcast task update via WebSocket
709
- if (req.app.locals.wss) {
710
- broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
711
- }
712
-
713
- res.json({
714
- projectName,
715
- projectPath,
716
- taskId,
717
- message: 'Task status updated successfully',
718
- output: stdout,
719
- timestamp: new Date().toISOString()
720
- });
721
- } else {
722
- console.error('Set task status failed:', stderr);
723
- res.status(500).json({
724
- error: 'Failed to update task status',
725
- message: stderr || stdout,
726
- code
727
- });
728
- }
729
- });
730
-
731
- setStatusProcess.stdin.end();
732
- } else {
733
- // For other updates, use update-task command with a prompt describing the changes
734
- const updates = [];
735
- if (title) updates.push(`title: "${title}"`);
736
- if (description) updates.push(`description: "${description}"`);
737
- if (priority) updates.push(`priority: "${priority}"`);
738
- if (details) updates.push(`details: "${details}"`);
739
-
740
- const prompt = `Update task with the following changes: ${updates.join(', ')}`;
741
-
742
- const updateProcess = spawn('npx', ['task-master-ai', 'update-task', `--id=${taskId}`, `--prompt=${prompt}`], {
743
- cwd: projectPath,
744
- stdio: ['pipe', 'pipe', 'pipe']
745
- });
746
-
747
- let stdout = '';
748
- let stderr = '';
749
-
750
- updateProcess.stdout.on('data', (data) => {
751
- stdout += data.toString();
752
- });
753
-
754
- updateProcess.stderr.on('data', (data) => {
755
- stderr += data.toString();
756
- });
757
-
758
- updateProcess.on('close', (code) => {
759
- if (code === 0) {
760
- // Broadcast task update via WebSocket
761
- if (req.app.locals.wss) {
762
- broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
763
- }
764
-
765
- res.json({
766
- projectName,
767
- projectPath,
768
- taskId,
769
- message: 'Task updated successfully',
770
- output: stdout,
771
- timestamp: new Date().toISOString()
772
- });
773
- } else {
774
- console.error('Update task failed:', stderr);
775
- res.status(500).json({
776
- error: 'Failed to update task',
777
- message: stderr || stdout,
778
- code
779
- });
780
- }
781
- });
782
-
783
- updateProcess.stdin.end();
784
- }
785
-
786
- } catch (error) {
787
- console.error('Update task error:', error);
788
- res.status(500).json({
789
- error: 'Failed to update task',
790
- message: error.message
791
- });
792
- }
793
- });
794
-
795
- /**
796
- * POST /api/taskmaster/parse-prd/:projectName
797
- * Parse a PRD file to generate tasks
798
- */
799
- router.post('/parse-prd/:projectName', async (req, res) => {
800
- try {
801
- const { projectName } = req.params;
802
- const { fileName = 'prd.txt', numTasks, append = false } = req.body;
803
-
804
- // Get project path
805
- let projectPath;
806
- try {
807
- projectPath = await extractProjectDirectory(projectName);
808
- } catch (error) {
809
- return res.status(404).json({
810
- error: 'Project not found',
811
- message: `Project "${projectName}" does not exist`
812
- });
813
- }
814
-
815
- const prdPath = path.join(projectPath, '.taskmaster', 'docs', fileName);
816
-
817
- // Check if PRD file exists
818
- try {
819
- await fsPromises.access(prdPath, fs.constants.F_OK);
820
- } catch (error) {
821
- return res.status(404).json({
822
- error: 'PRD file not found',
823
- message: `File "${fileName}" does not exist in .taskmaster/docs/`
824
- });
825
- }
826
-
827
- // Build the command args
828
- const args = ['task-master-ai', 'parse-prd', prdPath];
829
-
830
- if (numTasks) {
831
- args.push('--num-tasks', numTasks.toString());
832
- }
833
-
834
- if (append) {
835
- args.push('--append');
836
- }
837
-
838
- args.push('--research'); // Use research for better PRD parsing
839
-
840
- // Run task-master parse-prd command
841
- const parsePRDProcess = spawn('npx', args, {
842
- cwd: projectPath,
843
- stdio: ['pipe', 'pipe', 'pipe']
844
- });
845
-
846
- let stdout = '';
847
- let stderr = '';
848
-
849
- parsePRDProcess.stdout.on('data', (data) => {
850
- stdout += data.toString();
851
- });
852
-
853
- parsePRDProcess.stderr.on('data', (data) => {
854
- stderr += data.toString();
855
- });
856
-
857
- parsePRDProcess.on('close', (code) => {
858
- if (code === 0) {
859
- // Broadcast task update via WebSocket
860
- if (req.app.locals.wss) {
861
- broadcastTaskMasterTasksUpdate(
862
- req.app.locals.wss,
863
- projectName
864
- );
865
- }
866
-
867
- res.json({
868
- projectName,
869
- projectPath,
870
- prdFile: fileName,
871
- message: 'PRD parsed and tasks generated successfully',
872
- output: stdout,
873
- timestamp: new Date().toISOString()
874
- });
875
- } else {
876
- console.error('Parse PRD failed:', stderr);
877
- res.status(500).json({
878
- error: 'Failed to parse PRD',
879
- message: stderr || stdout,
880
- code
881
- });
882
- }
883
- });
884
-
885
- parsePRDProcess.stdin.end();
886
-
887
- } catch (error) {
888
- console.error('Parse PRD error:', error);
889
- res.status(500).json({
890
- error: 'Failed to parse PRD',
891
- message: error.message
892
- });
893
- }
894
- });
895
-
896
- /**
897
- * GET /api/taskmaster/prd-templates
898
- * Get available PRD templates
899
- */
900
- router.get('/prd-templates', async (req, res) => {
901
- try {
902
- // Return built-in templates
903
- const templates = [
904
- {
905
- id: 'web-app',
906
- name: 'Web Application',
907
- description: 'Template for web application projects with frontend and backend components',
908
- category: 'web',
909
- content: `# Product Requirements Document - Web Application
910
-
911
- ## Overview
912
- **Product Name:** [Your App Name]
913
- **Version:** 1.0
914
- **Date:** ${new Date().toISOString().split('T')[0]}
915
- **Author:** [Your Name]
916
-
917
- ## Executive Summary
918
- Brief description of what this web application will do and why it's needed.
919
-
920
- ## Product Goals
921
- - Goal 1: [Specific measurable goal]
922
- - Goal 2: [Specific measurable goal]
923
- - Goal 3: [Specific measurable goal]
924
-
925
- ## User Stories
926
- ### Core Features
927
- 1. **User Registration & Authentication**
928
- - As a user, I want to create an account so I can access personalized features
929
- - As a user, I want to log in securely so my data is protected
930
- - As a user, I want to reset my password if I forget it
931
-
932
- 2. **Main Application Features**
933
- - As a user, I want to [core feature 1] so I can [benefit]
934
- - As a user, I want to [core feature 2] so I can [benefit]
935
- - As a user, I want to [core feature 3] so I can [benefit]
936
-
937
- 3. **User Interface**
938
- - As a user, I want a responsive design so I can use the app on any device
939
- - As a user, I want intuitive navigation so I can easily find features
940
-
941
- ## Technical Requirements
942
- ### Frontend
943
- - Framework: React/Vue/Angular or vanilla JavaScript
944
- - Styling: CSS framework (Tailwind, Bootstrap, etc.)
945
- - State Management: Redux/Vuex/Context API
946
- - Build Tools: Webpack/Vite
947
- - Testing: Jest/Vitest for unit tests
948
-
949
- ### Backend
950
- - Runtime: Node.js/Python/Java
951
- - Database: PostgreSQL/MySQL/MongoDB
952
- - API: RESTful API or GraphQL
953
- - Authentication: JWT tokens
954
- - Testing: Integration and unit tests
955
-
956
- ### Infrastructure
957
- - Hosting: Cloud provider (AWS, Azure, GCP)
958
- - CI/CD: GitHub Actions/GitLab CI
959
- - Monitoring: Application monitoring tools
960
- - Security: HTTPS, input validation, rate limiting
961
-
962
- ## Success Metrics
963
- - User engagement metrics
964
- - Performance benchmarks (load time < 2s)
965
- - Error rates < 1%
966
- - User satisfaction scores
967
-
968
- ## Timeline
969
- - Phase 1: Core functionality (4-6 weeks)
970
- - Phase 2: Advanced features (2-4 weeks)
971
- - Phase 3: Polish and launch (2 weeks)
972
-
973
- ## Constraints & Assumptions
974
- - Budget constraints
975
- - Technical limitations
976
- - Team size and expertise
977
- - Timeline constraints`
978
- },
979
- {
980
- id: 'api',
981
- name: 'REST API',
982
- description: 'Template for REST API development projects',
983
- category: 'backend',
984
- content: `# Product Requirements Document - REST API
985
-
986
- ## Overview
987
- **API Name:** [Your API Name]
988
- **Version:** v1.0
989
- **Date:** ${new Date().toISOString().split('T')[0]}
990
- **Author:** [Your Name]
991
-
992
- ## Executive Summary
993
- Description of the API's purpose, target users, and primary use cases.
994
-
995
- ## API Goals
996
- - Goal 1: Provide secure data access
997
- - Goal 2: Ensure scalable architecture
998
- - Goal 3: Maintain high availability (99.9% uptime)
999
-
1000
- ## Functional Requirements
1001
- ### Core Endpoints
1002
- 1. **Authentication Endpoints**
1003
- - POST /api/auth/login - User authentication
1004
- - POST /api/auth/logout - User logout
1005
- - POST /api/auth/refresh - Token refresh
1006
- - POST /api/auth/register - User registration
1007
-
1008
- 2. **Data Management Endpoints**
1009
- - GET /api/resources - List resources with pagination
1010
- - GET /api/resources/{id} - Get specific resource
1011
- - POST /api/resources - Create new resource
1012
- - PUT /api/resources/{id} - Update existing resource
1013
- - DELETE /api/resources/{id} - Delete resource
1014
-
1015
- 3. **Administrative Endpoints**
1016
- - GET /api/admin/users - Manage users (admin only)
1017
- - GET /api/admin/analytics - System analytics
1018
- - POST /api/admin/backup - Trigger system backup
1019
-
1020
- ## Technical Requirements
1021
- ### API Design
1022
- - RESTful architecture following OpenAPI 3.0 specification
1023
- - JSON request/response format
1024
- - Consistent error response format
1025
- - API versioning strategy
1026
-
1027
- ### Authentication & Security
1028
- - JWT token-based authentication
1029
- - Role-based access control (RBAC)
1030
- - Rate limiting (100 requests/minute per user)
1031
- - Input validation and sanitization
1032
- - HTTPS enforcement
1033
-
1034
- ### Database
1035
- - Database type: [PostgreSQL/MongoDB/MySQL]
1036
- - Connection pooling
1037
- - Database migrations
1038
- - Backup and recovery procedures
1039
-
1040
- ### Performance Requirements
1041
- - Response time: < 200ms for 95% of requests
1042
- - Throughput: 1000+ requests/second
1043
- - Concurrent users: 10,000+
1044
- - Database query optimization
1045
-
1046
- ### Documentation
1047
- - Auto-generated API documentation (Swagger/OpenAPI)
1048
- - Code examples for common use cases
1049
- - SDK development for major languages
1050
- - Postman collection for testing
1051
-
1052
- ## Error Handling
1053
- - Standardized error codes and messages
1054
- - Proper HTTP status codes
1055
- - Detailed error logging
1056
- - Graceful degradation strategies
1057
-
1058
- ## Testing Strategy
1059
- - Unit tests (80%+ coverage)
1060
- - Integration tests for all endpoints
1061
- - Load testing and performance testing
1062
- - Security testing (OWASP compliance)
1063
-
1064
- ## Monitoring & Logging
1065
- - Application performance monitoring
1066
- - Error tracking and alerting
1067
- - Access logs and audit trails
1068
- - Health check endpoints
1069
-
1070
- ## Deployment
1071
- - Containerized deployment (Docker)
1072
- - CI/CD pipeline setup
1073
- - Environment management (dev, staging, prod)
1074
- - Blue-green deployment strategy
1075
-
1076
- ## Success Metrics
1077
- - API uptime > 99.9%
1078
- - Average response time < 200ms
1079
- - Zero critical security vulnerabilities
1080
- - Developer adoption metrics`
1081
- },
1082
- {
1083
- id: 'mobile-app',
1084
- name: 'Mobile Application',
1085
- description: 'Template for mobile app development projects (iOS/Android)',
1086
- category: 'mobile',
1087
- content: `# Product Requirements Document - Mobile Application
1088
-
1089
- ## Overview
1090
- **App Name:** [Your App Name]
1091
- **Platform:** iOS / Android / Cross-platform
1092
- **Version:** 1.0
1093
- **Date:** ${new Date().toISOString().split('T')[0]}
1094
- **Author:** [Your Name]
1095
-
1096
- ## Executive Summary
1097
- Brief description of the mobile app's purpose, target audience, and key value proposition.
1098
-
1099
- ## Product Goals
1100
- - Goal 1: [Specific user engagement goal]
1101
- - Goal 2: [Specific functionality goal]
1102
- - Goal 3: [Specific performance goal]
1103
-
1104
- ## User Stories
1105
- ### Core Features
1106
- 1. **Onboarding & Authentication**
1107
- - As a new user, I want a simple onboarding process
1108
- - As a user, I want to sign up with email or social media
1109
- - As a user, I want biometric authentication for security
1110
-
1111
- 2. **Main App Features**
1112
- - As a user, I want [core feature 1] accessible from home screen
1113
- - As a user, I want [core feature 2] to work offline
1114
- - As a user, I want to sync data across devices
1115
-
1116
- 3. **User Experience**
1117
- - As a user, I want intuitive navigation patterns
1118
- - As a user, I want fast loading times
1119
- - As a user, I want accessibility features
1120
-
1121
- ## Technical Requirements
1122
- ### Mobile Development
1123
- - **Cross-platform:** React Native / Flutter / Xamarin
1124
- - **Native:** Swift (iOS) / Kotlin (Android)
1125
- - **State Management:** Redux / MobX / Provider
1126
- - **Navigation:** React Navigation / Flutter Navigation
1127
-
1128
- ### Backend Integration
1129
- - REST API or GraphQL integration
1130
- - Real-time features (WebSockets/Push notifications)
1131
- - Offline data synchronization
1132
- - Background processing
1133
-
1134
- ### Device Features
1135
- - Camera and photo library access
1136
- - GPS location services
1137
- - Push notifications
1138
- - Biometric authentication
1139
- - Device storage
1140
-
1141
- ### Performance Requirements
1142
- - App launch time < 3 seconds
1143
- - Screen transition animations < 300ms
1144
- - Memory usage optimization
1145
- - Battery usage optimization
1146
-
1147
- ## Platform-Specific Considerations
1148
- ### iOS Requirements
1149
- - iOS 13.0+ minimum version
1150
- - App Store guidelines compliance
1151
- - iOS design guidelines (Human Interface Guidelines)
1152
- - TestFlight beta testing
1153
-
1154
- ### Android Requirements
1155
- - Android 8.0+ (API level 26) minimum
1156
- - Google Play Store guidelines
1157
- - Material Design guidelines
1158
- - Google Play Console testing
1159
-
1160
- ## User Interface Design
1161
- - Responsive design for different screen sizes
1162
- - Dark mode support
1163
- - Accessibility compliance (WCAG 2.1)
1164
- - Consistent design system
1165
-
1166
- ## Security & Privacy
1167
- - Secure data storage (Keychain/Keystore)
1168
- - API communication encryption
1169
- - Privacy policy compliance (GDPR/CCPA)
1170
- - App security best practices
1171
-
1172
- ## Testing Strategy
1173
- - Unit testing (80%+ coverage)
1174
- - UI/E2E testing (Detox/Appium)
1175
- - Device testing on multiple screen sizes
1176
- - Performance testing
1177
- - Security testing
1178
-
1179
- ## App Store Deployment
1180
- - App store optimization (ASO)
1181
- - App icons and screenshots
1182
- - Store listing content
1183
- - Release management strategy
1184
-
1185
- ## Analytics & Monitoring
1186
- - User analytics (Firebase/Analytics)
1187
- - Crash reporting (Crashlytics/Sentry)
1188
- - Performance monitoring
1189
- - User feedback collection
1190
-
1191
- ## Success Metrics
1192
- - App store ratings > 4.0
1193
- - User retention rates
1194
- - Daily/Monthly active users
1195
- - App performance metrics
1196
- - Conversion rates`
1197
- },
1198
- {
1199
- id: 'data-analysis',
1200
- name: 'Data Analysis Project',
1201
- description: 'Template for data analysis and visualization projects',
1202
- category: 'data',
1203
- content: `# Product Requirements Document - Data Analysis Project
1204
-
1205
- ## Overview
1206
- **Project Name:** [Your Analysis Project]
1207
- **Analysis Type:** [Descriptive/Predictive/Prescriptive]
1208
- **Date:** ${new Date().toISOString().split('T')[0]}
1209
- **Author:** [Your Name]
1210
-
1211
- ## Executive Summary
1212
- Description of the business problem, data sources, and expected insights.
1213
-
1214
- ## Project Goals
1215
- - Goal 1: [Specific business question to answer]
1216
- - Goal 2: [Specific prediction to make]
1217
- - Goal 3: [Specific recommendation to provide]
1218
-
1219
- ## Business Requirements
1220
- ### Key Questions
1221
- 1. What patterns exist in the current data?
1222
- 2. What factors influence [target variable]?
1223
- 3. What predictions can be made for [future outcome]?
1224
- 4. What recommendations can improve [business metric]?
1225
-
1226
- ### Success Criteria
1227
- - Actionable insights for stakeholders
1228
- - Statistical significance in findings
1229
- - Reproducible analysis pipeline
1230
- - Clear visualization and reporting
1231
-
1232
- ## Data Requirements
1233
- ### Data Sources
1234
- 1. **Primary Data**
1235
- - Source: [Database/API/Files]
1236
- - Format: [CSV/JSON/SQL]
1237
- - Size: [Volume estimate]
1238
- - Update frequency: [Real-time/Daily/Monthly]
1239
-
1240
- 2. **External Data**
1241
- - Third-party APIs
1242
- - Public datasets
1243
- - Market research data
1244
-
1245
- ### Data Quality Requirements
1246
- - Data completeness (< 5% missing values)
1247
- - Data accuracy validation
1248
- - Data consistency checks
1249
- - Historical data availability
1250
-
1251
- ## Technical Requirements
1252
- ### Data Pipeline
1253
- - Data extraction and ingestion
1254
- - Data cleaning and preprocessing
1255
- - Data transformation and feature engineering
1256
- - Data validation and quality checks
1257
-
1258
- ### Analysis Tools
1259
- - **Programming:** Python/R/SQL
1260
- - **Libraries:** pandas, numpy, scikit-learn, matplotlib
1261
- - **Visualization:** Tableau, PowerBI, or custom dashboards
1262
- - **Version Control:** Git for code and DVC for data
1263
-
1264
- ### Computing Resources
1265
- - Local development environment
1266
- - Cloud computing (AWS/GCP/Azure) if needed
1267
- - Database access and permissions
1268
- - Storage requirements
1269
-
1270
- ## Analysis Methodology
1271
- ### Data Exploration
1272
- 1. Descriptive statistics and data profiling
1273
- 2. Data visualization and pattern identification
1274
- 3. Correlation analysis
1275
- 4. Outlier detection and handling
1276
-
1277
- ### Statistical Analysis
1278
- 1. Hypothesis formulation
1279
- 2. Statistical testing
1280
- 3. Confidence intervals
1281
- 4. Effect size calculations
1282
-
1283
- ### Machine Learning (if applicable)
1284
- 1. Feature selection and engineering
1285
- 2. Model selection and training
1286
- 3. Cross-validation and evaluation
1287
- 4. Model interpretation and explainability
1288
-
1289
- ## Deliverables
1290
- ### Reports
1291
- - Executive summary for stakeholders
1292
- - Technical analysis report
1293
- - Data quality report
1294
- - Methodology documentation
1295
-
1296
- ### Visualizations
1297
- - Interactive dashboards
1298
- - Static charts and graphs
1299
- - Data story presentations
1300
- - Key findings infographics
1301
-
1302
- ### Code & Documentation
1303
- - Reproducible analysis scripts
1304
- - Data pipeline code
1305
- - Documentation and comments
1306
- - Testing and validation code
1307
-
1308
- ## Timeline
1309
- - Phase 1: Data collection and exploration (2 weeks)
1310
- - Phase 2: Analysis and modeling (3 weeks)
1311
- - Phase 3: Reporting and visualization (1 week)
1312
- - Phase 4: Stakeholder presentation (1 week)
1313
-
1314
- ## Risks & Assumptions
1315
- - Data availability and quality risks
1316
- - Technical complexity assumptions
1317
- - Resource and timeline constraints
1318
- - Stakeholder engagement assumptions
1319
-
1320
- ## Success Metrics
1321
- - Stakeholder satisfaction with insights
1322
- - Accuracy of predictions (if applicable)
1323
- - Business impact of recommendations
1324
- - Reproducibility of results`
1325
- }
1326
- ];
1327
-
1328
- res.json({
1329
- templates,
1330
- timestamp: new Date().toISOString()
1331
- });
1332
-
1333
- } catch (error) {
1334
- console.error('PRD templates error:', error);
1335
- res.status(500).json({
1336
- error: 'Failed to get PRD templates',
1337
- message: error.message
1338
- });
1339
- }
1340
- });
1341
-
1342
- /**
1343
- * POST /api/taskmaster/apply-template/:projectName
1344
- * Apply a PRD template to create a new PRD file
1345
- */
1346
- router.post('/apply-template/:projectName', async (req, res) => {
1347
- try {
1348
- const { projectName } = req.params;
1349
- const { templateId, fileName = 'prd.txt', customizations = {} } = req.body;
1350
-
1351
- if (!templateId) {
1352
- return res.status(400).json({
1353
- error: 'Missing required parameter',
1354
- message: 'templateId is required'
1355
- });
1356
- }
1357
-
1358
- // Get project path
1359
- let projectPath;
1360
- try {
1361
- projectPath = await extractProjectDirectory(projectName);
1362
- } catch (error) {
1363
- return res.status(404).json({
1364
- error: 'Project not found',
1365
- message: `Project "${projectName}" does not exist`
1366
- });
1367
- }
1368
-
1369
- // Get the template content (this would normally fetch from the templates list)
1370
- const templates = await getAvailableTemplates();
1371
- const template = templates.find(t => t.id === templateId);
1372
-
1373
- if (!template) {
1374
- return res.status(404).json({
1375
- error: 'Template not found',
1376
- message: `Template "${templateId}" does not exist`
1377
- });
1378
- }
1379
-
1380
- // Apply customizations to template content
1381
- let content = template.content;
1382
-
1383
- // Replace placeholders with customizations
1384
- for (const [key, value] of Object.entries(customizations)) {
1385
- const placeholder = `[${key}]`;
1386
- content = content.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), value);
1387
- }
1388
-
1389
- // Ensure .taskmaster/docs directory exists
1390
- const docsDir = path.join(projectPath, '.taskmaster', 'docs');
1391
- try {
1392
- await fsPromises.mkdir(docsDir, { recursive: true });
1393
- } catch (error) {
1394
- console.error('Failed to create docs directory:', error);
1395
- }
1396
-
1397
- const filePath = path.join(docsDir, fileName);
1398
-
1399
- // Write the template content to the file
1400
- try {
1401
- await fsPromises.writeFile(filePath, content, 'utf8');
1402
-
1403
- res.json({
1404
- projectName,
1405
- projectPath,
1406
- templateId,
1407
- templateName: template.name,
1408
- fileName,
1409
- filePath: filePath,
1410
- message: 'PRD template applied successfully',
1411
- timestamp: new Date().toISOString()
1412
- });
1413
-
1414
- } catch (writeError) {
1415
- console.error('Failed to write PRD template:', writeError);
1416
- return res.status(500).json({
1417
- error: 'Failed to write PRD template',
1418
- message: writeError.message
1419
- });
1420
- }
1421
-
1422
- } catch (error) {
1423
- console.error('Apply template error:', error);
1424
- res.status(500).json({
1425
- error: 'Failed to apply PRD template',
1426
- message: error.message
1427
- });
1428
- }
1429
- });
1430
-
1431
- // Helper function to get available templates
1432
- async function getAvailableTemplates() {
1433
- // This could be extended to read from files or database
1434
- return [
1435
- {
1436
- id: 'web-app',
1437
- name: 'Web Application',
1438
- description: 'Template for web application projects',
1439
- category: 'web',
1440
- content: `# Product Requirements Document - Web Application
1441
-
1442
- ## Overview
1443
- **Product Name:** [Your App Name]
1444
- **Version:** 1.0
1445
- **Date:** ${new Date().toISOString().split('T')[0]}
1446
- **Author:** [Your Name]
1447
-
1448
- ## Executive Summary
1449
- Brief description of what this web application will do and why it's needed.
1450
-
1451
- ## User Stories
1452
- 1. As a user, I want [feature] so I can [benefit]
1453
- 2. As a user, I want [feature] so I can [benefit]
1454
- 3. As a user, I want [feature] so I can [benefit]
1455
-
1456
- ## Technical Requirements
1457
- - Frontend framework
1458
- - Backend services
1459
- - Database requirements
1460
- - Security considerations
1461
-
1462
- ## Success Metrics
1463
- - User engagement metrics
1464
- - Performance benchmarks
1465
- - Business objectives`
1466
- },
1467
- // Add other templates here if needed
1468
- ];
1469
- }
1470
-
1471
- export default router;
1
+ /**
2
+ * TASKMASTER API ROUTES
3
+ * ====================
4
+ *
5
+ * This module provides API endpoints for TaskMaster integration including:
6
+ * - .taskmaster folder detection in project directories
7
+ * - MCP server configuration detection
8
+ * - TaskMaster state and metadata management
9
+ */
10
+
11
+ import express from 'express';
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { promises as fsPromises } from 'fs';
15
+ import { spawn } from 'child_process';
16
+ import { extractProjectDirectory } from '../projects.js';
17
+ import { detectTaskMasterMCPServer } from '../utils/mcp-detector.js';
18
+ import { broadcastTaskMasterProjectUpdate, broadcastTaskMasterTasksUpdate } from '../utils/taskmaster-websocket.js';
19
+ import { orchestrationTaskService } from '@/modules/orchestration/tasks/orchestration-task.service.js';
20
+
21
+ const router = express.Router();
22
+
23
+ /**
24
+ * Check if TaskMaster CLI is installed globally
25
+ * @returns {Promise<Object>} Installation status result
26
+ */
27
+ async function checkTaskMasterInstallation() {
28
+ return new Promise((resolve) => {
29
+ // Check if task-master command is available
30
+ const child = spawn('which', ['task-master'], {
31
+ stdio: ['ignore', 'pipe', 'pipe'],
32
+ shell: true
33
+ });
34
+
35
+ let output = '';
36
+ let errorOutput = '';
37
+
38
+ child.stdout.on('data', (data) => {
39
+ output += data.toString();
40
+ });
41
+
42
+ child.stderr.on('data', (data) => {
43
+ errorOutput += data.toString();
44
+ });
45
+
46
+ child.on('close', (code) => {
47
+ if (code === 0 && output.trim()) {
48
+ // TaskMaster is installed, get version
49
+ const versionChild = spawn('task-master', ['--version'], {
50
+ stdio: ['ignore', 'pipe', 'pipe'],
51
+ shell: true
52
+ });
53
+
54
+ let versionOutput = '';
55
+
56
+ versionChild.stdout.on('data', (data) => {
57
+ versionOutput += data.toString();
58
+ });
59
+
60
+ versionChild.on('close', (versionCode) => {
61
+ resolve({
62
+ isInstalled: true,
63
+ installPath: output.trim(),
64
+ version: versionCode === 0 ? versionOutput.trim() : 'unknown',
65
+ reason: null
66
+ });
67
+ });
68
+
69
+ versionChild.on('error', () => {
70
+ resolve({
71
+ isInstalled: true,
72
+ installPath: output.trim(),
73
+ version: 'unknown',
74
+ reason: null
75
+ });
76
+ });
77
+ } else {
78
+ resolve({
79
+ isInstalled: false,
80
+ installPath: null,
81
+ version: null,
82
+ reason: 'TaskMaster CLI not found in PATH'
83
+ });
84
+ }
85
+ });
86
+
87
+ child.on('error', (error) => {
88
+ resolve({
89
+ isInstalled: false,
90
+ installPath: null,
91
+ version: null,
92
+ reason: `Error checking installation: ${error.message}`
93
+ });
94
+ });
95
+ });
96
+ }
97
+
98
+
99
+ async function readTaskMasterTasks(projectName) {
100
+ const projectPath = await extractProjectDirectory(projectName);
101
+ const tasksFilePath = path.join(projectPath, '.taskmaster', 'tasks', 'tasks.json');
102
+
103
+ await fsPromises.access(tasksFilePath);
104
+ const tasksContent = await fsPromises.readFile(tasksFilePath, 'utf8');
105
+ const tasksData = JSON.parse(tasksContent);
106
+
107
+ let tasks = [];
108
+ let currentTag = 'master';
109
+
110
+ if (Array.isArray(tasksData)) {
111
+ tasks = tasksData;
112
+ } else if (tasksData.tasks) {
113
+ tasks = tasksData.tasks;
114
+ } else if (tasksData[currentTag] && tasksData[currentTag].tasks) {
115
+ tasks = tasksData[currentTag].tasks;
116
+ } else if (tasksData.master && tasksData.master.tasks) {
117
+ tasks = tasksData.master.tasks;
118
+ } else {
119
+ const firstTag = Object.keys(tasksData).find((key) =>
120
+ tasksData[key].tasks && Array.isArray(tasksData[key].tasks)
121
+ );
122
+ if (firstTag) {
123
+ tasks = tasksData[firstTag].tasks;
124
+ currentTag = firstTag;
125
+ }
126
+ }
127
+
128
+ const transformedTasks = tasks.map((task) => ({
129
+ id: task.id,
130
+ title: task.title || 'Untitled Task',
131
+ description: task.description || '',
132
+ status: task.status || 'pending',
133
+ priority: task.priority || 'medium',
134
+ dependencies: task.dependencies || [],
135
+ createdAt: task.createdAt || task.created || new Date().toISOString(),
136
+ updatedAt: task.updatedAt || task.updated || new Date().toISOString(),
137
+ details: task.details || '',
138
+ testStrategy: task.testStrategy || task.test_strategy || '',
139
+ subtasks: task.subtasks || []
140
+ }));
141
+
142
+ return { projectPath, transformedTasks, currentTag };
143
+ }
144
+
145
+ // API Routes
146
+
147
+ /**
148
+ * GET /api/taskmaster/installation-status
149
+ * Check if TaskMaster CLI is installed on the system
150
+ */
151
+ router.get('/installation-status', async (req, res) => {
152
+ try {
153
+ const installationStatus = await checkTaskMasterInstallation();
154
+
155
+ // Also check for MCP server configuration
156
+ const mcpStatus = await detectTaskMasterMCPServer();
157
+
158
+ res.json({
159
+ success: true,
160
+ installation: installationStatus,
161
+ mcpServer: mcpStatus,
162
+ isReady: installationStatus.isInstalled && mcpStatus.hasMCPServer
163
+ });
164
+ } catch (error) {
165
+ console.error('Error checking TaskMaster installation:', error);
166
+ res.status(500).json({
167
+ success: false,
168
+ error: 'Failed to check TaskMaster installation status',
169
+ installation: {
170
+ isInstalled: false,
171
+ reason: `Server error: ${error.message}`
172
+ },
173
+ mcpServer: {
174
+ hasMCPServer: false,
175
+ reason: `Server error: ${error.message}`
176
+ },
177
+ isReady: false
178
+ });
179
+ }
180
+ });
181
+
182
+ /**
183
+ * GET /api/taskmaster/tasks/:projectName
184
+ * Load actual tasks from .taskmaster/tasks/tasks.json
185
+ */
186
+ router.get('/tasks/:projectName', async (req, res) => {
187
+ try {
188
+ const { projectName } = req.params;
189
+
190
+ const { projectPath, transformedTasks, currentTag } = await readTaskMasterTasks(projectName);
191
+
192
+ res.json({
193
+ projectName,
194
+ projectPath,
195
+ tasks: transformedTasks,
196
+ currentTag,
197
+ totalTasks: transformedTasks.length,
198
+ tasksByStatus: {
199
+ pending: transformedTasks.filter(t => t.status === 'pending').length,
200
+ 'in-progress': transformedTasks.filter(t => t.status === 'in-progress').length,
201
+ done: transformedTasks.filter(t => t.status === 'done').length,
202
+ review: transformedTasks.filter(t => t.status === 'review').length,
203
+ deferred: transformedTasks.filter(t => t.status === 'deferred').length,
204
+ cancelled: transformedTasks.filter(t => t.status === 'cancelled').length
205
+ },
206
+ timestamp: new Date().toISOString()
207
+ });
208
+
209
+ } catch (error) {
210
+ if (error?.code === 'ENOENT') {
211
+ return res.json({
212
+ projectName: req.params.projectName,
213
+ tasks: [],
214
+ message: 'No tasks.json file found'
215
+ });
216
+ }
217
+ if (String(error?.message || '').includes('does not exist')) {
218
+ return res.status(404).json({
219
+ error: 'Project not found',
220
+ message: `Project "${req.params.projectName}" does not exist`
221
+ });
222
+ }
223
+ console.error('TaskMaster tasks loading error:', error);
224
+ res.status(500).json({
225
+ error: 'Failed to load TaskMaster tasks',
226
+ message: error.message
227
+ });
228
+ }
229
+ });
230
+
231
+ /**
232
+ * POST /api/taskmaster/sync-orchestration/:projectName
233
+ * One-way sync: TaskMaster -> Orchestration tasks
234
+ */
235
+ router.post('/sync-orchestration/:projectName', async (req, res) => {
236
+ try {
237
+ const { projectName } = req.params;
238
+ const { transformedTasks } = await readTaskMasterTasks(projectName);
239
+
240
+ const projectId = typeof req.body?.projectId === 'string' && req.body.projectId.trim()
241
+ ? req.body.projectId.trim()
242
+ : projectName;
243
+
244
+ const syncedTasks = transformedTasks.map((task) =>
245
+ orchestrationTaskService.upsertFromTaskMaster({
246
+ projectId,
247
+ taskmasterId: String(task.id),
248
+ title: task.title,
249
+ description: task.description,
250
+ })
251
+ );
252
+
253
+ res.json({
254
+ success: true,
255
+ projectName,
256
+ projectId,
257
+ synced: syncedTasks.length,
258
+ tasks: syncedTasks,
259
+ timestamp: new Date().toISOString(),
260
+ });
261
+ } catch (error) {
262
+ if (error?.code === 'ENOENT') {
263
+ return res.json({ success: true, projectName: req.params.projectName, synced: 0, tasks: [] });
264
+ }
265
+ console.error('TaskMaster orchestration sync error:', error);
266
+ res.status(500).json({
267
+ success: false,
268
+ error: 'Failed to sync TaskMaster tasks to orchestration',
269
+ message: error.message,
270
+ });
271
+ }
272
+ });
273
+
274
+ /**
275
+ * GET /api/taskmaster/prd/:projectName
276
+ * List all PRD files in the project's .taskmaster/docs directory
277
+ */
278
+ router.get('/prd/:projectName', async (req, res) => {
279
+ try {
280
+ const { projectName } = req.params;
281
+
282
+ // Get project path
283
+ let projectPath;
284
+ try {
285
+ projectPath = await extractProjectDirectory(projectName);
286
+ } catch (error) {
287
+ return res.status(404).json({
288
+ error: 'Project not found',
289
+ message: `Project "${projectName}" does not exist`
290
+ });
291
+ }
292
+
293
+ const docsPath = path.join(projectPath, '.taskmaster', 'docs');
294
+
295
+ // Check if docs directory exists
296
+ try {
297
+ await fsPromises.access(docsPath, fs.constants.R_OK);
298
+ } catch (error) {
299
+ return res.json({
300
+ projectName,
301
+ prdFiles: [],
302
+ message: 'No .taskmaster/docs directory found'
303
+ });
304
+ }
305
+
306
+ // Read directory and filter for PRD files
307
+ try {
308
+ const files = await fsPromises.readdir(docsPath);
309
+ const prdFiles = [];
310
+
311
+ for (const file of files) {
312
+ const filePath = path.join(docsPath, file);
313
+ const stats = await fsPromises.stat(filePath);
314
+
315
+ if (stats.isFile() && (file.endsWith('.txt') || file.endsWith('.md'))) {
316
+ prdFiles.push({
317
+ name: file,
318
+ path: path.relative(projectPath, filePath),
319
+ size: stats.size,
320
+ modified: stats.mtime.toISOString(),
321
+ created: stats.birthtime.toISOString()
322
+ });
323
+ }
324
+ }
325
+
326
+ res.json({
327
+ projectName,
328
+ projectPath,
329
+ prdFiles: prdFiles.sort((a, b) => new Date(b.modified) - new Date(a.modified)),
330
+ timestamp: new Date().toISOString()
331
+ });
332
+
333
+ } catch (readError) {
334
+ console.error('Error reading docs directory:', readError);
335
+ return res.status(500).json({
336
+ error: 'Failed to read PRD files',
337
+ message: readError.message
338
+ });
339
+ }
340
+
341
+ } catch (error) {
342
+ console.error('PRD list error:', error);
343
+ res.status(500).json({
344
+ error: 'Failed to list PRD files',
345
+ message: error.message
346
+ });
347
+ }
348
+ });
349
+
350
+ /**
351
+ * POST /api/taskmaster/prd/:projectName
352
+ * Create or update a PRD file in the project's .taskmaster/docs directory
353
+ */
354
+ router.post('/prd/:projectName', async (req, res) => {
355
+ try {
356
+ const { projectName } = req.params;
357
+ const { fileName, content } = req.body;
358
+
359
+ if (!fileName || !content) {
360
+ return res.status(400).json({
361
+ error: 'Missing required fields',
362
+ message: 'fileName and content are required'
363
+ });
364
+ }
365
+
366
+ // Validate filename
367
+ if (!fileName.match(/^[\w\-. ]+\.(txt|md)$/)) {
368
+ return res.status(400).json({
369
+ error: 'Invalid filename',
370
+ message: 'Filename must end with .txt or .md and contain only alphanumeric characters, spaces, dots, and dashes'
371
+ });
372
+ }
373
+
374
+ // Get project path
375
+ let projectPath;
376
+ try {
377
+ projectPath = await extractProjectDirectory(projectName);
378
+ } catch (error) {
379
+ return res.status(404).json({
380
+ error: 'Project not found',
381
+ message: `Project "${projectName}" does not exist`
382
+ });
383
+ }
384
+
385
+ const docsPath = path.join(projectPath, '.taskmaster', 'docs');
386
+ const filePath = path.join(docsPath, fileName);
387
+
388
+ // Ensure docs directory exists
389
+ try {
390
+ await fsPromises.mkdir(docsPath, { recursive: true });
391
+ } catch (error) {
392
+ console.error('Failed to create docs directory:', error);
393
+ return res.status(500).json({
394
+ error: 'Failed to create directory',
395
+ message: error.message
396
+ });
397
+ }
398
+
399
+ // Write the PRD file
400
+ try {
401
+ await fsPromises.writeFile(filePath, content, 'utf8');
402
+
403
+ // Get file stats
404
+ const stats = await fsPromises.stat(filePath);
405
+
406
+ res.json({
407
+ projectName,
408
+ projectPath,
409
+ fileName,
410
+ filePath: path.relative(projectPath, filePath),
411
+ size: stats.size,
412
+ created: stats.birthtime.toISOString(),
413
+ modified: stats.mtime.toISOString(),
414
+ message: 'PRD file saved successfully',
415
+ timestamp: new Date().toISOString()
416
+ });
417
+
418
+ } catch (writeError) {
419
+ console.error('Failed to write PRD file:', writeError);
420
+ return res.status(500).json({
421
+ error: 'Failed to write PRD file',
422
+ message: writeError.message
423
+ });
424
+ }
425
+
426
+ } catch (error) {
427
+ console.error('PRD create/update error:', error);
428
+ res.status(500).json({
429
+ error: 'Failed to create/update PRD file',
430
+ message: error.message
431
+ });
432
+ }
433
+ });
434
+
435
+ /**
436
+ * GET /api/taskmaster/prd/:projectName/:fileName
437
+ * Get content of a specific PRD file
438
+ */
439
+ router.get('/prd/:projectName/:fileName', async (req, res) => {
440
+ try {
441
+ const { projectName, fileName } = req.params;
442
+
443
+ // Get project path
444
+ let projectPath;
445
+ try {
446
+ projectPath = await extractProjectDirectory(projectName);
447
+ } catch (error) {
448
+ return res.status(404).json({
449
+ error: 'Project not found',
450
+ message: `Project "${projectName}" does not exist`
451
+ });
452
+ }
453
+
454
+ const filePath = path.join(projectPath, '.taskmaster', 'docs', fileName);
455
+
456
+ // Check if file exists
457
+ try {
458
+ await fsPromises.access(filePath, fs.constants.R_OK);
459
+ } catch (error) {
460
+ return res.status(404).json({
461
+ error: 'PRD file not found',
462
+ message: `File "${fileName}" does not exist`
463
+ });
464
+ }
465
+
466
+ // Read file content
467
+ try {
468
+ const content = await fsPromises.readFile(filePath, 'utf8');
469
+ const stats = await fsPromises.stat(filePath);
470
+
471
+ res.json({
472
+ projectName,
473
+ projectPath,
474
+ fileName,
475
+ filePath: path.relative(projectPath, filePath),
476
+ content,
477
+ size: stats.size,
478
+ created: stats.birthtime.toISOString(),
479
+ modified: stats.mtime.toISOString(),
480
+ timestamp: new Date().toISOString()
481
+ });
482
+
483
+ } catch (readError) {
484
+ console.error('Failed to read PRD file:', readError);
485
+ return res.status(500).json({
486
+ error: 'Failed to read PRD file',
487
+ message: readError.message
488
+ });
489
+ }
490
+
491
+ } catch (error) {
492
+ console.error('PRD read error:', error);
493
+ res.status(500).json({
494
+ error: 'Failed to read PRD file',
495
+ message: error.message
496
+ });
497
+ }
498
+ });
499
+
500
+ /**
501
+ * POST /api/taskmaster/init/:projectName
502
+ * Initialize TaskMaster in a project
503
+ */
504
+ router.post('/init/:projectName', async (req, res) => {
505
+ try {
506
+ const { projectName } = req.params;
507
+
508
+ // Get project path
509
+ let projectPath;
510
+ try {
511
+ projectPath = await extractProjectDirectory(projectName);
512
+ } catch (error) {
513
+ return res.status(404).json({
514
+ error: 'Project not found',
515
+ message: `Project "${projectName}" does not exist`
516
+ });
517
+ }
518
+
519
+ // Check if TaskMaster is already initialized
520
+ const taskMasterPath = path.join(projectPath, '.taskmaster');
521
+ try {
522
+ await fsPromises.access(taskMasterPath, fs.constants.F_OK);
523
+ return res.status(400).json({
524
+ error: 'TaskMaster already initialized',
525
+ message: 'TaskMaster is already configured for this project'
526
+ });
527
+ } catch (error) {
528
+ // Directory doesn't exist, we can proceed
529
+ }
530
+
531
+ // Run taskmaster init command
532
+ const initProcess = spawn('npx', ['task-master', 'init'], {
533
+ cwd: projectPath,
534
+ stdio: ['pipe', 'pipe', 'pipe']
535
+ });
536
+
537
+ let stdout = '';
538
+ let stderr = '';
539
+
540
+ initProcess.stdout.on('data', (data) => {
541
+ stdout += data.toString();
542
+ });
543
+
544
+ initProcess.stderr.on('data', (data) => {
545
+ stderr += data.toString();
546
+ });
547
+
548
+ initProcess.on('close', (code) => {
549
+ if (code === 0) {
550
+ // Broadcast TaskMaster project update via WebSocket
551
+ if (req.app.locals.wss) {
552
+ broadcastTaskMasterProjectUpdate(
553
+ req.app.locals.wss,
554
+ projectName,
555
+ { hasTaskmaster: true, status: 'initialized' }
556
+ );
557
+ }
558
+
559
+ res.json({
560
+ projectName,
561
+ projectPath,
562
+ message: 'TaskMaster initialized successfully',
563
+ output: stdout,
564
+ timestamp: new Date().toISOString()
565
+ });
566
+ } else {
567
+ console.error('TaskMaster init failed:', stderr);
568
+ res.status(500).json({
569
+ error: 'Failed to initialize TaskMaster',
570
+ message: stderr || stdout,
571
+ code
572
+ });
573
+ }
574
+ });
575
+
576
+ // Send 'yes' responses to automated prompts
577
+ initProcess.stdin.write('yes\n');
578
+ initProcess.stdin.end();
579
+
580
+ } catch (error) {
581
+ console.error('TaskMaster init error:', error);
582
+ res.status(500).json({
583
+ error: 'Failed to initialize TaskMaster',
584
+ message: error.message
585
+ });
586
+ }
587
+ });
588
+
589
+ /**
590
+ * POST /api/taskmaster/add-task/:projectName
591
+ * Add a new task to the project
592
+ */
593
+ router.post('/add-task/:projectName', async (req, res) => {
594
+ try {
595
+ const { projectName } = req.params;
596
+ const { prompt, title, description, priority = 'medium', dependencies } = req.body;
597
+
598
+ if (!prompt && (!title || !description)) {
599
+ return res.status(400).json({
600
+ error: 'Missing required parameters',
601
+ message: 'Either "prompt" or both "title" and "description" are required'
602
+ });
603
+ }
604
+
605
+ // Get project path
606
+ let projectPath;
607
+ try {
608
+ projectPath = await extractProjectDirectory(projectName);
609
+ } catch (error) {
610
+ return res.status(404).json({
611
+ error: 'Project not found',
612
+ message: `Project "${projectName}" does not exist`
613
+ });
614
+ }
615
+
616
+ // Build the task-master add-task command
617
+ const args = ['task-master-ai', 'add-task'];
618
+
619
+ if (prompt) {
620
+ args.push('--prompt', prompt);
621
+ args.push('--research'); // Use research for AI-generated tasks
622
+ } else {
623
+ args.push('--prompt', `Create a task titled "${title}" with description: ${description}`);
624
+ }
625
+
626
+ if (priority) {
627
+ args.push('--priority', priority);
628
+ }
629
+
630
+ if (dependencies) {
631
+ args.push('--dependencies', dependencies);
632
+ }
633
+
634
+ // Run task-master add-task command
635
+ const addTaskProcess = spawn('npx', args, {
636
+ cwd: projectPath,
637
+ stdio: ['pipe', 'pipe', 'pipe']
638
+ });
639
+
640
+ let stdout = '';
641
+ let stderr = '';
642
+
643
+ addTaskProcess.stdout.on('data', (data) => {
644
+ stdout += data.toString();
645
+ });
646
+
647
+ addTaskProcess.stderr.on('data', (data) => {
648
+ stderr += data.toString();
649
+ });
650
+
651
+ addTaskProcess.on('close', (code) => {
652
+ console.log('Add task process completed with code:', code);
653
+ console.log('Stdout:', stdout);
654
+ console.log('Stderr:', stderr);
655
+
656
+ if (code === 0) {
657
+ // Broadcast task update via WebSocket
658
+ if (req.app.locals.wss) {
659
+ broadcastTaskMasterTasksUpdate(
660
+ req.app.locals.wss,
661
+ projectName
662
+ );
663
+ }
664
+
665
+ res.json({
666
+ projectName,
667
+ projectPath,
668
+ message: 'Task added successfully',
669
+ output: stdout,
670
+ timestamp: new Date().toISOString()
671
+ });
672
+ } else {
673
+ console.error('Add task failed:', stderr);
674
+ res.status(500).json({
675
+ error: 'Failed to add task',
676
+ message: stderr || stdout,
677
+ code
678
+ });
679
+ }
680
+ });
681
+
682
+ addTaskProcess.stdin.end();
683
+
684
+ } catch (error) {
685
+ console.error('Add task error:', error);
686
+ res.status(500).json({
687
+ error: 'Failed to add task',
688
+ message: error.message
689
+ });
690
+ }
691
+ });
692
+
693
+ /**
694
+ * PUT /api/taskmaster/update-task/:projectName/:taskId
695
+ * Update a specific task using TaskMaster CLI
696
+ */
697
+ router.put('/update-task/:projectName/:taskId', async (req, res) => {
698
+ try {
699
+ const { projectName, taskId } = req.params;
700
+ const { title, description, status, priority, details } = req.body;
701
+
702
+ // Get project path
703
+ let projectPath;
704
+ try {
705
+ projectPath = await extractProjectDirectory(projectName);
706
+ } catch (error) {
707
+ return res.status(404).json({
708
+ error: 'Project not found',
709
+ message: `Project "${projectName}" does not exist`
710
+ });
711
+ }
712
+
713
+ // If only updating status, use set-status command
714
+ if (status && Object.keys(req.body).length === 1) {
715
+ const setStatusProcess = spawn('npx', ['task-master-ai', 'set-status', `--id=${taskId}`, `--status=${status}`], {
716
+ cwd: projectPath,
717
+ stdio: ['pipe', 'pipe', 'pipe']
718
+ });
719
+
720
+ let stdout = '';
721
+ let stderr = '';
722
+
723
+ setStatusProcess.stdout.on('data', (data) => {
724
+ stdout += data.toString();
725
+ });
726
+
727
+ setStatusProcess.stderr.on('data', (data) => {
728
+ stderr += data.toString();
729
+ });
730
+
731
+ setStatusProcess.on('close', (code) => {
732
+ if (code === 0) {
733
+ // Broadcast task update via WebSocket
734
+ if (req.app.locals.wss) {
735
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
736
+ }
737
+
738
+ res.json({
739
+ projectName,
740
+ projectPath,
741
+ taskId,
742
+ message: 'Task status updated successfully',
743
+ output: stdout,
744
+ timestamp: new Date().toISOString()
745
+ });
746
+ } else {
747
+ console.error('Set task status failed:', stderr);
748
+ res.status(500).json({
749
+ error: 'Failed to update task status',
750
+ message: stderr || stdout,
751
+ code
752
+ });
753
+ }
754
+ });
755
+
756
+ setStatusProcess.stdin.end();
757
+ } else {
758
+ // For other updates, use update-task command with a prompt describing the changes
759
+ const updates = [];
760
+ if (title) updates.push(`title: "${title}"`);
761
+ if (description) updates.push(`description: "${description}"`);
762
+ if (priority) updates.push(`priority: "${priority}"`);
763
+ if (details) updates.push(`details: "${details}"`);
764
+
765
+ const prompt = `Update task with the following changes: ${updates.join(', ')}`;
766
+
767
+ const updateProcess = spawn('npx', ['task-master-ai', 'update-task', `--id=${taskId}`, `--prompt=${prompt}`], {
768
+ cwd: projectPath,
769
+ stdio: ['pipe', 'pipe', 'pipe']
770
+ });
771
+
772
+ let stdout = '';
773
+ let stderr = '';
774
+
775
+ updateProcess.stdout.on('data', (data) => {
776
+ stdout += data.toString();
777
+ });
778
+
779
+ updateProcess.stderr.on('data', (data) => {
780
+ stderr += data.toString();
781
+ });
782
+
783
+ updateProcess.on('close', (code) => {
784
+ if (code === 0) {
785
+ // Broadcast task update via WebSocket
786
+ if (req.app.locals.wss) {
787
+ broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectName);
788
+ }
789
+
790
+ res.json({
791
+ projectName,
792
+ projectPath,
793
+ taskId,
794
+ message: 'Task updated successfully',
795
+ output: stdout,
796
+ timestamp: new Date().toISOString()
797
+ });
798
+ } else {
799
+ console.error('Update task failed:', stderr);
800
+ res.status(500).json({
801
+ error: 'Failed to update task',
802
+ message: stderr || stdout,
803
+ code
804
+ });
805
+ }
806
+ });
807
+
808
+ updateProcess.stdin.end();
809
+ }
810
+
811
+ } catch (error) {
812
+ console.error('Update task error:', error);
813
+ res.status(500).json({
814
+ error: 'Failed to update task',
815
+ message: error.message
816
+ });
817
+ }
818
+ });
819
+
820
+ /**
821
+ * POST /api/taskmaster/parse-prd/:projectName
822
+ * Parse a PRD file to generate tasks
823
+ */
824
+ router.post('/parse-prd/:projectName', async (req, res) => {
825
+ try {
826
+ const { projectName } = req.params;
827
+ const { fileName = 'prd.txt', numTasks, append = false } = req.body;
828
+
829
+ // Get project path
830
+ let projectPath;
831
+ try {
832
+ projectPath = await extractProjectDirectory(projectName);
833
+ } catch (error) {
834
+ return res.status(404).json({
835
+ error: 'Project not found',
836
+ message: `Project "${projectName}" does not exist`
837
+ });
838
+ }
839
+
840
+ const prdPath = path.join(projectPath, '.taskmaster', 'docs', fileName);
841
+
842
+ // Check if PRD file exists
843
+ try {
844
+ await fsPromises.access(prdPath, fs.constants.F_OK);
845
+ } catch (error) {
846
+ return res.status(404).json({
847
+ error: 'PRD file not found',
848
+ message: `File "${fileName}" does not exist in .taskmaster/docs/`
849
+ });
850
+ }
851
+
852
+ // Build the command args
853
+ const args = ['task-master-ai', 'parse-prd', prdPath];
854
+
855
+ if (numTasks) {
856
+ args.push('--num-tasks', numTasks.toString());
857
+ }
858
+
859
+ if (append) {
860
+ args.push('--append');
861
+ }
862
+
863
+ args.push('--research'); // Use research for better PRD parsing
864
+
865
+ // Run task-master parse-prd command
866
+ const parsePRDProcess = spawn('npx', args, {
867
+ cwd: projectPath,
868
+ stdio: ['pipe', 'pipe', 'pipe']
869
+ });
870
+
871
+ let stdout = '';
872
+ let stderr = '';
873
+
874
+ parsePRDProcess.stdout.on('data', (data) => {
875
+ stdout += data.toString();
876
+ });
877
+
878
+ parsePRDProcess.stderr.on('data', (data) => {
879
+ stderr += data.toString();
880
+ });
881
+
882
+ parsePRDProcess.on('close', (code) => {
883
+ if (code === 0) {
884
+ // Broadcast task update via WebSocket
885
+ if (req.app.locals.wss) {
886
+ broadcastTaskMasterTasksUpdate(
887
+ req.app.locals.wss,
888
+ projectName
889
+ );
890
+ }
891
+
892
+ res.json({
893
+ projectName,
894
+ projectPath,
895
+ prdFile: fileName,
896
+ message: 'PRD parsed and tasks generated successfully',
897
+ output: stdout,
898
+ timestamp: new Date().toISOString()
899
+ });
900
+ } else {
901
+ console.error('Parse PRD failed:', stderr);
902
+ res.status(500).json({
903
+ error: 'Failed to parse PRD',
904
+ message: stderr || stdout,
905
+ code
906
+ });
907
+ }
908
+ });
909
+
910
+ parsePRDProcess.stdin.end();
911
+
912
+ } catch (error) {
913
+ console.error('Parse PRD error:', error);
914
+ res.status(500).json({
915
+ error: 'Failed to parse PRD',
916
+ message: error.message
917
+ });
918
+ }
919
+ });
920
+
921
+ /**
922
+ * GET /api/taskmaster/prd-templates
923
+ * Get available PRD templates
924
+ */
925
+ router.get('/prd-templates', async (req, res) => {
926
+ try {
927
+ // Return built-in templates
928
+ const templates = [
929
+ {
930
+ id: 'web-app',
931
+ name: 'Web Application',
932
+ description: 'Template for web application projects with frontend and backend components',
933
+ category: 'web',
934
+ content: `# Product Requirements Document - Web Application
935
+
936
+ ## Overview
937
+ **Product Name:** [Your App Name]
938
+ **Version:** 1.0
939
+ **Date:** ${new Date().toISOString().split('T')[0]}
940
+ **Author:** [Your Name]
941
+
942
+ ## Executive Summary
943
+ Brief description of what this web application will do and why it's needed.
944
+
945
+ ## Product Goals
946
+ - Goal 1: [Specific measurable goal]
947
+ - Goal 2: [Specific measurable goal]
948
+ - Goal 3: [Specific measurable goal]
949
+
950
+ ## User Stories
951
+ ### Core Features
952
+ 1. **User Registration & Authentication**
953
+ - As a user, I want to create an account so I can access personalized features
954
+ - As a user, I want to log in securely so my data is protected
955
+ - As a user, I want to reset my password if I forget it
956
+
957
+ 2. **Main Application Features**
958
+ - As a user, I want to [core feature 1] so I can [benefit]
959
+ - As a user, I want to [core feature 2] so I can [benefit]
960
+ - As a user, I want to [core feature 3] so I can [benefit]
961
+
962
+ 3. **User Interface**
963
+ - As a user, I want a responsive design so I can use the app on any device
964
+ - As a user, I want intuitive navigation so I can easily find features
965
+
966
+ ## Technical Requirements
967
+ ### Frontend
968
+ - Framework: React/Vue/Angular or vanilla JavaScript
969
+ - Styling: CSS framework (Tailwind, Bootstrap, etc.)
970
+ - State Management: Redux/Vuex/Context API
971
+ - Build Tools: Webpack/Vite
972
+ - Testing: Jest/Vitest for unit tests
973
+
974
+ ### Backend
975
+ - Runtime: Node.js/Python/Java
976
+ - Database: PostgreSQL/MySQL/MongoDB
977
+ - API: RESTful API or GraphQL
978
+ - Authentication: JWT tokens
979
+ - Testing: Integration and unit tests
980
+
981
+ ### Infrastructure
982
+ - Hosting: Cloud provider (AWS, Azure, GCP)
983
+ - CI/CD: GitHub Actions/GitLab CI
984
+ - Monitoring: Application monitoring tools
985
+ - Security: HTTPS, input validation, rate limiting
986
+
987
+ ## Success Metrics
988
+ - User engagement metrics
989
+ - Performance benchmarks (load time < 2s)
990
+ - Error rates < 1%
991
+ - User satisfaction scores
992
+
993
+ ## Timeline
994
+ - Phase 1: Core functionality (4-6 weeks)
995
+ - Phase 2: Advanced features (2-4 weeks)
996
+ - Phase 3: Polish and launch (2 weeks)
997
+
998
+ ## Constraints & Assumptions
999
+ - Budget constraints
1000
+ - Technical limitations
1001
+ - Team size and expertise
1002
+ - Timeline constraints`
1003
+ },
1004
+ {
1005
+ id: 'api',
1006
+ name: 'REST API',
1007
+ description: 'Template for REST API development projects',
1008
+ category: 'backend',
1009
+ content: `# Product Requirements Document - REST API
1010
+
1011
+ ## Overview
1012
+ **API Name:** [Your API Name]
1013
+ **Version:** v1.0
1014
+ **Date:** ${new Date().toISOString().split('T')[0]}
1015
+ **Author:** [Your Name]
1016
+
1017
+ ## Executive Summary
1018
+ Description of the API's purpose, target users, and primary use cases.
1019
+
1020
+ ## API Goals
1021
+ - Goal 1: Provide secure data access
1022
+ - Goal 2: Ensure scalable architecture
1023
+ - Goal 3: Maintain high availability (99.9% uptime)
1024
+
1025
+ ## Functional Requirements
1026
+ ### Core Endpoints
1027
+ 1. **Authentication Endpoints**
1028
+ - POST /api/auth/login - User authentication
1029
+ - POST /api/auth/logout - User logout
1030
+ - POST /api/auth/refresh - Token refresh
1031
+ - POST /api/auth/register - User registration
1032
+
1033
+ 2. **Data Management Endpoints**
1034
+ - GET /api/resources - List resources with pagination
1035
+ - GET /api/resources/{id} - Get specific resource
1036
+ - POST /api/resources - Create new resource
1037
+ - PUT /api/resources/{id} - Update existing resource
1038
+ - DELETE /api/resources/{id} - Delete resource
1039
+
1040
+ 3. **Administrative Endpoints**
1041
+ - GET /api/admin/users - Manage users (admin only)
1042
+ - GET /api/admin/analytics - System analytics
1043
+ - POST /api/admin/backup - Trigger system backup
1044
+
1045
+ ## Technical Requirements
1046
+ ### API Design
1047
+ - RESTful architecture following OpenAPI 3.0 specification
1048
+ - JSON request/response format
1049
+ - Consistent error response format
1050
+ - API versioning strategy
1051
+
1052
+ ### Authentication & Security
1053
+ - JWT token-based authentication
1054
+ - Role-based access control (RBAC)
1055
+ - Rate limiting (100 requests/minute per user)
1056
+ - Input validation and sanitization
1057
+ - HTTPS enforcement
1058
+
1059
+ ### Database
1060
+ - Database type: [PostgreSQL/MongoDB/MySQL]
1061
+ - Connection pooling
1062
+ - Database migrations
1063
+ - Backup and recovery procedures
1064
+
1065
+ ### Performance Requirements
1066
+ - Response time: < 200ms for 95% of requests
1067
+ - Throughput: 1000+ requests/second
1068
+ - Concurrent users: 10,000+
1069
+ - Database query optimization
1070
+
1071
+ ### Documentation
1072
+ - Auto-generated API documentation (Swagger/OpenAPI)
1073
+ - Code examples for common use cases
1074
+ - SDK development for major languages
1075
+ - Postman collection for testing
1076
+
1077
+ ## Error Handling
1078
+ - Standardized error codes and messages
1079
+ - Proper HTTP status codes
1080
+ - Detailed error logging
1081
+ - Graceful degradation strategies
1082
+
1083
+ ## Testing Strategy
1084
+ - Unit tests (80%+ coverage)
1085
+ - Integration tests for all endpoints
1086
+ - Load testing and performance testing
1087
+ - Security testing (OWASP compliance)
1088
+
1089
+ ## Monitoring & Logging
1090
+ - Application performance monitoring
1091
+ - Error tracking and alerting
1092
+ - Access logs and audit trails
1093
+ - Health check endpoints
1094
+
1095
+ ## Deployment
1096
+ - Containerized deployment (Docker)
1097
+ - CI/CD pipeline setup
1098
+ - Environment management (dev, staging, prod)
1099
+ - Blue-green deployment strategy
1100
+
1101
+ ## Success Metrics
1102
+ - API uptime > 99.9%
1103
+ - Average response time < 200ms
1104
+ - Zero critical security vulnerabilities
1105
+ - Developer adoption metrics`
1106
+ },
1107
+ {
1108
+ id: 'mobile-app',
1109
+ name: 'Mobile Application',
1110
+ description: 'Template for mobile app development projects (iOS/Android)',
1111
+ category: 'mobile',
1112
+ content: `# Product Requirements Document - Mobile Application
1113
+
1114
+ ## Overview
1115
+ **App Name:** [Your App Name]
1116
+ **Platform:** iOS / Android / Cross-platform
1117
+ **Version:** 1.0
1118
+ **Date:** ${new Date().toISOString().split('T')[0]}
1119
+ **Author:** [Your Name]
1120
+
1121
+ ## Executive Summary
1122
+ Brief description of the mobile app's purpose, target audience, and key value proposition.
1123
+
1124
+ ## Product Goals
1125
+ - Goal 1: [Specific user engagement goal]
1126
+ - Goal 2: [Specific functionality goal]
1127
+ - Goal 3: [Specific performance goal]
1128
+
1129
+ ## User Stories
1130
+ ### Core Features
1131
+ 1. **Onboarding & Authentication**
1132
+ - As a new user, I want a simple onboarding process
1133
+ - As a user, I want to sign up with email or social media
1134
+ - As a user, I want biometric authentication for security
1135
+
1136
+ 2. **Main App Features**
1137
+ - As a user, I want [core feature 1] accessible from home screen
1138
+ - As a user, I want [core feature 2] to work offline
1139
+ - As a user, I want to sync data across devices
1140
+
1141
+ 3. **User Experience**
1142
+ - As a user, I want intuitive navigation patterns
1143
+ - As a user, I want fast loading times
1144
+ - As a user, I want accessibility features
1145
+
1146
+ ## Technical Requirements
1147
+ ### Mobile Development
1148
+ - **Cross-platform:** React Native / Flutter / Xamarin
1149
+ - **Native:** Swift (iOS) / Kotlin (Android)
1150
+ - **State Management:** Redux / MobX / Provider
1151
+ - **Navigation:** React Navigation / Flutter Navigation
1152
+
1153
+ ### Backend Integration
1154
+ - REST API or GraphQL integration
1155
+ - Real-time features (WebSockets/Push notifications)
1156
+ - Offline data synchronization
1157
+ - Background processing
1158
+
1159
+ ### Device Features
1160
+ - Camera and photo library access
1161
+ - GPS location services
1162
+ - Push notifications
1163
+ - Biometric authentication
1164
+ - Device storage
1165
+
1166
+ ### Performance Requirements
1167
+ - App launch time < 3 seconds
1168
+ - Screen transition animations < 300ms
1169
+ - Memory usage optimization
1170
+ - Battery usage optimization
1171
+
1172
+ ## Platform-Specific Considerations
1173
+ ### iOS Requirements
1174
+ - iOS 13.0+ minimum version
1175
+ - App Store guidelines compliance
1176
+ - iOS design guidelines (Human Interface Guidelines)
1177
+ - TestFlight beta testing
1178
+
1179
+ ### Android Requirements
1180
+ - Android 8.0+ (API level 26) minimum
1181
+ - Google Play Store guidelines
1182
+ - Material Design guidelines
1183
+ - Google Play Console testing
1184
+
1185
+ ## User Interface Design
1186
+ - Responsive design for different screen sizes
1187
+ - Dark mode support
1188
+ - Accessibility compliance (WCAG 2.1)
1189
+ - Consistent design system
1190
+
1191
+ ## Security & Privacy
1192
+ - Secure data storage (Keychain/Keystore)
1193
+ - API communication encryption
1194
+ - Privacy policy compliance (GDPR/CCPA)
1195
+ - App security best practices
1196
+
1197
+ ## Testing Strategy
1198
+ - Unit testing (80%+ coverage)
1199
+ - UI/E2E testing (Detox/Appium)
1200
+ - Device testing on multiple screen sizes
1201
+ - Performance testing
1202
+ - Security testing
1203
+
1204
+ ## App Store Deployment
1205
+ - App store optimization (ASO)
1206
+ - App icons and screenshots
1207
+ - Store listing content
1208
+ - Release management strategy
1209
+
1210
+ ## Analytics & Monitoring
1211
+ - User analytics (Firebase/Analytics)
1212
+ - Crash reporting (Crashlytics/Sentry)
1213
+ - Performance monitoring
1214
+ - User feedback collection
1215
+
1216
+ ## Success Metrics
1217
+ - App store ratings > 4.0
1218
+ - User retention rates
1219
+ - Daily/Monthly active users
1220
+ - App performance metrics
1221
+ - Conversion rates`
1222
+ },
1223
+ {
1224
+ id: 'data-analysis',
1225
+ name: 'Data Analysis Project',
1226
+ description: 'Template for data analysis and visualization projects',
1227
+ category: 'data',
1228
+ content: `# Product Requirements Document - Data Analysis Project
1229
+
1230
+ ## Overview
1231
+ **Project Name:** [Your Analysis Project]
1232
+ **Analysis Type:** [Descriptive/Predictive/Prescriptive]
1233
+ **Date:** ${new Date().toISOString().split('T')[0]}
1234
+ **Author:** [Your Name]
1235
+
1236
+ ## Executive Summary
1237
+ Description of the business problem, data sources, and expected insights.
1238
+
1239
+ ## Project Goals
1240
+ - Goal 1: [Specific business question to answer]
1241
+ - Goal 2: [Specific prediction to make]
1242
+ - Goal 3: [Specific recommendation to provide]
1243
+
1244
+ ## Business Requirements
1245
+ ### Key Questions
1246
+ 1. What patterns exist in the current data?
1247
+ 2. What factors influence [target variable]?
1248
+ 3. What predictions can be made for [future outcome]?
1249
+ 4. What recommendations can improve [business metric]?
1250
+
1251
+ ### Success Criteria
1252
+ - Actionable insights for stakeholders
1253
+ - Statistical significance in findings
1254
+ - Reproducible analysis pipeline
1255
+ - Clear visualization and reporting
1256
+
1257
+ ## Data Requirements
1258
+ ### Data Sources
1259
+ 1. **Primary Data**
1260
+ - Source: [Database/API/Files]
1261
+ - Format: [CSV/JSON/SQL]
1262
+ - Size: [Volume estimate]
1263
+ - Update frequency: [Real-time/Daily/Monthly]
1264
+
1265
+ 2. **External Data**
1266
+ - Third-party APIs
1267
+ - Public datasets
1268
+ - Market research data
1269
+
1270
+ ### Data Quality Requirements
1271
+ - Data completeness (< 5% missing values)
1272
+ - Data accuracy validation
1273
+ - Data consistency checks
1274
+ - Historical data availability
1275
+
1276
+ ## Technical Requirements
1277
+ ### Data Pipeline
1278
+ - Data extraction and ingestion
1279
+ - Data cleaning and preprocessing
1280
+ - Data transformation and feature engineering
1281
+ - Data validation and quality checks
1282
+
1283
+ ### Analysis Tools
1284
+ - **Programming:** Python/R/SQL
1285
+ - **Libraries:** pandas, numpy, scikit-learn, matplotlib
1286
+ - **Visualization:** Tableau, PowerBI, or custom dashboards
1287
+ - **Version Control:** Git for code and DVC for data
1288
+
1289
+ ### Computing Resources
1290
+ - Local development environment
1291
+ - Cloud computing (AWS/GCP/Azure) if needed
1292
+ - Database access and permissions
1293
+ - Storage requirements
1294
+
1295
+ ## Analysis Methodology
1296
+ ### Data Exploration
1297
+ 1. Descriptive statistics and data profiling
1298
+ 2. Data visualization and pattern identification
1299
+ 3. Correlation analysis
1300
+ 4. Outlier detection and handling
1301
+
1302
+ ### Statistical Analysis
1303
+ 1. Hypothesis formulation
1304
+ 2. Statistical testing
1305
+ 3. Confidence intervals
1306
+ 4. Effect size calculations
1307
+
1308
+ ### Machine Learning (if applicable)
1309
+ 1. Feature selection and engineering
1310
+ 2. Model selection and training
1311
+ 3. Cross-validation and evaluation
1312
+ 4. Model interpretation and explainability
1313
+
1314
+ ## Deliverables
1315
+ ### Reports
1316
+ - Executive summary for stakeholders
1317
+ - Technical analysis report
1318
+ - Data quality report
1319
+ - Methodology documentation
1320
+
1321
+ ### Visualizations
1322
+ - Interactive dashboards
1323
+ - Static charts and graphs
1324
+ - Data story presentations
1325
+ - Key findings infographics
1326
+
1327
+ ### Code & Documentation
1328
+ - Reproducible analysis scripts
1329
+ - Data pipeline code
1330
+ - Documentation and comments
1331
+ - Testing and validation code
1332
+
1333
+ ## Timeline
1334
+ - Phase 1: Data collection and exploration (2 weeks)
1335
+ - Phase 2: Analysis and modeling (3 weeks)
1336
+ - Phase 3: Reporting and visualization (1 week)
1337
+ - Phase 4: Stakeholder presentation (1 week)
1338
+
1339
+ ## Risks & Assumptions
1340
+ - Data availability and quality risks
1341
+ - Technical complexity assumptions
1342
+ - Resource and timeline constraints
1343
+ - Stakeholder engagement assumptions
1344
+
1345
+ ## Success Metrics
1346
+ - Stakeholder satisfaction with insights
1347
+ - Accuracy of predictions (if applicable)
1348
+ - Business impact of recommendations
1349
+ - Reproducibility of results`
1350
+ }
1351
+ ];
1352
+
1353
+ res.json({
1354
+ templates,
1355
+ timestamp: new Date().toISOString()
1356
+ });
1357
+
1358
+ } catch (error) {
1359
+ console.error('PRD templates error:', error);
1360
+ res.status(500).json({
1361
+ error: 'Failed to get PRD templates',
1362
+ message: error.message
1363
+ });
1364
+ }
1365
+ });
1366
+
1367
+ /**
1368
+ * POST /api/taskmaster/apply-template/:projectName
1369
+ * Apply a PRD template to create a new PRD file
1370
+ */
1371
+ router.post('/apply-template/:projectName', async (req, res) => {
1372
+ try {
1373
+ const { projectName } = req.params;
1374
+ const { templateId, fileName = 'prd.txt', customizations = {} } = req.body;
1375
+
1376
+ if (!templateId) {
1377
+ return res.status(400).json({
1378
+ error: 'Missing required parameter',
1379
+ message: 'templateId is required'
1380
+ });
1381
+ }
1382
+
1383
+ // Get project path
1384
+ let projectPath;
1385
+ try {
1386
+ projectPath = await extractProjectDirectory(projectName);
1387
+ } catch (error) {
1388
+ return res.status(404).json({
1389
+ error: 'Project not found',
1390
+ message: `Project "${projectName}" does not exist`
1391
+ });
1392
+ }
1393
+
1394
+ // Get the template content (this would normally fetch from the templates list)
1395
+ const templates = await getAvailableTemplates();
1396
+ const template = templates.find(t => t.id === templateId);
1397
+
1398
+ if (!template) {
1399
+ return res.status(404).json({
1400
+ error: 'Template not found',
1401
+ message: `Template "${templateId}" does not exist`
1402
+ });
1403
+ }
1404
+
1405
+ // Apply customizations to template content
1406
+ let content = template.content;
1407
+
1408
+ // Replace placeholders with customizations
1409
+ for (const [key, value] of Object.entries(customizations)) {
1410
+ const placeholder = `[${key}]`;
1411
+ content = content.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), value);
1412
+ }
1413
+
1414
+ // Ensure .taskmaster/docs directory exists
1415
+ const docsDir = path.join(projectPath, '.taskmaster', 'docs');
1416
+ try {
1417
+ await fsPromises.mkdir(docsDir, { recursive: true });
1418
+ } catch (error) {
1419
+ console.error('Failed to create docs directory:', error);
1420
+ }
1421
+
1422
+ const filePath = path.join(docsDir, fileName);
1423
+
1424
+ // Write the template content to the file
1425
+ try {
1426
+ await fsPromises.writeFile(filePath, content, 'utf8');
1427
+
1428
+ res.json({
1429
+ projectName,
1430
+ projectPath,
1431
+ templateId,
1432
+ templateName: template.name,
1433
+ fileName,
1434
+ filePath: filePath,
1435
+ message: 'PRD template applied successfully',
1436
+ timestamp: new Date().toISOString()
1437
+ });
1438
+
1439
+ } catch (writeError) {
1440
+ console.error('Failed to write PRD template:', writeError);
1441
+ return res.status(500).json({
1442
+ error: 'Failed to write PRD template',
1443
+ message: writeError.message
1444
+ });
1445
+ }
1446
+
1447
+ } catch (error) {
1448
+ console.error('Apply template error:', error);
1449
+ res.status(500).json({
1450
+ error: 'Failed to apply PRD template',
1451
+ message: error.message
1452
+ });
1453
+ }
1454
+ });
1455
+
1456
+ // Helper function to get available templates
1457
+ async function getAvailableTemplates() {
1458
+ // This could be extended to read from files or database
1459
+ return [
1460
+ {
1461
+ id: 'web-app',
1462
+ name: 'Web Application',
1463
+ description: 'Template for web application projects',
1464
+ category: 'web',
1465
+ content: `# Product Requirements Document - Web Application
1466
+
1467
+ ## Overview
1468
+ **Product Name:** [Your App Name]
1469
+ **Version:** 1.0
1470
+ **Date:** ${new Date().toISOString().split('T')[0]}
1471
+ **Author:** [Your Name]
1472
+
1473
+ ## Executive Summary
1474
+ Brief description of what this web application will do and why it's needed.
1475
+
1476
+ ## User Stories
1477
+ 1. As a user, I want [feature] so I can [benefit]
1478
+ 2. As a user, I want [feature] so I can [benefit]
1479
+ 3. As a user, I want [feature] so I can [benefit]
1480
+
1481
+ ## Technical Requirements
1482
+ - Frontend framework
1483
+ - Backend services
1484
+ - Database requirements
1485
+ - Security considerations
1486
+
1487
+ ## Success Metrics
1488
+ - User engagement metrics
1489
+ - Performance benchmarks
1490
+ - Business objectives`
1491
+ },
1492
+ // Add other templates here if needed
1493
+ ];
1494
+ }
1495
+
1496
+ export default router;