roadmap-skill 0.2.8 → 0.2.10

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.
package/dist/index.js CHANGED
@@ -276,7 +276,7 @@ var ProjectStorage = class {
276
276
  if (filters.searchText && !task.title.toLowerCase().includes(filters.searchText.toLowerCase()) && !task.description.toLowerCase().includes(filters.searchText.toLowerCase())) {
277
277
  continue;
278
278
  }
279
- if (filters.includeCompleted === false && task.status === "done") {
279
+ if (filters.includeCompleted !== true && task.status === "done") {
280
280
  continue;
281
281
  }
282
282
  results.push({ task, project: data.project });
@@ -345,15 +345,38 @@ var storage = new ProjectStorage();
345
345
  // src/tools/project-tools.ts
346
346
  var ProjectTypeEnum = z.enum(["roadmap", "skill-tree", "kanban"]);
347
347
  var ProjectStatusEnum = z.enum(["active", "completed", "archived"]);
348
+ function toProjectSummary(project, taskCount, tags) {
349
+ return {
350
+ id: project.id,
351
+ name: project.name,
352
+ projectType: project.projectType,
353
+ status: project.status,
354
+ targetDate: project.targetDate,
355
+ taskCount,
356
+ ...tags ? { tags } : {}
357
+ };
358
+ }
359
+ function toTaskSummary(task) {
360
+ return {
361
+ id: task.id,
362
+ title: task.title,
363
+ status: task.status,
364
+ priority: task.priority,
365
+ dueDate: task.dueDate,
366
+ assignee: task.assignee,
367
+ tags: task.tags
368
+ };
369
+ }
348
370
  var createProjectTool = {
349
371
  name: "create_project",
350
- description: "Create a new project roadmap",
372
+ description: "Create a new project roadmap. Returns summary by default; set verbose=true for full data.",
351
373
  inputSchema: z.object({
352
374
  name: z.string().min(1, "Project name is required"),
353
375
  description: z.string(),
354
376
  projectType: ProjectTypeEnum,
355
377
  startDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format"),
356
- targetDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format")
378
+ targetDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format"),
379
+ verbose: z.boolean().optional()
357
380
  }),
358
381
  async execute(input) {
359
382
  try {
@@ -367,7 +390,7 @@ var createProjectTool = {
367
390
  const projectData = await storage.createProject(projectInput);
368
391
  return {
369
392
  success: true,
370
- data: projectData
393
+ data: input.verbose ? projectData : toProjectSummary(projectData.project, 0)
371
394
  };
372
395
  } catch (error) {
373
396
  return {
@@ -379,14 +402,33 @@ var createProjectTool = {
379
402
  };
380
403
  var listProjectsTool = {
381
404
  name: "list_projects",
382
- description: "List all projects with their task and milestone counts",
383
- inputSchema: z.object({}),
384
- async execute() {
405
+ description: "List all projects. Summary mode includes current project tags for Agent reuse. Set verbose=true for full project data.",
406
+ inputSchema: z.object({
407
+ verbose: z.boolean().optional()
408
+ }),
409
+ async execute(input) {
385
410
  try {
386
411
  const projects = await storage.listProjects();
412
+ if (input.verbose) {
413
+ return {
414
+ success: true,
415
+ data: projects
416
+ };
417
+ }
418
+ const summaries = await Promise.all(
419
+ projects.map(async (projectSummary) => {
420
+ const projectData = await storage.readProject(projectSummary.project.id);
421
+ const tags = (projectData?.tags ?? []).map((tag) => ({
422
+ id: tag.id,
423
+ name: tag.name,
424
+ color: tag.color
425
+ }));
426
+ return toProjectSummary(projectSummary.project, projectSummary.taskCount, tags);
427
+ })
428
+ );
387
429
  return {
388
430
  success: true,
389
- data: projects
431
+ data: summaries
390
432
  };
391
433
  } catch (error) {
392
434
  return {
@@ -398,9 +440,10 @@ var listProjectsTool = {
398
440
  };
399
441
  var getProjectTool = {
400
442
  name: "get_project",
401
- description: "Get a project by ID with all its data (tasks, tags, milestones)",
443
+ description: "Get a project by ID with all its data (tasks, tags, milestones). Tasks are returned as summaries by default; set verbose=true for full task data.",
402
444
  inputSchema: z.object({
403
- projectId: z.string().min(1, "Project ID is required")
445
+ projectId: z.string().min(1, "Project ID is required"),
446
+ verbose: z.boolean().optional()
404
447
  }),
405
448
  async execute(input) {
406
449
  try {
@@ -413,7 +456,10 @@ var getProjectTool = {
413
456
  }
414
457
  return {
415
458
  success: true,
416
- data: projectData
459
+ data: input.verbose ? projectData : {
460
+ ...projectData,
461
+ tasks: projectData.tasks.map(toTaskSummary)
462
+ }
417
463
  };
418
464
  } catch (error) {
419
465
  return {
@@ -425,7 +471,7 @@ var getProjectTool = {
425
471
  };
426
472
  var updateProjectTool = {
427
473
  name: "update_project",
428
- description: "Update an existing project",
474
+ description: "Update an existing project. Returns summary by default; set verbose=true for full data.",
429
475
  inputSchema: z.object({
430
476
  projectId: z.string().min(1, "Project ID is required"),
431
477
  name: z.string().min(1).optional(),
@@ -433,11 +479,12 @@ var updateProjectTool = {
433
479
  projectType: ProjectTypeEnum.optional(),
434
480
  status: ProjectStatusEnum.optional(),
435
481
  startDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
436
- targetDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
482
+ targetDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
483
+ verbose: z.boolean().optional()
437
484
  }),
438
485
  async execute(input) {
439
486
  try {
440
- const { projectId, ...updateData } = input;
487
+ const { projectId, verbose, ...updateData } = input;
441
488
  if (Object.keys(updateData).length === 0) {
442
489
  return {
443
490
  success: false,
@@ -454,7 +501,7 @@ var updateProjectTool = {
454
501
  }
455
502
  return {
456
503
  success: true,
457
- data: projectData
504
+ data: verbose ? projectData : toProjectSummary(projectData.project, projectData.tasks.length)
458
505
  };
459
506
  } catch (error) {
460
507
  return {
@@ -504,6 +551,39 @@ init_esm_shims();
504
551
  function generateTagId() {
505
552
  return `tag_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
506
553
  }
554
+ var HEX_COLOR_PATTERN = /^#[0-9A-Fa-f]{6}$/;
555
+ var TAG_COLOR_PALETTE = [
556
+ "#FF6B6B",
557
+ "#FF9F43",
558
+ "#FDCB6E",
559
+ "#6C5CE7",
560
+ "#74B9FF",
561
+ "#00B894",
562
+ "#00CEC9",
563
+ "#E17055",
564
+ "#FAB1A0",
565
+ "#55A3FF",
566
+ "#A29BFE",
567
+ "#FD79A8"
568
+ ];
569
+ function hashTagName(value) {
570
+ let hash = 5381;
571
+ for (const char of value.toLowerCase()) {
572
+ hash = hash * 33 ^ char.charCodeAt(0);
573
+ }
574
+ return Math.abs(hash >>> 0);
575
+ }
576
+ function resolveTagColor(tagName, inputColor) {
577
+ if (inputColor) {
578
+ return inputColor;
579
+ }
580
+ const normalizedTagName = tagName.trim();
581
+ if (normalizedTagName.length === 0) {
582
+ return TAG_COLOR_PALETTE[0];
583
+ }
584
+ const colorIndex = hashTagName(normalizedTagName) % TAG_COLOR_PALETTE.length;
585
+ return TAG_COLOR_PALETTE[colorIndex];
586
+ }
507
587
  var TagService = class {
508
588
  storage;
509
589
  constructor(storage2) {
@@ -535,11 +615,19 @@ var TagService = class {
535
615
  code: "DUPLICATE_ERROR"
536
616
  };
537
617
  }
618
+ const resolvedColor = resolveTagColor(data.name, data.color);
619
+ if (!HEX_COLOR_PATTERN.test(resolvedColor)) {
620
+ return {
621
+ success: false,
622
+ error: `Color must be a valid hex code (e.g., #FF5733), received '${resolvedColor}'`,
623
+ code: "VALIDATION_ERROR"
624
+ };
625
+ }
538
626
  const now = (/* @__PURE__ */ new Date()).toISOString();
539
627
  const tag = {
540
628
  id: generateTagId(),
541
629
  name: data.name,
542
- color: data.color,
630
+ color: resolvedColor,
543
631
  description: data.description || "",
544
632
  createdAt: now
545
633
  };
@@ -638,6 +726,13 @@ var TagService = class {
638
726
  };
639
727
  }
640
728
  }
729
+ if (data.color && !HEX_COLOR_PATTERN.test(data.color)) {
730
+ return {
731
+ success: false,
732
+ error: `Color must be a valid hex code (e.g., #FF5733), received '${data.color}'`,
733
+ code: "VALIDATION_ERROR"
734
+ };
735
+ }
641
736
  const now = (/* @__PURE__ */ new Date()).toISOString();
642
737
  const existingTag = projectData.tags[tagIndex];
643
738
  const updatedTag = {
@@ -789,6 +884,10 @@ function calculateCompletedAt(currentStatus, newStatus, existingCompletedAt, now
789
884
  }
790
885
  return existingCompletedAt;
791
886
  }
887
+ function findInvalidTagIds(projectData, tagIds) {
888
+ const validTagIds = new Set(projectData.tags.map((tag) => tag.id));
889
+ return tagIds.filter((tagId) => !validTagIds.has(tagId));
890
+ }
792
891
  var TaskService = {
793
892
  /**
794
893
  * Create a new task in a project
@@ -806,6 +905,15 @@ var TaskService = {
806
905
  code: "NOT_FOUND"
807
906
  };
808
907
  }
908
+ const incomingTagIds = data.tags ?? [];
909
+ const invalidTagIds = findInvalidTagIds(projectData, incomingTagIds);
910
+ if (invalidTagIds.length > 0) {
911
+ return {
912
+ success: false,
913
+ error: `Invalid tag IDs for project '${projectId}': ${invalidTagIds.join(", ")}`,
914
+ code: "VALIDATION_ERROR"
915
+ };
916
+ }
809
917
  const now = (/* @__PURE__ */ new Date()).toISOString();
810
918
  const task = {
811
919
  id: generateTaskId(),
@@ -814,7 +922,7 @@ var TaskService = {
814
922
  description: data.description,
815
923
  status: "todo",
816
924
  priority: data.priority ?? "medium",
817
- tags: data.tags ?? [],
925
+ tags: incomingTagIds,
818
926
  dueDate: data.dueDate ?? null,
819
927
  assignee: data.assignee ?? null,
820
928
  createdAt: now,
@@ -907,6 +1015,16 @@ var TaskService = {
907
1015
  code: "VALIDATION_ERROR"
908
1016
  };
909
1017
  }
1018
+ if (data.tags) {
1019
+ const invalidTagIds = findInvalidTagIds(projectData, data.tags);
1020
+ if (invalidTagIds.length > 0) {
1021
+ return {
1022
+ success: false,
1023
+ error: `Invalid tag IDs for project '${projectId}': ${invalidTagIds.join(", ")}`,
1024
+ code: "VALIDATION_ERROR"
1025
+ };
1026
+ }
1027
+ }
910
1028
  const now = (/* @__PURE__ */ new Date()).toISOString();
911
1029
  const existingTask = projectData.tasks[taskIndex];
912
1030
  const completedAt = calculateCompletedAt(
@@ -1038,9 +1156,19 @@ var TaskService = {
1038
1156
  continue;
1039
1157
  }
1040
1158
  const existingTask = projectData.tasks[taskIndex];
1041
- let updatedTags = existingTask.tags;
1042
- if (data.tags && data.tags.length > 0) {
1043
- const existingTags = existingTask.tags || [];
1159
+ let updatedTags = existingTask.tags ?? [];
1160
+ if (data.tags) {
1161
+ const invalidTagIds = findInvalidTagIds(projectData, data.tags);
1162
+ if (invalidTagIds.length > 0) {
1163
+ return {
1164
+ success: false,
1165
+ error: `Invalid tag IDs for project '${projectId}': ${invalidTagIds.join(", ")}`,
1166
+ code: "VALIDATION_ERROR"
1167
+ };
1168
+ }
1169
+ }
1170
+ if (data.tags) {
1171
+ const existingTags = existingTask.tags ?? [];
1044
1172
  switch (data.tagOperation) {
1045
1173
  case "add":
1046
1174
  updatedTags = [.../* @__PURE__ */ new Set([...existingTags, ...data.tags])];
@@ -1105,9 +1233,20 @@ init_esm_shims();
1105
1233
  // src/tools/task-tools.ts
1106
1234
  var TaskStatusEnum = z2.enum(["todo", "in-progress", "review", "done"]);
1107
1235
  var TaskPriorityEnum = z2.enum(["low", "medium", "high", "critical"]);
1236
+ function toTaskSummary2(task) {
1237
+ return {
1238
+ id: task.id,
1239
+ title: task.title,
1240
+ status: task.status,
1241
+ priority: task.priority,
1242
+ dueDate: task.dueDate,
1243
+ assignee: task.assignee,
1244
+ tags: task.tags
1245
+ };
1246
+ }
1108
1247
  var createTaskTool = {
1109
1248
  name: "create_task",
1110
- description: "Create a new task in a project",
1249
+ description: "Create a new task in a project. tags must be existing tag IDs from the same project. Returns summary by default; set verbose=true for full data.",
1111
1250
  inputSchema: z2.object({
1112
1251
  projectId: z2.string().min(1, "Project ID is required"),
1113
1252
  title: z2.string().min(1, "Task title is required"),
@@ -1115,7 +1254,8 @@ var createTaskTool = {
1115
1254
  priority: TaskPriorityEnum.default("medium"),
1116
1255
  tags: z2.array(z2.string()).default([]),
1117
1256
  dueDate: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
1118
- assignee: z2.string().optional()
1257
+ assignee: z2.string().optional(),
1258
+ verbose: z2.boolean().optional()
1119
1259
  }),
1120
1260
  async execute(input) {
1121
1261
  const result = await TaskService.create(input.projectId, {
@@ -1126,12 +1266,16 @@ var createTaskTool = {
1126
1266
  dueDate: input.dueDate,
1127
1267
  assignee: input.assignee
1128
1268
  });
1129
- return result;
1269
+ if (!result.success) return result;
1270
+ return {
1271
+ success: true,
1272
+ data: input.verbose ? result.data : toTaskSummary2(result.data)
1273
+ };
1130
1274
  }
1131
1275
  };
1132
1276
  var listTasksTool = {
1133
1277
  name: "list_tasks",
1134
- description: "List tasks with optional filters",
1278
+ description: "List tasks with optional filters. By default, completed (done) tasks are excluded. Set includeCompleted=true to include them. Returns summaries by default; set verbose=true for full task data.",
1135
1279
  inputSchema: z2.object({
1136
1280
  projectId: z2.string().optional(),
1137
1281
  status: TaskStatusEnum.optional(),
@@ -1140,7 +1284,8 @@ var listTasksTool = {
1140
1284
  assignee: z2.string().optional(),
1141
1285
  dueBefore: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
1142
1286
  dueAfter: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
1143
- includeCompleted: z2.boolean().optional()
1287
+ includeCompleted: z2.boolean().optional(),
1288
+ verbose: z2.boolean().optional()
1144
1289
  }),
1145
1290
  async execute(input) {
1146
1291
  try {
@@ -1154,9 +1299,10 @@ var listTasksTool = {
1154
1299
  dueAfter: input.dueAfter,
1155
1300
  includeCompleted: input.includeCompleted
1156
1301
  });
1302
+ const tasks = results.map((r) => r.task);
1157
1303
  return {
1158
1304
  success: true,
1159
- data: results
1305
+ data: input.verbose ? tasks : tasks.map(toTaskSummary2)
1160
1306
  };
1161
1307
  } catch (error) {
1162
1308
  return {
@@ -1180,7 +1326,7 @@ var getTaskTool = {
1180
1326
  };
1181
1327
  var updateTaskTool = {
1182
1328
  name: "update_task",
1183
- description: "Update an existing task",
1329
+ description: "Update an existing task. tags must be existing tag IDs from the same project. Returns summary by default; set verbose=true for full data.",
1184
1330
  inputSchema: z2.object({
1185
1331
  projectId: z2.string().min(1, "Project ID is required"),
1186
1332
  taskId: z2.string().min(1, "Task ID is required"),
@@ -1190,12 +1336,17 @@ var updateTaskTool = {
1190
1336
  priority: TaskPriorityEnum.optional(),
1191
1337
  tags: z2.array(z2.string()).optional(),
1192
1338
  dueDate: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional().nullable(),
1193
- assignee: z2.string().optional().nullable()
1339
+ assignee: z2.string().optional().nullable(),
1340
+ verbose: z2.boolean().optional()
1194
1341
  }),
1195
1342
  async execute(input) {
1196
- const { projectId, taskId, ...updateData } = input;
1343
+ const { projectId, taskId, verbose, ...updateData } = input;
1197
1344
  const result = await TaskService.update(projectId, taskId, updateData);
1198
- return result;
1345
+ if (!result.success) return result;
1346
+ return {
1347
+ success: true,
1348
+ data: verbose ? result.data : toTaskSummary2(result.data)
1349
+ };
1199
1350
  }
1200
1351
  };
1201
1352
  var deleteTaskTool = {
@@ -1218,22 +1369,31 @@ var deleteTaskTool = {
1218
1369
  };
1219
1370
  var batchUpdateTasksTool = {
1220
1371
  name: "batch_update_tasks",
1221
- description: "Update multiple tasks at once",
1372
+ description: "Update multiple tasks at once. tags must be existing tag IDs from the same project. Returns summaries by default; set verbose=true for full task data.",
1222
1373
  inputSchema: z2.object({
1223
1374
  projectId: z2.string().min(1, "Project ID is required"),
1224
1375
  taskIds: z2.array(z2.string()).min(1, "At least one task ID is required"),
1225
1376
  status: TaskStatusEnum.optional(),
1226
1377
  priority: TaskPriorityEnum.optional(),
1227
1378
  tags: z2.array(z2.string()).optional(),
1228
- tagOperation: z2.enum(["add", "remove", "replace"]).default("replace")
1379
+ tagOperation: z2.enum(["add", "remove", "replace"]).default("replace"),
1380
+ verbose: z2.boolean().optional()
1229
1381
  }),
1230
1382
  async execute(input) {
1231
- const { projectId, taskIds, tagOperation, ...restData } = input;
1383
+ const { projectId, taskIds, tagOperation, verbose, ...restData } = input;
1232
1384
  const result = await TaskService.batchUpdate(projectId, taskIds, {
1233
1385
  ...restData,
1234
1386
  tagOperation
1235
1387
  });
1236
- return result;
1388
+ if (!result.success) return result;
1389
+ return {
1390
+ success: true,
1391
+ data: {
1392
+ updatedTasks: verbose ? result.data.updatedTasks : result.data.updatedTasks.map(toTaskSummary2),
1393
+ updatedCount: result.data.updatedCount,
1394
+ notFoundIds: result.data.notFoundIds
1395
+ }
1396
+ };
1237
1397
  }
1238
1398
  };
1239
1399
 
@@ -1243,11 +1403,11 @@ import { z as z3 } from "zod";
1243
1403
  var tagService = new TagService(storage);
1244
1404
  var createTagTool = {
1245
1405
  name: "create_tag",
1246
- description: "Create a new tag in a project",
1406
+ description: "Create a new tag in a project. If color is omitted, it is generated deterministically from tag name.",
1247
1407
  inputSchema: z3.object({
1248
1408
  projectId: z3.string().min(1, "Project ID is required"),
1249
1409
  name: z3.string().min(1, "Tag name is required"),
1250
- color: z3.string().regex(/^#[0-9A-Fa-f]{6}$/, "Color must be a valid hex code (e.g., #FF5733)"),
1410
+ color: z3.string().regex(/^#[0-9A-Fa-f]{6}$/, "Color must be a valid hex code (e.g., #FF5733)").optional(),
1251
1411
  description: z3.string().default("")
1252
1412
  }),
1253
1413
  async execute(input) {
@@ -2085,12 +2245,12 @@ init_esm_shims();
2085
2245
  init_esm_shims();
2086
2246
  var projectPrompts = [
2087
2247
  {
2088
- name: "recommendNextTasks",
2248
+ name: "suggest-tasks",
2089
2249
  description: "Intelligently recommend the next priority tasks based on urgency, due dates, and project status",
2090
2250
  arguments: [
2091
2251
  {
2092
2252
  name: "projectId",
2093
- description: "Specific project ID (optional; if not provided, analyze all projects)",
2253
+ description: "Specific project ID (optional; if not provided, auto-detect from current context or analyze all projects)",
2094
2254
  required: false
2095
2255
  },
2096
2256
  {
@@ -2101,18 +2261,18 @@ var projectPrompts = [
2101
2261
  ]
2102
2262
  },
2103
2263
  {
2104
- name: "autoPrioritize",
2264
+ name: "auto-prioritize",
2105
2265
  description: "Automatically analyze tasks and intelligently adjust priorities, considering due dates, dependencies, and project importance",
2106
2266
  arguments: [
2107
2267
  {
2108
2268
  name: "projectId",
2109
- description: "Specific project ID (optional; if not provided, analyze all projects)",
2269
+ description: "Specific project ID (optional; if not provided, auto-detect from current context or analyze all projects)",
2110
2270
  required: false
2111
2271
  }
2112
2272
  ]
2113
2273
  },
2114
2274
  {
2115
- name: "enhanceTaskDetails",
2275
+ name: "add-task-details",
2116
2276
  description: "Intelligently enhance task details, including description, acceptance criteria, subtasks, and required resources",
2117
2277
  arguments: [
2118
2278
  {
@@ -2123,7 +2283,7 @@ var projectPrompts = [
2123
2283
  ]
2124
2284
  },
2125
2285
  {
2126
- name: "quickCapture",
2286
+ name: "quick-capture",
2127
2287
  description: "Quickly capture ideas/tasks, auto-categorize and suggest priorities",
2128
2288
  arguments: [
2129
2289
  {
@@ -2133,14 +2293,25 @@ var projectPrompts = [
2133
2293
  },
2134
2294
  {
2135
2295
  name: "projectId",
2136
- description: "Target project ID (optional)",
2296
+ description: "Target project ID (optional; if not provided, auto-detect from current context)",
2297
+ required: false
2298
+ }
2299
+ ]
2300
+ },
2301
+ {
2302
+ name: "open-web-ui",
2303
+ description: "Open the web visualization interface for the roadmap skill",
2304
+ arguments: [
2305
+ {
2306
+ name: "port",
2307
+ description: "Port to run the web interface on (optional, default: 7860)",
2137
2308
  required: false
2138
2309
  }
2139
2310
  ]
2140
2311
  }
2141
2312
  ];
2142
2313
  function getRecommendNextTasksPrompt(projectId, limit) {
2143
- const context = projectId ? `Analyze tasks for project ${projectId}` : "Analyze tasks for all active projects";
2314
+ const projectHint = projectId ? `User specified project: ${projectId}. Use this project if it exists, or inform user if not found.` : "User did not specify a project. Based on the current working directory and conversation context, try to identify the most relevant project. If a clear match exists, focus on that project; otherwise, analyze all active projects";
2144
2315
  const taskLimit = limit ? parseInt(limit, 10) : 3;
2145
2316
  return {
2146
2317
  description: "Intelligent Task Recommendation Assistant",
@@ -2149,7 +2320,7 @@ function getRecommendNextTasksPrompt(projectId, limit) {
2149
2320
  role: "user",
2150
2321
  content: {
2151
2322
  type: "text",
2152
- text: `${context}, please recommend the ${taskLimit} tasks I should prioritize next.
2323
+ text: `${projectHint}, please recommend the ${taskLimit} tasks I should prioritize next.
2153
2324
 
2154
2325
  ## Recommendation Logic (sorted by priority):
2155
2326
 
@@ -2209,7 +2380,7 @@ Keep task status synchronized with actual progress!`
2209
2380
  };
2210
2381
  }
2211
2382
  function getAutoPrioritizePrompt(projectId) {
2212
- const context = projectId ? `Analyze task priorities for project ${projectId}` : "Analyze task priorities for all projects";
2383
+ const projectHint = projectId ? `User specified project: ${projectId}. Use this project if it exists, or inform user if not found.` : "User did not specify a project. Based on the current working directory and conversation context, try to identify the most relevant project. If a clear match exists, focus on that project; otherwise, analyze all active projects";
2213
2384
  return {
2214
2385
  description: "Intelligent Priority Optimization Assistant",
2215
2386
  messages: [
@@ -2217,7 +2388,7 @@ function getAutoPrioritizePrompt(projectId) {
2217
2388
  role: "user",
2218
2389
  content: {
2219
2390
  type: "text",
2220
- text: `${context}, please automatically analyze and suggest priority adjustments.
2391
+ text: `${projectHint}, please automatically analyze and adjust priorities.
2221
2392
 
2222
2393
  ## Priority Adjustment Rules:
2223
2394
 
@@ -2251,7 +2422,7 @@ function getAutoPrioritizePrompt(projectId) {
2251
2422
  - Identify task dependency relationships
2252
2423
  - Evaluate overall project health
2253
2424
  3. **Generate adjustment suggestions**: List tasks needing priority changes with reasons
2254
- 4. **Batch update**: Use batch_update_tasks to execute priority adjustments
2425
+ 4. **Batch update**: Use batch_update_tasks to execute priority adjustments immediately \u2014 no confirmation needed
2255
2426
 
2256
2427
  ## Output Format:
2257
2428
 
@@ -2273,7 +2444,7 @@ function getAutoPrioritizePrompt(projectId) {
2273
2444
  ### Keep Unchanged (Priorities are reasonable)
2274
2445
  - List tasks with reasonable priority settings
2275
2446
 
2276
- Please provide analysis results, then execute batch update after user confirmation.`
2447
+ Please provide analysis results and immediately execute batch_update_tasks to apply the priority adjustments \u2014 no confirmation needed.`
2277
2448
  }
2278
2449
  }
2279
2450
  ]
@@ -2328,7 +2499,7 @@ If the task is complex, suggest breaking it down:
2328
2499
  - If design task: Add design specs, review criteria
2329
2500
  - If documentation task: Add doc structure, references
2330
2501
  - If testing task: Add test scenarios, coverage scope
2331
- 4. **Generate enhancement content**: Use update_task to update task description
2502
+ 4. **Apply enhancement**: Use update_task to update task description immediately \u2014 no confirmation needed
2332
2503
 
2333
2504
  ## Updated task should include:
2334
2505
 
@@ -2351,14 +2522,14 @@ If the task is complex, suggest breaking it down:
2351
2522
  - References: [link]
2352
2523
  \`\`\`
2353
2524
 
2354
- Please fetch task info first, then provide detailed enhancement suggestions.`
2525
+ Please fetch task info and immediately use update_task to apply the enhanced details \u2014 no confirmation needed.`
2355
2526
  }
2356
2527
  }
2357
2528
  ]
2358
2529
  };
2359
2530
  }
2360
2531
  function getQuickCapturePrompt(idea, projectId) {
2361
- const projectContext = projectId ? `Add to project ${projectId}` : "Auto-select the most suitable project";
2532
+ const projectContext = projectId ? `User specified project: ${projectId}. Use this project if it exists, or inform user if not found.` : "User did not specify a project. Based on the current working directory and conversation context, try to identify the most relevant project. If a clear match exists, use that project; otherwise, analyze all active projects and select the best match";
2362
2533
  return {
2363
2534
  description: "Quick Capture Assistant",
2364
2535
  messages: [
@@ -2370,7 +2541,7 @@ function getQuickCapturePrompt(idea, projectId) {
2370
2541
 
2371
2542
  ${projectContext}
2372
2543
 
2373
- ## Please help me complete the following steps:
2544
+ ## Please complete the following steps immediately:
2374
2545
 
2375
2546
  ### 1. Task Information Extraction
2376
2547
  Extract from description:
@@ -2379,11 +2550,10 @@ Extract from description:
2379
2550
  - **Task Type**: bug / feature / refactor / docs / chore
2380
2551
  - **Estimated Priority**: critical / high / medium / low (based on urgency in description)
2381
2552
 
2382
- ### 2. Project Recommendation (if no project specified)
2383
- If user didn't specify a project, please:
2553
+ ### 2. Project Selection (if no project specified)
2384
2554
  - List all active projects
2385
2555
  - Analyze which project the task content is most relevant to
2386
- - Recommend the most suitable project
2556
+ - Select the most suitable project automatically
2387
2557
 
2388
2558
  ### 3. Tag Suggestions
2389
2559
  Suggest relevant tags:
@@ -2391,11 +2561,21 @@ Suggest relevant tags:
2391
2561
  - Priority tags: urgent, important
2392
2562
  - Domain tags: frontend, backend, design, testing (if applicable)
2393
2563
 
2394
- ### 4. Generate Task
2395
- Use create_task to create the task
2564
+ Tag consistency rules:
2565
+ - list_tags first, then prefer reusing existing tags in that project
2566
+ - If no suitable tag exists, create_tag first (color optional, system can auto-generate) and then use the returned tag ID
2567
+ - create_task.tags must contain tag IDs only (not tag names)
2396
2568
 
2397
- ### 5. Status Recommendation
2398
- After creating the task, if you start working on it immediately, consider setting the status to in-progress. Use update_task to keep progress updated during work, and mark as done when completed.
2569
+ ### 4. Create Task
2570
+ Use create_task to create the task immediately \u2014 no confirmation needed.
2571
+ Before create_task:
2572
+ 1. Call list_tags(projectId)
2573
+ 2. Match suggested tags to existing tags by name (case-insensitive)
2574
+ 3. For missing tags, call create_tag(projectId, name, color?)
2575
+ 4. Build create_task.tags from tag IDs only
2576
+
2577
+ ### 5. Status
2578
+ After creating, if work starts immediately, use update_task to set status to in-progress.
2399
2579
 
2400
2580
  ## Example:
2401
2581
 
@@ -2407,13 +2587,29 @@ After creating the task, if you start working on it immediately, consider settin
2407
2587
  - Type: Bug
2408
2588
  - Priority: High (affects user experience)
2409
2589
  - Suggested Tags: bug, frontend, mobile
2590
+ - create_task.tags: [existing_or_new_tag_ids]
2410
2591
  - Recommended Project: [Recommend if there's a web project]
2411
2592
 
2412
- ## Current Idea Analysis:
2593
+ ## Current Idea:
2413
2594
 
2414
2595
  Idea: "${idea}"
2415
2596
 
2416
- Please analyze and generate task suggestions. After user confirmation, execute create_task to create the task.`
2597
+ Analyze the idea, select the best matching project, and immediately execute create_task \u2014 no confirmation needed.`
2598
+ }
2599
+ }
2600
+ ]
2601
+ };
2602
+ }
2603
+ function getOpenWebUIPrompt(port) {
2604
+ const portNum = port ? parseInt(port, 10) : 7860;
2605
+ return {
2606
+ description: "Open Web Visualization Interface",
2607
+ messages: [
2608
+ {
2609
+ role: "user",
2610
+ content: {
2611
+ type: "text",
2612
+ text: `Please open the roadmap-skill web interface by calling the open_web_interface tool with port ${portNum}. Do it immediately without asking for confirmation.`
2417
2613
  }
2418
2614
  }
2419
2615
  ]
@@ -2421,14 +2617,16 @@ Please analyze and generate task suggestions. After user confirmation, execute c
2421
2617
  }
2422
2618
  function getPromptByName(name, args) {
2423
2619
  switch (name) {
2424
- case "recommendNextTasks":
2620
+ case "suggest-tasks":
2425
2621
  return getRecommendNextTasksPrompt(args?.projectId, args?.limit);
2426
- case "autoPrioritize":
2622
+ case "auto-prioritize":
2427
2623
  return getAutoPrioritizePrompt(args?.projectId);
2428
- case "enhanceTaskDetails":
2624
+ case "add-task-details":
2429
2625
  return getEnhanceTaskDetailsPrompt(args?.taskId || "");
2430
- case "quickCapture":
2626
+ case "quick-capture":
2431
2627
  return getQuickCapturePrompt(args?.idea || "", args?.projectId);
2628
+ case "open-web-ui":
2629
+ return getOpenWebUIPrompt(args?.port);
2432
2630
  default:
2433
2631
  return null;
2434
2632
  }