@pixelbyte-software/pixcode 1.35.2 → 1.35.3

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 (173) 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-D1-AIL_5.js → index-D8z78r_D.js} +57 -57
  11. package/dist/assets/{index-B8w57E1r.css → index-DmchzORZ.css} +1 -1
  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/daemon/manager.js +33 -33
  36. package/dist-server/server/daemon-manager.js +64 -64
  37. package/dist-server/server/routes/commands.js +25 -25
  38. package/dist-server/server/routes/git.js +17 -17
  39. package/dist-server/server/routes/taskmaster.js +419 -419
  40. package/package.json +180 -180
  41. package/scripts/fix-node-pty.js +67 -67
  42. package/scripts/smoke/a2a-roundtrip.mjs +167 -167
  43. package/scripts/smoke/orchestration-api.mjs +172 -172
  44. package/scripts/smoke/orchestration-live-run.mjs +176 -176
  45. package/server/claude-sdk.js +898 -898
  46. package/server/cli.js +935 -935
  47. package/server/constants/config.js +4 -4
  48. package/server/cursor-cli.js +342 -342
  49. package/server/daemon/manager.js +564 -564
  50. package/server/daemon-manager.js +959 -959
  51. package/server/database/db.js +794 -794
  52. package/server/database/json-store.js +197 -197
  53. package/server/gemini-cli.js +535 -535
  54. package/server/gemini-response-handler.js +79 -79
  55. package/server/index.js +3135 -3135
  56. package/server/load-env.js +34 -34
  57. package/server/middleware/auth.js +173 -173
  58. package/server/modules/orchestration/a2a/adapter-registry.ts +108 -108
  59. package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +55 -55
  60. package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +284 -284
  61. package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -244
  62. package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -249
  63. package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -248
  64. package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -248
  65. package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -248
  66. package/server/modules/orchestration/a2a/routes.ts +577 -577
  67. package/server/modules/orchestration/a2a/task-store.ts +178 -178
  68. package/server/modules/orchestration/a2a/types.ts +125 -125
  69. package/server/modules/orchestration/a2a/validator.ts +113 -113
  70. package/server/modules/orchestration/index.ts +66 -66
  71. package/server/modules/orchestration/preview/port-watcher.ts +112 -112
  72. package/server/modules/orchestration/preview/preview-proxy.ts +60 -60
  73. package/server/modules/orchestration/preview/types.ts +19 -19
  74. package/server/modules/orchestration/tasks/orchestration-task-store.ts +45 -45
  75. package/server/modules/orchestration/tasks/orchestration-task.routes.ts +73 -73
  76. package/server/modules/orchestration/tasks/orchestration-task.service.ts +145 -145
  77. package/server/modules/orchestration/tasks/orchestration-task.types.ts +29 -29
  78. package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -127
  79. package/server/modules/orchestration/workflows/workflow-runner.ts +1206 -1206
  80. package/server/modules/orchestration/workflows/workflow-store.ts +97 -97
  81. package/server/modules/orchestration/workflows/workflow.routes.ts +169 -169
  82. package/server/modules/orchestration/workflows/workflow.types.ts +70 -70
  83. package/server/modules/orchestration/workflows/workspace-target.ts +120 -120
  84. package/server/modules/orchestration/workspace/docker-workspace.ts +135 -135
  85. package/server/modules/orchestration/workspace/path-safety.ts +55 -55
  86. package/server/modules/orchestration/workspace/types.ts +52 -52
  87. package/server/modules/orchestration/workspace/workspace-manager.ts +97 -97
  88. package/server/modules/orchestration/workspace/worktree-workspace.ts +125 -125
  89. package/server/modules/providers/index.ts +2 -2
  90. package/server/modules/providers/list/claude/claude-auth.provider.ts +145 -145
  91. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
  92. package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
  93. package/server/modules/providers/list/claude/claude.provider.ts +15 -15
  94. package/server/modules/providers/list/codex/codex-auth.provider.ts +115 -115
  95. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
  96. package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
  97. package/server/modules/providers/list/codex/codex.provider.ts +15 -15
  98. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
  99. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
  100. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
  101. package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
  102. package/server/modules/providers/list/gemini/gemini-auth.provider.ts +163 -163
  103. package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
  104. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
  105. package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
  106. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +130 -130
  107. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
  108. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +232 -232
  109. package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
  110. package/server/modules/providers/list/qwen/qwen-auth.provider.ts +145 -145
  111. package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
  112. package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
  113. package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
  114. package/server/modules/providers/provider.registry.ts +40 -40
  115. package/server/modules/providers/provider.routes.ts +819 -819
  116. package/server/modules/providers/services/mcp.service.ts +86 -86
  117. package/server/modules/providers/services/provider-auth.service.ts +26 -26
  118. package/server/modules/providers/services/sessions.service.ts +45 -45
  119. package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
  120. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
  121. package/server/modules/providers/shared/provider-configs.ts +142 -142
  122. package/server/modules/providers/tests/mcp.test.ts +293 -293
  123. package/server/openai-codex.js +462 -462
  124. package/server/opencode-cli.js +459 -459
  125. package/server/opencode-response-handler.js +107 -107
  126. package/server/projects.js +3105 -3105
  127. package/server/qwen-code-cli.js +395 -395
  128. package/server/qwen-response-handler.js +73 -73
  129. package/server/routes/agent.js +1365 -1365
  130. package/server/routes/auth.js +138 -138
  131. package/server/routes/codex.js +19 -19
  132. package/server/routes/commands.js +554 -554
  133. package/server/routes/cursor.js +52 -52
  134. package/server/routes/gemini.js +24 -24
  135. package/server/routes/git.js +1488 -1488
  136. package/server/routes/mcp-utils.js +31 -31
  137. package/server/routes/messages.js +61 -61
  138. package/server/routes/network.js +120 -120
  139. package/server/routes/plugins.js +318 -318
  140. package/server/routes/projects.js +915 -915
  141. package/server/routes/qwen.js +27 -27
  142. package/server/routes/settings.js +286 -286
  143. package/server/routes/taskmaster.js +1496 -1496
  144. package/server/routes/telegram.js +125 -125
  145. package/server/routes/user.js +123 -123
  146. package/server/services/external-access.js +171 -171
  147. package/server/services/install-jobs.js +571 -571
  148. package/server/services/notification-orchestrator.js +242 -242
  149. package/server/services/provider-credentials.js +189 -189
  150. package/server/services/provider-models.js +381 -381
  151. package/server/services/telegram/bot.js +279 -279
  152. package/server/services/telegram/telegram-http-client.js +130 -130
  153. package/server/services/telegram/translations.js +170 -170
  154. package/server/services/vapid-keys.js +36 -36
  155. package/server/sessionManager.js +225 -225
  156. package/server/shared/interfaces.ts +54 -54
  157. package/server/shared/types.ts +172 -172
  158. package/server/shared/utils.ts +193 -193
  159. package/server/tsconfig.json +36 -36
  160. package/server/utils/colors.js +21 -21
  161. package/server/utils/commandParser.js +303 -303
  162. package/server/utils/frontmatter.js +18 -18
  163. package/server/utils/gitConfig.js +34 -34
  164. package/server/utils/mcp-detector.js +147 -147
  165. package/server/utils/plugin-loader.js +457 -457
  166. package/server/utils/plugin-process-manager.js +184 -184
  167. package/server/utils/port-access.js +209 -209
  168. package/server/utils/runtime-paths.js +37 -37
  169. package/server/utils/taskmaster-websocket.js +128 -128
  170. package/server/utils/url-detection.js +71 -71
  171. package/server/vite-daemon.js +78 -78
  172. package/shared/modelConstants.js +162 -162
  173. package/shared/networkHosts.js +22 -22
@@ -1,1496 +1,1496 @@
1
- /**
2
- * TASKMASTER API ROUTES
3
- * ====================
4
- *
5
- * This module provides API endpoints for TaskMaster integration including:
6
- * - .taskmaster folder detection in project directories
7
- * - MCP server configuration detection
8
- * - TaskMaster state and metadata management
9
- */
10
-
11
- import express from 'express';
12
- import fs from 'fs';
13
- import path from 'path';
14
- import { promises as fsPromises } from 'fs';
15
- import { spawn } from 'child_process';
16
- import { extractProjectDirectory } from '../projects.js';
17
- import { detectTaskMasterMCPServer } from '../utils/mcp-detector.js';
18
- import { broadcastTaskMasterProjectUpdate, broadcastTaskMasterTasksUpdate } from '../utils/taskmaster-websocket.js';
19
- 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 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;