@pixelbyte-software/pixcode 1.35.2 → 1.35.4

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