@specforge/mcp 3.3.8 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/cli/commands/set-status.js +1 -1
  2. package/dist/cli/commands/set-status.js.map +1 -1
  3. package/dist/cli/commands/specs.types.d.ts +1 -1
  4. package/dist/cli/commands/specs.types.d.ts.map +1 -1
  5. package/dist/cli/commands/specs.types.js +6 -0
  6. package/dist/cli/commands/specs.types.js.map +1 -1
  7. package/dist/lib/format.d.ts +0 -32
  8. package/dist/lib/format.d.ts.map +1 -1
  9. package/dist/lib/format.js +0 -40
  10. package/dist/lib/format.js.map +1 -1
  11. package/dist/lib/index.d.ts +1 -1
  12. package/dist/lib/index.d.ts.map +1 -1
  13. package/dist/lib/index.js +1 -1
  14. package/dist/lib/index.js.map +1 -1
  15. package/dist/server.d.ts.map +1 -1
  16. package/dist/server.js +6 -17
  17. package/dist/server.js.map +1 -1
  18. package/dist/tools/core/blueprint.d.ts.map +1 -1
  19. package/dist/tools/core/blueprint.js +4 -34
  20. package/dist/tools/core/blueprint.js.map +1 -1
  21. package/dist/tools/core/dependency.d.ts.map +1 -1
  22. package/dist/tools/core/dependency.js +0 -2
  23. package/dist/tools/core/dependency.js.map +1 -1
  24. package/dist/tools/core/epic.d.ts.map +1 -1
  25. package/dist/tools/core/epic.js +0 -2
  26. package/dist/tools/core/epic.js.map +1 -1
  27. package/dist/tools/core/lookup.d.ts.map +1 -1
  28. package/dist/tools/core/lookup.js +0 -6
  29. package/dist/tools/core/lookup.js.map +1 -1
  30. package/dist/tools/core/pattern.d.ts.map +1 -1
  31. package/dist/tools/core/pattern.js +0 -2
  32. package/dist/tools/core/pattern.js.map +1 -1
  33. package/dist/tools/core/project.d.ts.map +1 -1
  34. package/dist/tools/core/project.js +0 -2
  35. package/dist/tools/core/project.js.map +1 -1
  36. package/dist/tools/core/session.d.ts.map +1 -1
  37. package/dist/tools/core/session.js +0 -3
  38. package/dist/tools/core/session.js.map +1 -1
  39. package/dist/tools/core/specification.d.ts.map +1 -1
  40. package/dist/tools/core/specification.js +0 -1
  41. package/dist/tools/core/specification.js.map +1 -1
  42. package/dist/tools/core/ticket.d.ts.map +1 -1
  43. package/dist/tools/core/ticket.js +24 -1
  44. package/dist/tools/core/ticket.js.map +1 -1
  45. package/dist/tools/core/types.d.ts +0 -1
  46. package/dist/tools/core/types.d.ts.map +1 -1
  47. package/dist/tools/core/workflow-guide.d.ts.map +1 -1
  48. package/dist/tools/core/workflow-guide.js +3 -1
  49. package/dist/tools/core/workflow-guide.js.map +1 -1
  50. package/dist/tools/core/workflow.d.ts.map +1 -1
  51. package/dist/tools/core/workflow.js +0 -2
  52. package/dist/tools/core/workflow.js.map +1 -1
  53. package/dist/tools/index.d.ts +8 -0
  54. package/dist/tools/index.d.ts.map +1 -1
  55. package/dist/tools/index.js +212 -1423
  56. package/dist/tools/index.js.map +1 -1
  57. package/dist/types/index.d.ts +1 -1
  58. package/dist/types/index.d.ts.map +1 -1
  59. package/dist/types/index.js.map +1 -1
  60. package/package.json +1 -1
@@ -14,7 +14,7 @@
14
14
  * - Search: Search, find by file/tag, find related
15
15
  * - Git: Link commits and PRs, get linked items
16
16
  */
17
- import { ValidationError, ApiError, validateToolArgs, formatMCPError, transformError, validateTicket, filterWarningsByStrictness, } from '../validation/index.js';
17
+ import { ValidationError, ApiError, validateToolArgs, formatMCPError, transformError, } from '../validation/index.js';
18
18
  import { resolvePatternsWithCache, getPatternOverrides, flattenCodeStandards, } from '../patterns/index.js';
19
19
  import { getResponseModeFromArgs, formatWriteResponse, } from '../lib/response.js';
20
20
  import { createFeedbackHandler } from './core/feedback.js';
@@ -33,75 +33,6 @@ import { findProjectRoot } from '../cli/config/paths.js';
33
33
  *
34
34
  * @returns Array of tool definitions
35
35
  */
36
- /**
37
- * Format parameter definition for read operations
38
- * Allows AI agents to request JSON or TOON-formatted responses
39
- */
40
- const FORMAT_PARAMETER = {
41
- type: 'string',
42
- enum: ['json', 'toon'],
43
- description: 'Output format. TOON (default) provides ~44% token reduction. Use "json" for structured data processing.',
44
- default: 'toon',
45
- };
46
- /**
47
- * List of read operation tool names that support the format parameter
48
- * Write operations (create_*, update_*, report_*, etc.) are excluded
49
- */
50
- const READ_TOOL_NAMES = new Set([
51
- // Project operations
52
- 'list_projects',
53
- 'get_project',
54
- 'lookup_project',
55
- // Specification operations
56
- 'list_specifications',
57
- 'get_specification',
58
- 'lookup_specification',
59
- // Blueprint operations
60
- 'blueprint',
61
- // Epic operations
62
- 'list_epics',
63
- 'get_epic',
64
- 'lookup_epic',
65
- // Ticket operations
66
- 'list_tickets',
67
- 'get_ticket',
68
- 'lookup_ticket',
69
- 'lookup_tickets_by_status',
70
- // Dependency operations
71
- 'get_dependency_tree',
72
- 'check_circular_dependencies',
73
- // Context operations
74
- 'get_implementation_context',
75
- 'get_next_actionable_tickets',
76
- 'get_blocked_tickets',
77
- 'get_critical_path',
78
- 'get_patterns',
79
- // Status & Analytics
80
- 'get_report',
81
- // Search operations
82
- 'search_tickets',
83
- // Agent Teams (read operations)
84
- 'get_epic_dependency_graph',
85
- 'get_implementation_plan',
86
- // Review operations
87
- 'review_planning',
88
- 'review_implementation',
89
- ]);
90
- /**
91
- * Add format parameter to a tool's input schema
92
- */
93
- function addFormatParameter(tool) {
94
- return {
95
- ...tool,
96
- inputSchema: {
97
- ...tool.inputSchema,
98
- properties: {
99
- ...tool.inputSchema.properties,
100
- format: FORMAT_PARAMETER,
101
- },
102
- },
103
- };
104
- }
105
36
  export function getTools() {
106
37
  const tools = [
107
38
  // ========================================================================
@@ -140,11 +71,6 @@ export function getTools() {
140
71
  type: 'string',
141
72
  description: 'Project name to search for (partial match, case-insensitive)',
142
73
  },
143
- format: {
144
- type: 'string',
145
- enum: ['json', 'toon'],
146
- description: 'Output format (default: json)',
147
- },
148
74
  },
149
75
  required: ['name'],
150
76
  },
@@ -214,40 +140,6 @@ export function getTools() {
214
140
  required: ['projectId'],
215
141
  },
216
142
  },
217
- {
218
- name: 'get_specification',
219
- description: `Get specification with optional summary mode or full details.
220
-
221
- Use summary: true for minimal response (~70 tokens) with key fields only (id, title, status, priority, epicCount, ticketCount, completedTicketCount).
222
-
223
- Optional includes (ignored when summary=true):
224
- - 'status': Progress, ticket counts, blockers (replaces get_specification_status)
225
- - 'epics': List of epics with summary data
226
- - 'patterns': Tech stack, code patterns, naming conventions`,
227
- inputSchema: {
228
- type: 'object',
229
- properties: {
230
- specificationId: {
231
- type: 'string',
232
- description: 'The ID of the specification to retrieve',
233
- },
234
- summary: {
235
- type: 'boolean',
236
- description: 'Return minimal summary fields only (~70 tokens vs ~600 full). Ignores include parameter when true. Default: false',
237
- default: false,
238
- },
239
- include: {
240
- type: 'array',
241
- items: {
242
- type: 'string',
243
- enum: ['status', 'epics', 'patterns'],
244
- },
245
- description: 'Optional data to include in response (ignored when summary=true)',
246
- },
247
- },
248
- required: ['specificationId'],
249
- },
250
- },
251
143
  {
252
144
  name: 'lookup_specification',
253
145
  description: 'Fast specification lookup by title. Returns minimal data (id, title, status, epicCount, ticketCount) for token efficiency.',
@@ -262,11 +154,6 @@ Optional includes (ignored when summary=true):
262
154
  type: 'string',
263
155
  description: 'Specification title to search for (partial match, case-insensitive)',
264
156
  },
265
- format: {
266
- type: 'string',
267
- enum: ['json', 'toon'],
268
- description: 'Output format (default: json)',
269
- },
270
157
  },
271
158
  required: ['projectId', 'title'],
272
159
  },
@@ -276,7 +163,7 @@ Optional includes (ignored when summary=true):
276
163
  // ========================================================================
277
164
  {
278
165
  name: 'list_epics',
279
- description: 'List epics for a specification with optional status and field filters. Supports pagination with limit/offset. Use fields to select specific fields and reduce token usage.',
166
+ description: 'List epics for a specification with optional status and field filters. Supports pagination with limit/offset. Use fields to select specific fields and reduce token usage. During active planning sessions, field selection and result limits are automatically enforced.',
280
167
  inputSchema: {
281
168
  type: 'object',
282
169
  properties: {
@@ -330,39 +217,6 @@ Optional includes (ignored when summary=true):
330
217
  required: ['specificationId'],
331
218
  },
332
219
  },
333
- {
334
- name: 'get_epic',
335
- description: `Get epic with optional summary mode or full details.
336
-
337
- Use summary: true for minimal response (~80 tokens) with key fields only (id, epicNumber, title, status, objective, ticketCount, completedTicketCount).
338
-
339
- Optional includes (ignored when summary=true):
340
- - 'status': Progress percentage, ticket counts, active tickets (replaces get_epic_status)
341
- - 'tickets': List of tickets with summary data`,
342
- inputSchema: {
343
- type: 'object',
344
- properties: {
345
- epicId: {
346
- type: 'string',
347
- description: 'The ID of the epic to retrieve',
348
- },
349
- summary: {
350
- type: 'boolean',
351
- description: 'Return minimal summary fields only (~80 tokens vs ~400 full). Ignores include parameter when true. Default: false',
352
- default: false,
353
- },
354
- include: {
355
- type: 'array',
356
- items: {
357
- type: 'string',
358
- enum: ['status', 'tickets'],
359
- },
360
- description: 'Optional data to include in response (ignored when summary=true)',
361
- },
362
- },
363
- required: ['epicId'],
364
- },
365
- },
366
220
  {
367
221
  name: 'lookup_epic',
368
222
  description: "Fast epic lookup by number or title. Returns minimal data (id, number, title, status, ticketCount). Use 'number' for exact match, 'title' for partial match.",
@@ -381,11 +235,6 @@ Optional includes (ignored when summary=true):
381
235
  type: 'string',
382
236
  description: 'Epic title for partial match lookup',
383
237
  },
384
- format: {
385
- type: 'string',
386
- enum: ['json', 'toon'],
387
- description: 'Output format (default: json)',
388
- },
389
238
  },
390
239
  required: ['specificationId'],
391
240
  },
@@ -395,7 +244,7 @@ Optional includes (ignored when summary=true):
395
244
  // ========================================================================
396
245
  {
397
246
  name: 'list_tickets',
398
- description: 'List tickets for an epic with optional status and field filters. Supports pagination with limit/offset. Use fields to select specific fields and reduce token usage. Use include: ["statusReason"] to get reasons why pending tickets are blocked.',
247
+ description: 'List tickets for an epic with optional status and field filters. Supports pagination with limit/offset. Use fields to select specific fields and reduce token usage. Use include: ["statusReason"] to get reasons why pending tickets are blocked. During active planning sessions, field selection and result limits are automatically enforced.',
399
248
  inputSchema: {
400
249
  type: 'object',
401
250
  properties: {
@@ -466,44 +315,6 @@ Optional includes (ignored when summary=true):
466
315
  required: ['epicId'],
467
316
  },
468
317
  },
469
- {
470
- name: 'get_ticket',
471
- description: `Get ticket with optional summary mode or full details.
472
-
473
- Use summary: true for minimal response (~100 tokens) with key fields only (id, ticketNumber, title, status, complexity, estimatedHours, priority).
474
-
475
- For full details, statusReason is auto-included for pending tickets explaining why the ticket is blocked.
476
-
477
- Optional includes (ignored when summary=true):
478
- - 'dependencies': Tickets this blocks and is blocked by (replaces get_ticket_dependencies)
479
- - 'testStatus': Test results and history (replaces get_ticket_test_status)
480
- - 'commits': Linked git commits (replaces get_ticket_commits)
481
- - 'prs': Linked pull requests (replaces get_ticket_prs)
482
- - 'statusReason': Why ticket is pending (auto-included for pending tickets)`,
483
- inputSchema: {
484
- type: 'object',
485
- properties: {
486
- ticketId: {
487
- type: 'string',
488
- description: 'The ID of the ticket to retrieve',
489
- },
490
- summary: {
491
- type: 'boolean',
492
- description: 'Return minimal summary fields only (~100 tokens vs ~500 full). Ignores include parameter when true. Default: false',
493
- default: false,
494
- },
495
- include: {
496
- type: 'array',
497
- items: {
498
- type: 'string',
499
- enum: ['dependencies', 'testStatus', 'commits', 'prs', 'statusReason'],
500
- },
501
- description: 'Additional data to include (ignored when summary=true). statusReason is auto-included for pending tickets.',
502
- },
503
- },
504
- required: ['ticketId'],
505
- },
506
- },
507
318
  {
508
319
  name: 'lookup_ticket',
509
320
  description: "Fast ticket lookup by number or title. Returns minimal data (id, number, title, status, complexity). Use 'number' for exact match, 'title' for partial match.",
@@ -522,11 +333,6 @@ Optional includes (ignored when summary=true):
522
333
  type: 'string',
523
334
  description: 'Ticket title for partial match lookup',
524
335
  },
525
- format: {
526
- type: 'string',
527
- enum: ['json', 'toon'],
528
- description: 'Output format (default: json)',
529
- },
530
336
  },
531
337
  required: ['epicId'],
532
338
  },
@@ -548,90 +354,6 @@ Optional includes (ignored when summary=true):
548
354
  },
549
355
  },
550
356
  // ========================================================================
551
- // Core Operations - Dependencies (Epic 3)
552
- // ========================================================================
553
- {
554
- name: 'add_dependency',
555
- description: 'Add a dependency between two tickets. The first ticket will depend on the second.',
556
- inputSchema: {
557
- type: 'object',
558
- properties: {
559
- ticketId: {
560
- type: 'string',
561
- description: 'The ID of the ticket that will depend on another',
562
- },
563
- dependsOnId: {
564
- type: 'string',
565
- description: 'The ID of the ticket it will depend on',
566
- },
567
- type: {
568
- type: 'string',
569
- enum: ['blocks', 'requires'],
570
- description: "Type of dependency (default: 'requires')",
571
- },
572
- },
573
- required: ['ticketId', 'dependsOnId'],
574
- },
575
- },
576
- {
577
- name: 'remove_dependency',
578
- description: 'Remove a dependency between two tickets',
579
- inputSchema: {
580
- type: 'object',
581
- properties: {
582
- ticketId: {
583
- type: 'string',
584
- description: 'The ID of the dependent ticket',
585
- },
586
- dependsOnId: {
587
- type: 'string',
588
- description: 'The ID of the ticket it depends on',
589
- },
590
- dependencyId: {
591
- type: 'string',
592
- description: 'Alternative: Direct ID of the dependency record',
593
- },
594
- },
595
- },
596
- },
597
- {
598
- name: 'get_dependency_tree',
599
- description: 'Get the full dependency tree for a specification, showing all tickets and their dependency relationships',
600
- inputSchema: {
601
- type: 'object',
602
- properties: {
603
- specificationId: {
604
- type: 'string',
605
- description: 'The ID of the specification',
606
- },
607
- },
608
- required: ['specificationId'],
609
- },
610
- },
611
- {
612
- name: 'check_circular_dependencies',
613
- description: `Check for circular dependencies between tickets in a specification.
614
-
615
- Returns any cycles found where tickets depend on each other in a loop (e.g., A→B→C→A).
616
-
617
- Examples:
618
- - check_circular_dependencies specificationId="spec-123"
619
- - check_circular_dependencies projectId="proj-123" // Check all specs in project`,
620
- inputSchema: {
621
- type: 'object',
622
- properties: {
623
- specificationId: {
624
- type: 'string',
625
- description: 'Specification ID to check (optional if projectId provided)',
626
- },
627
- projectId: {
628
- type: 'string',
629
- description: 'Project ID to check all specifications (optional if specificationId provided)',
630
- },
631
- },
632
- },
633
- },
634
- // ========================================================================
635
357
  // Context & AI Tools (Epic 4)
636
358
  // ========================================================================
637
359
  {
@@ -689,20 +411,6 @@ Examples:
689
411
  required: ['specificationId'],
690
412
  },
691
413
  },
692
- {
693
- name: 'get_critical_path',
694
- description: 'Get the critical path (longest dependency chain) for a specification',
695
- inputSchema: {
696
- type: 'object',
697
- properties: {
698
- specificationId: {
699
- type: 'string',
700
- description: 'The ID of the specification',
701
- },
702
- },
703
- required: ['specificationId'],
704
- },
705
- },
706
414
  {
707
415
  name: 'get_patterns',
708
416
  description: 'Get patterns for a specification or ticket with full inheritance chain. When ticketId is provided, returns resolved patterns with spec → epic → ticket inheritance.',
@@ -725,7 +433,7 @@ Examples:
725
433
  // ========================================================================
726
434
  {
727
435
  name: 'start_work_session',
728
- description: 'Start working on a ticket. Creates a WorkSession record and transitions ready -> active. Returns the workSessionId along with error with statusReason if ticket is pending (dependencies not met).',
436
+ description: 'Start working on a ticket. Returns full ticket details (description, implementation steps, AC, technicalDetails, codeReferences, typeReferences, tags, notes, complexity, priority) alongside checklistState and workSessionId. No need to call get_ticket separately. Returns error with statusReason if ticket is pending.',
729
437
  inputSchema: {
730
438
  type: 'object',
731
439
  properties: {
@@ -852,7 +560,9 @@ Use this instead of calling update_ticket for checklist changes. Provides:
852
560
  - Auto-calculated progress percentage
853
561
  - Completion readiness hints
854
562
 
855
- IMPORTANT: All acceptance criteria must be validated and all implementation steps must be completed via this tool before calling complete_work_session. The completion gate enforces this.`,
563
+ IMPORTANT: All acceptance criteria must be validated and all implementation steps must be completed via this tool before calling complete_work_session. The completion gate enforces this.
564
+
565
+ Set getTicket: true to fetch full ticket details in the response — useful for re-reading ticket context mid-implementation. Can be the sole operation or combined with other actions.`,
856
566
  inputSchema: {
857
567
  type: 'object',
858
568
  properties: {
@@ -977,6 +687,10 @@ IMPORTANT: All acceptance criteria must be validated and all implementation step
977
687
  type: 'boolean',
978
688
  description: 'Clear existing blocker and resume work.',
979
689
  },
690
+ getTicket: {
691
+ type: 'boolean',
692
+ description: 'Fetch full ticket details. Can be the sole operation or combined with other actions.',
693
+ },
980
694
  },
981
695
  required: ['ticketId'],
982
696
  },
@@ -1014,11 +728,6 @@ Format options:
1014
728
  type: 'string',
1015
729
  description: 'ID of the scoped entity (projectId, specificationId, or epicId)',
1016
730
  },
1017
- format: {
1018
- type: 'string',
1019
- enum: ['json', 'toon', 'summary'],
1020
- description: 'Output format: json (full structured), toon (~44% smaller), summary (key metrics only ~70% smaller). Default: json',
1021
- },
1022
731
  startDate: {
1023
732
  type: 'string',
1024
733
  description: 'Start date for work report (ISO 8601)',
@@ -1046,7 +755,7 @@ Combines:
1046
755
  - Status, complexity, priority filters
1047
756
 
1048
757
  At least one of: query, files, tags, or relatedTo is required.
1049
- At least one scope filter (projectId, specificationId, or epicId) is required.`,
758
+ At least one scope filter (projectId, specificationId, or epicId) is required. During active planning sessions, prefer lookup_ticket for targeted lookups.`,
1050
759
  inputSchema: {
1051
760
  type: 'object',
1052
761
  properties: {
@@ -1223,7 +932,7 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
1223
932
  // ========================================================================
1224
933
  {
1225
934
  name: 'create_specification',
1226
- description: 'Create a new specification with full context. Create epics separately using epic.create for better quality.',
935
+ description: 'Create a new specification with full context. Create epics separately using epic.create for better quality. After creation, use start_planning_session to begin structured planning.',
1227
936
  inputSchema: {
1228
937
  type: 'object',
1229
938
  properties: {
@@ -1387,766 +1096,107 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
1387
1096
  },
1388
1097
  },
1389
1098
  {
1390
- name: 'create_epic',
1391
- description: 'Create a new epic in a specification with full context. Create tickets separately using ticket.create for better quality.',
1099
+ name: 'import_specification',
1100
+ description: 'Import a markdown file as a complete specification with AI-powered parsing. Parses epics from ## headers and tickets from ### headers.',
1392
1101
  inputSchema: {
1393
1102
  type: 'object',
1394
1103
  properties: {
1395
- specificationId: {
1104
+ projectId: {
1396
1105
  type: 'string',
1397
- description: 'The ID of the specification',
1106
+ description: 'The ID of the project to import into',
1107
+ },
1108
+ content: {
1109
+ type: 'string',
1110
+ description: 'Raw markdown content to parse and import',
1398
1111
  },
1399
1112
  title: {
1400
1113
  type: 'string',
1401
- description: 'Epic title',
1114
+ description: 'Override the parsed title (optional)',
1402
1115
  },
1403
- description: {
1116
+ specificationTypeId: {
1404
1117
  type: 'string',
1405
- description: 'Detailed description',
1118
+ description: 'Specification type ID (uses default if not provided)',
1406
1119
  },
1407
- objective: {
1120
+ },
1121
+ required: ['projectId', 'content'],
1122
+ },
1123
+ },
1124
+ // ========================================================================
1125
+ // Implementation Session Operations
1126
+ // ========================================================================
1127
+ {
1128
+ name: 'start_implementation_session',
1129
+ description: 'Start an implementation session for a specification. An implementation session is for autonomous multi-ticket implementation, tracking completed/failed/skipped tickets. This is different from a work session (session.start) which is for working on a single ticket. Returns actionable and blocked tickets.',
1130
+ inputSchema: {
1131
+ type: 'object',
1132
+ properties: {
1133
+ specificationId: {
1408
1134
  type: 'string',
1409
- description: 'What this epic achieves',
1135
+ description: 'The ID of the specification to create a session for',
1410
1136
  },
1411
- epicNumber: {
1412
- type: 'number',
1413
- description: 'Epic number (auto-incremented if not provided)',
1137
+ config: {
1138
+ type: 'object',
1139
+ description: 'Optional session configuration',
1140
+ properties: {
1141
+ mode: {
1142
+ type: 'string',
1143
+ enum: ['single', 'autonomous', 'guided'],
1144
+ description: 'Implementation mode (default: autonomous)',
1145
+ },
1146
+ maxTickets: {
1147
+ type: 'number',
1148
+ description: 'Maximum tickets to process (null = unlimited, default: 5)',
1149
+ },
1150
+ stopOnFailure: {
1151
+ type: 'boolean',
1152
+ description: 'Stop session on first failure (default: false)',
1153
+ },
1154
+ autoCommit: {
1155
+ type: 'boolean',
1156
+ description: 'Auto-commit after each ticket (default: true)',
1157
+ },
1158
+ reviewAtEpicBoundaries: {
1159
+ type: 'boolean',
1160
+ description: 'Pause when crossing epic boundaries (default: false)',
1161
+ },
1162
+ epicReviewList: {
1163
+ type: 'array',
1164
+ items: { type: 'string' },
1165
+ description: 'Epic IDs that require review',
1166
+ },
1167
+ },
1414
1168
  },
1415
- content: {
1416
- type: 'string',
1417
- description: 'Full epic content (markdown)',
1169
+ force: {
1170
+ type: 'boolean',
1171
+ description: 'Force create by ending any existing active session (default: false)',
1418
1172
  },
1419
- scope: {
1173
+ },
1174
+ required: ['specificationId'],
1175
+ },
1176
+ },
1177
+ {
1178
+ name: 'end_session',
1179
+ description: 'End an implementation session (started with start_implementation_session). Returns final stats. This is different from session.complete which completes work on a single ticket.',
1180
+ inputSchema: {
1181
+ type: 'object',
1182
+ properties: {
1183
+ sessionId: {
1420
1184
  type: 'string',
1421
- description: "What's in/out of scope for this epic",
1185
+ description: 'The ID of the session to end',
1422
1186
  },
1423
- goals: {
1424
- type: 'array',
1425
- items: { type: 'string' },
1426
- description: 'Epic-specific goals',
1187
+ status: {
1188
+ type: 'string',
1189
+ enum: ['completed', 'aborted'],
1190
+ description: 'How the session ended',
1427
1191
  },
1428
- guardrails: {
1429
- type: 'array',
1430
- items: { type: 'string' },
1431
- description: 'What NOT to do for this epic',
1432
- },
1433
- risks: {
1434
- type: 'array',
1435
- items: { type: 'string' },
1436
- description: 'Risk factors for this epic',
1437
- },
1438
- constraints: {
1439
- type: 'array',
1440
- items: { type: 'string' },
1441
- description: 'Technical or business constraints for this epic',
1442
- },
1443
- assumptions: {
1444
- type: 'array',
1445
- items: { type: 'string' },
1446
- description: 'Key assumptions made for this epic',
1447
- },
1448
- architecture: {
1449
- type: 'string',
1450
- description: 'Architectural approach for this epic',
1451
- },
1452
- fileStructure: {
1453
- type: 'string',
1454
- description: 'File/folder organization for this epic',
1455
- },
1456
- techStack: {
1457
- type: 'array',
1458
- items: { type: 'string' },
1459
- description: 'Technologies used (subset of specification)',
1460
- },
1461
- dependencies: {
1462
- type: 'array',
1463
- items: { type: 'string' },
1464
- description: 'Required packages/libraries',
1465
- },
1466
- apiContracts: {
1467
- type: 'object',
1468
- description: 'API specifications for this epic',
1469
- },
1470
- acceptanceCriteria: {
1471
- type: 'array',
1472
- items: { type: 'string' },
1473
- description: 'Epic-level success criteria',
1474
- },
1475
- priority: {
1476
- type: 'string',
1477
- enum: ['high', 'medium', 'low'],
1478
- description: 'Priority level',
1479
- },
1480
- tags: {
1481
- type: 'array',
1482
- items: { type: 'string' },
1483
- description: 'Categorization tags',
1484
- },
1485
- estimatedHours: {
1486
- type: 'number',
1487
- description: 'Total estimated hours for epic',
1488
- },
1489
- // Pattern inheritance fields (epic level)
1490
- sharedPatterns: {
1491
- type: 'object',
1492
- description: 'Patterns shared by all tickets in this epic',
1493
- properties: {
1494
- errorHandling: { type: 'string', description: 'Override error handling for this epic' },
1495
- returnType: { type: 'string', description: 'Epic-specific return type' },
1496
- actionPrefix: { type: 'string', description: 'Redux/action prefix for this epic' },
1497
- stateSlice: { type: 'string', description: 'State slice path for this epic' },
1498
- },
1499
- },
1500
- additionalImports: {
1501
- type: 'array',
1502
- items: { type: 'string' },
1503
- description: 'Additional imports for tickets in this epic (added to spec-level imports)',
1504
- },
1505
- commonFiles: {
1506
- type: 'object',
1507
- description: 'Common file paths for this epic',
1508
- properties: {
1509
- reducer: { type: 'string', description: 'Reducer file path' },
1510
- actions: { type: 'string', description: 'Actions file path' },
1511
- types: { type: 'string', description: 'Types file path' },
1512
- index: { type: 'string', description: 'Index/barrel file path' },
1513
- },
1514
- },
1515
- responseMode: {
1516
- type: 'string',
1517
- enum: ['full', 'minimal', 'id-only'],
1518
- description: 'Response verbosity: full (default, ~500 tokens), minimal (~50 tokens), id-only (~20 tokens)',
1519
- },
1520
- },
1521
- required: ['specificationId', 'title', 'description', 'objective'],
1522
- },
1523
- },
1524
- {
1525
- name: 'create_ticket',
1526
- description: 'Create a new ticket in an epic. Returns validation warnings based on complexity level.',
1527
- inputSchema: {
1528
- type: 'object',
1529
- properties: {
1530
- epicId: {
1531
- type: 'string',
1532
- description: 'The ID of the epic',
1533
- },
1534
- title: {
1535
- type: 'string',
1536
- description: 'Ticket title',
1537
- },
1538
- ticketNumber: {
1539
- type: 'number',
1540
- description: 'Ticket number (auto-incremented if not provided)',
1541
- },
1542
- description: {
1543
- type: 'string',
1544
- description: 'Ticket description',
1545
- },
1546
- implementation: {
1547
- type: 'object',
1548
- description: 'Detailed implementation steps (JSON)',
1549
- },
1550
- technicalDetails: {
1551
- type: 'object',
1552
- description: 'Technical details like stack, endpoints (JSON)',
1553
- },
1554
- acceptanceCriteria: {
1555
- type: 'array',
1556
- items: { type: 'string' },
1557
- description: 'Success criteria',
1558
- },
1559
- priority: {
1560
- type: 'string',
1561
- enum: ['high', 'medium', 'low'],
1562
- description: 'Priority level',
1563
- },
1564
- complexity: {
1565
- type: 'string',
1566
- enum: ['small', 'medium', 'large', 'xlarge'],
1567
- description: 'Size/complexity indicator',
1568
- },
1569
- tags: {
1570
- type: 'array',
1571
- items: { type: 'string' },
1572
- description: 'Categorization tags',
1573
- },
1574
- notes: {
1575
- type: 'string',
1576
- description: 'Additional context, warnings, or considerations',
1577
- },
1578
- estimatedHours: {
1579
- type: 'number',
1580
- description: 'Estimated effort in hours',
1581
- },
1582
- dependsOn: {
1583
- type: 'array',
1584
- items: { type: 'string' },
1585
- description: 'Array of ticket IDs this ticket depends on',
1586
- },
1587
- validationStrictness: {
1588
- type: 'string',
1589
- enum: ['lenient', 'normal', 'strict'],
1590
- description: 'Warning strictness level. lenient=warnings only, normal=warnings+recommendations, strict=all. Default: normal',
1591
- },
1592
- responseMode: {
1593
- type: 'string',
1594
- enum: ['full', 'minimal', 'id-only'],
1595
- description: 'Response verbosity: full (default, ~500 tokens), minimal (~50 tokens), id-only (~20 tokens)',
1596
- },
1597
- },
1598
- required: ['epicId', 'title'],
1599
- },
1600
- },
1601
- {
1602
- name: 'import_specification',
1603
- description: 'Import a markdown file as a complete specification with AI-powered parsing. Parses epics from ## headers and tickets from ### headers.',
1604
- inputSchema: {
1605
- type: 'object',
1606
- properties: {
1607
- projectId: {
1608
- type: 'string',
1609
- description: 'The ID of the project to import into',
1610
- },
1611
- content: {
1612
- type: 'string',
1613
- description: 'Raw markdown content to parse and import',
1614
- },
1615
- title: {
1616
- type: 'string',
1617
- description: 'Override the parsed title (optional)',
1618
- },
1619
- specificationTypeId: {
1620
- type: 'string',
1621
- description: 'Specification type ID (uses default if not provided)',
1622
- },
1623
- },
1624
- required: ['projectId', 'content'],
1625
- },
1626
- },
1627
- // ========================================================================
1628
- // Update Operations
1629
- // ========================================================================
1630
- {
1631
- name: 'update_ticket',
1632
- description: "Update a ticket's properties (status, description, estimate, etc.).\n\n" +
1633
- 'When status changes, counts are automatically propagated up the hierarchy ' +
1634
- '(Epic → Specification → Project).',
1635
- inputSchema: {
1636
- type: 'object',
1637
- properties: {
1638
- ticketId: {
1639
- type: 'string',
1640
- description: 'The ID of the ticket to update',
1641
- },
1642
- title: {
1643
- type: 'string',
1644
- description: 'New title (optional)',
1645
- },
1646
- description: {
1647
- type: 'string',
1648
- description: 'New description (optional)',
1649
- },
1650
- status: {
1651
- type: 'string',
1652
- enum: ['pending', 'ready', 'active', 'done'],
1653
- description: 'Ticket status. pending/ready may be recalculated based on dependencies.',
1654
- },
1655
- priority: {
1656
- type: 'string',
1657
- enum: ['low', 'medium', 'high', 'critical'],
1658
- description: 'Priority level (optional)',
1659
- },
1660
- complexity: {
1661
- type: 'string',
1662
- enum: ['small', 'medium', 'large', 'xlarge'],
1663
- description: 'Size/complexity indicator (optional)',
1664
- },
1665
- blockReason: {
1666
- type: 'string',
1667
- description: 'External block reason. Forces status to pending until cleared.',
1668
- },
1669
- notes: {
1670
- type: 'string',
1671
- description: 'Additional context, warnings, or considerations (optional)',
1672
- },
1673
- estimatedHours: {
1674
- type: 'number',
1675
- description: 'Estimated hours (optional)',
1676
- },
1677
- tags: {
1678
- type: 'array',
1679
- items: { type: 'string' },
1680
- description: 'Tags (optional)',
1681
- },
1682
- acceptanceCriteria: {
1683
- type: 'array',
1684
- items: { type: 'string' },
1685
- description: 'Acceptance criteria (optional)',
1686
- },
1687
- implementation: {
1688
- type: 'object',
1689
- description: 'Detailed implementation steps (JSON) (optional)',
1690
- },
1691
- technicalDetails: {
1692
- type: 'object',
1693
- description: 'Technical details like stack, endpoints (JSON) (optional)',
1694
- },
1695
- validationStrictness: {
1696
- type: 'string',
1697
- enum: ['lenient', 'normal', 'strict'],
1698
- description: 'Warning strictness level (default: normal)',
1699
- default: 'normal',
1700
- },
1701
- responseMode: {
1702
- type: 'string',
1703
- enum: ['full', 'minimal', 'id-only'],
1704
- description: 'Response verbosity: full (default, ~500 tokens), minimal (~50 tokens), id-only (~20 tokens)',
1705
- },
1706
- },
1707
- required: ['ticketId'],
1708
- },
1709
- },
1710
- {
1711
- name: 'update_epic',
1712
- description: "Update an epic's properties",
1713
- inputSchema: {
1714
- type: 'object',
1715
- properties: {
1716
- epicId: {
1717
- type: 'string',
1718
- description: 'The ID of the epic to update',
1719
- },
1720
- title: {
1721
- type: 'string',
1722
- description: 'New title (optional)',
1723
- },
1724
- description: {
1725
- type: 'string',
1726
- description: 'New description (optional)',
1727
- },
1728
- status: {
1729
- type: 'string',
1730
- enum: ['todo', 'in_progress', 'completed'],
1731
- description: 'New status (optional)',
1732
- },
1733
- objective: {
1734
- type: 'string',
1735
- description: 'New objective (optional)',
1736
- },
1737
- scope: {
1738
- type: 'string',
1739
- description: 'What\'s in/out of scope (optional)',
1740
- },
1741
- goals: {
1742
- type: 'array',
1743
- items: { type: 'string' },
1744
- description: 'Epic-specific goals (optional)',
1745
- },
1746
- guardrails: {
1747
- type: 'array',
1748
- items: { type: 'string' },
1749
- description: 'What NOT to do (optional)',
1750
- },
1751
- risks: {
1752
- type: 'array',
1753
- items: { type: 'string' },
1754
- description: 'Risk factors (optional)',
1755
- },
1756
- constraints: {
1757
- type: 'array',
1758
- items: { type: 'string' },
1759
- description: 'Technical/business constraints (optional)',
1760
- },
1761
- assumptions: {
1762
- type: 'array',
1763
- items: { type: 'string' },
1764
- description: 'Key assumptions (optional)',
1765
- },
1766
- architecture: {
1767
- type: 'string',
1768
- description: 'Architectural approach (optional)',
1769
- },
1770
- fileStructure: {
1771
- type: 'string',
1772
- description: 'File/folder organization (optional)',
1773
- },
1774
- techStack: {
1775
- type: 'array',
1776
- items: { type: 'string' },
1777
- description: 'Technologies used (optional)',
1778
- },
1779
- dependencies: {
1780
- type: 'array',
1781
- items: { type: 'string' },
1782
- description: 'Required packages/libraries (optional)',
1783
- },
1784
- apiContracts: {
1785
- type: 'object',
1786
- description: 'API specifications (optional)',
1787
- },
1788
- acceptanceCriteria: {
1789
- type: 'array',
1790
- items: { type: 'string' },
1791
- description: 'Success criteria (optional)',
1792
- },
1793
- tags: {
1794
- type: 'array',
1795
- items: { type: 'string' },
1796
- description: 'Categorization tags (optional)',
1797
- },
1798
- estimatedHours: {
1799
- type: 'number',
1800
- description: 'Total estimated hours (optional)',
1801
- },
1802
- priority: {
1803
- type: 'string',
1804
- enum: ['low', 'medium', 'high', 'critical'],
1805
- description: 'Priority level (optional)',
1806
- },
1807
- // Pattern inheritance fields (epic level)
1808
- sharedPatterns: {
1809
- type: 'object',
1810
- description: 'Patterns shared by all tickets in this epic (optional)',
1811
- properties: {
1812
- errorHandling: { type: 'string', description: 'Override error handling for this epic' },
1813
- returnType: { type: 'string', description: 'Epic-specific return type' },
1814
- actionPrefix: { type: 'string', description: 'Redux/action prefix for this epic' },
1815
- stateSlice: { type: 'string', description: 'State slice path for this epic' },
1816
- },
1817
- },
1818
- additionalImports: {
1819
- type: 'array',
1820
- items: { type: 'string' },
1821
- description: 'Additional imports for tickets in this epic (optional)',
1822
- },
1823
- commonFiles: {
1824
- type: 'object',
1825
- description: 'Common file paths for this epic (optional)',
1826
- properties: {
1827
- reducer: { type: 'string', description: 'Reducer file path' },
1828
- actions: { type: 'string', description: 'Actions file path' },
1829
- types: { type: 'string', description: 'Types file path' },
1830
- index: { type: 'string', description: 'Index/barrel file path' },
1831
- },
1832
- },
1833
- responseMode: {
1834
- type: 'string',
1835
- enum: ['full', 'minimal', 'id-only'],
1836
- description: 'Response verbosity: full (default, ~500 tokens), minimal (~50 tokens), id-only (~20 tokens)',
1837
- },
1838
- },
1839
- required: ['epicId'],
1840
- },
1841
- },
1842
- {
1843
- name: 'update_specification',
1844
- description: "Update a specification's properties",
1845
- inputSchema: {
1846
- type: 'object',
1847
- properties: {
1848
- specificationId: {
1849
- type: 'string',
1850
- description: 'The ID of the specification to update',
1851
- },
1852
- title: {
1853
- type: 'string',
1854
- description: 'New title (optional)',
1855
- },
1856
- description: {
1857
- type: 'string',
1858
- description: 'New description (optional)',
1859
- },
1860
- status: {
1861
- type: 'string',
1862
- enum: ['draft', 'planning', 'ready', 'in_progress', 'completed'],
1863
- description: 'New status (optional)',
1864
- },
1865
- background: {
1866
- type: 'string',
1867
- description: 'New background (optional)',
1868
- },
1869
- scope: {
1870
- type: 'string',
1871
- description: 'New scope (optional)',
1872
- },
1873
- goals: {
1874
- type: 'array',
1875
- items: { type: 'string' },
1876
- description: 'Business/user/technical objectives (optional)',
1877
- },
1878
- requirements: {
1879
- type: 'array',
1880
- items: { type: 'string' },
1881
- description: 'Functional requirements (optional)',
1882
- },
1883
- nonFunctionalRequirements: {
1884
- type: 'array',
1885
- items: { type: 'string' },
1886
- description: 'Non-functional requirements like performance, security (optional)',
1887
- },
1888
- successMetrics: {
1889
- type: 'array',
1890
- items: { type: 'string' },
1891
- description: 'KPIs to measure success (optional)',
1892
- },
1893
- constraints: {
1894
- type: 'array',
1895
- items: { type: 'string' },
1896
- description: 'Technical/business constraints (optional)',
1897
- },
1898
- assumptions: {
1899
- type: 'array',
1900
- items: { type: 'string' },
1901
- description: 'Key assumptions made (optional)',
1902
- },
1903
- risks: {
1904
- type: 'array',
1905
- items: { type: 'string' },
1906
- description: 'Risk factors and mitigations (optional)',
1907
- },
1908
- guardrails: {
1909
- type: 'array',
1910
- items: { type: 'string' },
1911
- description: 'What NOT to do (optional)',
1912
- },
1913
- architecture: {
1914
- type: 'string',
1915
- description: 'Architectural approach (optional)',
1916
- },
1917
- fileStructure: {
1918
- type: 'string',
1919
- description: 'File/folder organization (optional)',
1920
- },
1921
- techStack: {
1922
- type: 'array',
1923
- items: { type: 'string' },
1924
- description: 'Technologies to use (optional)',
1925
- },
1926
- dependencies: {
1927
- type: 'array',
1928
- items: { type: 'string' },
1929
- description: 'Required packages/libraries (optional)',
1930
- },
1931
- apiContracts: {
1932
- type: 'object',
1933
- description: 'API specifications (optional)',
1934
- },
1935
- acceptanceCriteria: {
1936
- type: 'array',
1937
- items: { type: 'string' },
1938
- description: 'Success criteria (optional)',
1939
- },
1940
- tags: {
1941
- type: 'array',
1942
- items: { type: 'string' },
1943
- description: 'Categorization tags (optional)',
1944
- },
1945
- estimatedHours: {
1946
- type: 'number',
1947
- description: 'Total estimated hours (optional)',
1948
- },
1949
- targetAudience: {
1950
- type: 'string',
1951
- description: 'Who this is for - developers, users, stakeholders, etc. (optional)',
1952
- },
1953
- priority: {
1954
- type: 'string',
1955
- enum: ['low', 'medium', 'high', 'critical'],
1956
- description: 'Priority level (optional)',
1957
- },
1958
- validationCommands: {
1959
- type: 'object',
1960
- description: 'Validation commands (test, lint, build, typeCheck, custom) (optional)',
1961
- properties: {
1962
- test: { type: 'string', description: 'Test command' },
1963
- lint: { type: 'string', description: 'Lint command' },
1964
- build: { type: 'string', description: 'Build command' },
1965
- typeCheck: { type: 'string', description: 'Type check command' },
1966
- preValidation: { type: 'string', description: 'Pre-validation command' },
1967
- postValidation: { type: 'string', description: 'Post-validation command' },
1968
- custom: {
1969
- type: 'object',
1970
- description: 'Custom validation commands',
1971
- additionalProperties: { type: 'string' },
1972
- },
1973
- },
1974
- },
1975
- workingDirectory: {
1976
- type: 'string',
1977
- description: 'Working directory for commands (optional)',
1978
- },
1979
- outputDirectory: {
1980
- type: 'string',
1981
- description: 'Output directory for build artifacts (optional)',
1982
- },
1983
- // Pattern inheritance fields (specification level)
1984
- codeStandards: {
1985
- type: 'object',
1986
- description: 'Code standards inherited by all epics/tickets (optional)',
1987
- properties: {
1988
- language: { type: 'string', description: 'Primary language (e.g., "TypeScript")' },
1989
- asyncPattern: { type: 'string', description: 'Async pattern (e.g., "async/await")' },
1990
- errorHandling: { type: 'string', description: 'Error handling approach' },
1991
- documentation: { type: 'string', description: 'Documentation style' },
1992
- testing: { type: 'string', description: 'Testing approach' },
1993
- naming: {
1994
- type: 'object',
1995
- description: 'Naming conventions',
1996
- properties: {
1997
- files: { type: 'string', description: 'File naming convention' },
1998
- functions: { type: 'string', description: 'Function naming convention' },
1999
- interfaces: { type: 'string', description: 'Interface naming convention' },
2000
- actions: { type: 'string', description: 'Action naming convention' },
2001
- },
2002
- },
2003
- },
2004
- },
2005
- commonImports: {
2006
- type: 'array',
2007
- items: { type: 'string' },
2008
- description: 'Common imports inherited by all epics/tickets (optional)',
2009
- },
2010
- returnTypes: {
2011
- type: 'object',
2012
- description: 'Standard return types for CRUD operations (optional)',
2013
- properties: {
2014
- create: { type: 'string', description: 'Return type for create operations' },
2015
- update: { type: 'string', description: 'Return type for update operations' },
2016
- delete: { type: 'string', description: 'Return type for delete operations' },
2017
- list: { type: 'string', description: 'Return type for list operations' },
2018
- },
2019
- },
2020
- responseMode: {
2021
- type: 'string',
2022
- enum: ['full', 'minimal', 'id-only'],
2023
- description: 'Response verbosity: full (default, ~500 tokens), minimal (~50 tokens), id-only (~20 tokens)',
2024
- },
2025
- },
2026
- required: ['specificationId'],
2027
- },
2028
- },
2029
- // ========================================================================
2030
- // Implementation Session Operations
2031
- // ========================================================================
2032
- {
2033
- name: 'start_implementation_session',
2034
- description: 'Start an implementation session for a specification. An implementation session is for autonomous multi-ticket implementation, tracking completed/failed/skipped tickets. This is different from a work session (session.start) which is for working on a single ticket. Returns actionable and blocked tickets.',
2035
- inputSchema: {
2036
- type: 'object',
2037
- properties: {
2038
- specificationId: {
2039
- type: 'string',
2040
- description: 'The ID of the specification to create a session for',
2041
- },
2042
- config: {
2043
- type: 'object',
2044
- description: 'Optional session configuration',
2045
- properties: {
2046
- mode: {
2047
- type: 'string',
2048
- enum: ['single', 'autonomous', 'guided'],
2049
- description: 'Implementation mode (default: autonomous)',
2050
- },
2051
- maxTickets: {
2052
- type: 'number',
2053
- description: 'Maximum tickets to process (null = unlimited, default: 5)',
2054
- },
2055
- stopOnFailure: {
2056
- type: 'boolean',
2057
- description: 'Stop session on first failure (default: false)',
2058
- },
2059
- autoCommit: {
2060
- type: 'boolean',
2061
- description: 'Auto-commit after each ticket (default: true)',
2062
- },
2063
- reviewAtEpicBoundaries: {
2064
- type: 'boolean',
2065
- description: 'Pause when crossing epic boundaries (default: false)',
2066
- },
2067
- epicReviewList: {
2068
- type: 'array',
2069
- items: { type: 'string' },
2070
- description: 'Epic IDs that require review',
2071
- },
2072
- },
2073
- },
2074
- force: {
2075
- type: 'boolean',
2076
- description: 'Force create by ending any existing active session (default: false)',
2077
- },
2078
- },
2079
- required: ['specificationId'],
2080
- },
2081
- },
2082
- {
2083
- name: 'end_session',
2084
- description: 'End an implementation session (started with start_implementation_session). Returns final stats. This is different from session.complete which completes work on a single ticket.',
2085
- inputSchema: {
2086
- type: 'object',
2087
- properties: {
2088
- sessionId: {
2089
- type: 'string',
2090
- description: 'The ID of the session to end',
2091
- },
2092
- status: {
2093
- type: 'string',
2094
- enum: ['completed', 'aborted'],
2095
- description: 'How the session ended',
2096
- },
2097
- summary: {
2098
- type: 'string',
2099
- description: 'End-of-session summary',
1192
+ summary: {
1193
+ type: 'string',
1194
+ description: 'End-of-session summary',
2100
1195
  },
2101
1196
  },
2102
1197
  required: ['sessionId', 'status'],
2103
1198
  },
2104
1199
  },
2105
- // ========================================================================
2106
- // Bulk Operations
2107
- // ========================================================================
2108
- {
2109
- name: 'bulk_add_dependencies',
2110
- description: 'Add multiple dependencies between tickets in a single atomic transaction.',
2111
- inputSchema: {
2112
- type: 'object',
2113
- properties: {
2114
- dependencies: {
2115
- type: 'array',
2116
- description: 'Array of dependency definitions',
2117
- items: {
2118
- type: 'object',
2119
- properties: {
2120
- ticketId: {
2121
- type: 'string',
2122
- description: 'ID of the ticket that will depend on another',
2123
- },
2124
- dependsOnId: {
2125
- type: 'string',
2126
- description: 'ID of the ticket it will depend on',
2127
- },
2128
- type: {
2129
- type: 'string',
2130
- enum: ['blocks', 'requires'],
2131
- description: "Type of dependency (default: 'requires')",
2132
- },
2133
- },
2134
- required: ['ticketId', 'dependsOnId'],
2135
- },
2136
- },
2137
- skipCircularCheck: {
2138
- type: 'boolean',
2139
- description: 'Skip validation of circular dependencies (default: false)',
2140
- },
2141
- onError: {
2142
- type: 'string',
2143
- enum: ['rollback', 'continue'],
2144
- description: "Error handling mode: 'rollback' stops and undoes all, 'continue' skips failures (default: 'continue')",
2145
- },
2146
- },
2147
- required: ['dependencies'],
2148
- },
2149
- },
2150
1200
  {
2151
1201
  name: 'bulk_update_tickets',
2152
1202
  description: 'Update multiple tickets in a single atomic operation. All updates succeed or all fail (unless atomic: false).',
@@ -2544,34 +1594,6 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
2544
1594
  // ========================================================================
2545
1595
  // Delete Operations
2546
1596
  // ========================================================================
2547
- {
2548
- name: 'delete_ticket',
2549
- description: 'Delete a ticket and all its related records (dependencies, test results, discoveries, blueprint references)',
2550
- inputSchema: {
2551
- type: 'object',
2552
- properties: {
2553
- ticketId: {
2554
- type: 'string',
2555
- description: 'The ID of the ticket to delete',
2556
- },
2557
- },
2558
- required: ['ticketId'],
2559
- },
2560
- },
2561
- {
2562
- name: 'delete_epic',
2563
- description: 'Delete an epic and cascade delete all its tickets and related records',
2564
- inputSchema: {
2565
- type: 'object',
2566
- properties: {
2567
- epicId: {
2568
- type: 'string',
2569
- description: 'The ID of the epic to delete',
2570
- },
2571
- },
2572
- required: ['epicId'],
2573
- },
2574
- },
2575
1597
  {
2576
1598
  name: 'delete_specification',
2577
1599
  description: 'Delete a specification and cascade delete all epics, tickets, and related records',
@@ -2665,54 +1687,42 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
2665
1687
  // Review & Completion
2666
1688
  // ========================================================================
2667
1689
  {
2668
- name: 'review_planning',
2669
- description: 'Review the planning quality of a specification. Analyzes ticket completeness, dependency structure, estimation coverage, and acceptance criteria. Returns a detailed report with scores and actionable suggestions.',
1690
+ name: 'review_implementation',
1691
+ description: 'Review the implementation progress and quality of a specification. Analyzes completed tickets, test coverage, code quality signals, and remaining work. Returns a progress report with recommendations.',
2670
1692
  inputSchema: {
2671
1693
  type: 'object',
2672
1694
  properties: {
2673
1695
  specificationId: {
2674
1696
  type: 'string',
2675
- description: 'The ID of the specification to review',
2676
- },
2677
- page: {
2678
- type: 'integer',
2679
- description: 'Page number for paginated results (default: 1)',
2680
- },
2681
- pageSize: {
2682
- type: 'integer',
2683
- description: 'Number of items per page (default: 20)',
2684
- },
2685
- includeFullReport: {
2686
- type: 'boolean',
2687
- description: 'Whether to include the full detailed report (default: false)',
1697
+ description: 'The ID of the specification to review',
2688
1698
  },
2689
1699
  },
2690
1700
  required: ['specificationId'],
2691
1701
  },
2692
1702
  },
2693
1703
  {
2694
- name: 'review_implementation',
2695
- description: 'Review the implementation progress and quality of a specification. Analyzes completed tickets, test coverage, code quality signals, and remaining work. Returns a progress report with recommendations.',
1704
+ name: 'complete_specification',
1705
+ description: 'Mark a specification as complete. Validates that all epics and tickets are done, calculates final metrics, and transitions the specification to completed status. Use review_implementation first to check readiness.',
2696
1706
  inputSchema: {
2697
1707
  type: 'object',
2698
1708
  properties: {
2699
1709
  specificationId: {
2700
1710
  type: 'string',
2701
- description: 'The ID of the specification to review',
1711
+ description: 'The ID of the specification to complete',
2702
1712
  },
2703
1713
  },
2704
1714
  required: ['specificationId'],
2705
1715
  },
2706
1716
  },
2707
1717
  {
2708
- name: 'complete_specification',
2709
- description: 'Mark a specification as complete. Validates that all epics and tickets are done, calculates final metrics, and transitions the specification to completed status. Use review_implementation first to check readiness.',
1718
+ name: 'reopen_specification',
1719
+ description: 'Reopen a specification in "ready" status, regressing to "planning". After reopening, call start_planning_session to begin a new planning session.',
2710
1720
  inputSchema: {
2711
1721
  type: 'object',
2712
1722
  properties: {
2713
1723
  specificationId: {
2714
1724
  type: 'string',
2715
- description: 'The ID of the specification to complete',
1725
+ description: 'The ID of the specification to reopen',
2716
1726
  },
2717
1727
  },
2718
1728
  required: ['specificationId'],
@@ -2738,9 +1748,85 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
2738
1748
  },
2739
1749
  },
2740
1750
  },
1751
+ // ========================================================================
1752
+ // Planning Session Operations
1753
+ // ========================================================================
1754
+ {
1755
+ name: 'start_planning_session',
1756
+ description: 'Start or resume a guided planning session for a specification. Auto-detects the current state — whether the spec is new, partially complete, or needs refinement after review. Returns current status, progress scores, blockers, and suggested next actions. Always call this before using action_planning_session.',
1757
+ inputSchema: {
1758
+ type: 'object',
1759
+ properties: {
1760
+ specificationId: {
1761
+ type: 'string',
1762
+ description: 'The ID of the specification to plan',
1763
+ },
1764
+ },
1765
+ required: ['specificationId'],
1766
+ },
1767
+ },
1768
+ {
1769
+ name: 'action_planning_session',
1770
+ description: "Execute a planning action within an active session. Wraps all planning operations (create/update epics, tickets, dependencies, blueprints) and read operations (get_ticket for inspecting details) with automatic status tracking. The spec status advances or regresses automatically based on the action type and gate checks. Returns updated progress, blockers, and next suggested actions after every call. Use responseDetail to control verbosity: 'minimal' (~80 tokens) for rapid iteration, 'standard' (~200 tokens, default) for normal work, 'full' (~500 tokens) for debugging.",
1771
+ inputSchema: {
1772
+ type: 'object',
1773
+ properties: {
1774
+ specificationId: {
1775
+ type: 'string',
1776
+ description: 'The ID of the specification',
1777
+ },
1778
+ operation: {
1779
+ type: 'object',
1780
+ description: 'The operation to perform. Must include a "type" field.',
1781
+ properties: {
1782
+ type: {
1783
+ type: 'string',
1784
+ enum: [
1785
+ 'set_metadata',
1786
+ 'create_epic',
1787
+ 'update_epic',
1788
+ 'create_ticket',
1789
+ 'update_ticket',
1790
+ 'delete_epic',
1791
+ 'delete_ticket',
1792
+ 'add_dependencies',
1793
+ 'remove_dependency',
1794
+ 'create_blueprint',
1795
+ 'link_blueprint',
1796
+ 'get_ticket',
1797
+ 'advance_phase',
1798
+ 'get_status',
1799
+ ],
1800
+ description: 'The type of planning operation to perform',
1801
+ },
1802
+ },
1803
+ required: ['type'],
1804
+ },
1805
+ responseDetail: {
1806
+ type: 'string',
1807
+ enum: ['minimal', 'standard', 'full'],
1808
+ description: 'Response detail level: minimal (~80 tokens), standard (~200, default), full (~500)',
1809
+ },
1810
+ },
1811
+ required: ['specificationId', 'operation'],
1812
+ },
1813
+ },
1814
+ {
1815
+ name: 'complete_planning_session',
1816
+ description: "Complete the planning session and submit the spec for final review. Spec must be in 'validating' status. Runs a dry-run check first, then full review if no errors. Transitions spec to 'ready' on success. If the spec isn't in validating yet, returns what's needed to get there.",
1817
+ inputSchema: {
1818
+ type: 'object',
1819
+ properties: {
1820
+ specificationId: {
1821
+ type: 'string',
1822
+ description: 'The ID of the specification to complete planning for',
1823
+ },
1824
+ },
1825
+ required: ['specificationId'],
1826
+ },
1827
+ },
2741
1828
  ];
2742
- // Apply format parameter to all read operations
2743
- return tools.map(tool => READ_TOOL_NAMES.has(tool.name) ? addFormatParameter(tool) : tool);
1829
+ return tools;
2744
1830
  }
2745
1831
  /**
2746
1832
  * Retry configuration for transient failures
@@ -2849,14 +1935,6 @@ export function createToolHandlers(apiClient) {
2849
1935
  fields: argsWithContext.fields,
2850
1936
  });
2851
1937
  },
2852
- get_specification: async (_client, args) => {
2853
- validateRequired(args, 'specificationId');
2854
- return await apiClient.call('get_specification', {
2855
- specificationId: args.specificationId,
2856
- summary: args.summary,
2857
- include: args.include,
2858
- });
2859
- },
2860
1938
  lookup_specification: async (_client, args) => {
2861
1939
  validateRequired(args, 'title');
2862
1940
  // Inject projectId from .specforge.json if not provided
@@ -2881,14 +1959,6 @@ export function createToolHandlers(apiClient) {
2881
1959
  fields: argsWithContext.fields,
2882
1960
  });
2883
1961
  },
2884
- get_epic: async (_client, args) => {
2885
- validateRequired(args, 'epicId');
2886
- return await apiClient.call('get_epic', {
2887
- epicId: args.epicId,
2888
- summary: args.summary,
2889
- include: args.include,
2890
- });
2891
- },
2892
1962
  lookup_epic: async (_client, args) => {
2893
1963
  // Must provide either title or number
2894
1964
  if (!args.title && args.number === undefined) {
@@ -2920,14 +1990,6 @@ export function createToolHandlers(apiClient) {
2920
1990
  fields: argsWithContext.fields,
2921
1991
  });
2922
1992
  },
2923
- get_ticket: async (_client, args) => {
2924
- validateRequired(args, 'ticketId');
2925
- return await apiClient.call('get_ticket', {
2926
- ticketId: args.ticketId,
2927
- summary: args.summary,
2928
- include: args.include,
2929
- });
2930
- },
2931
1993
  lookup_ticket: async (_client, args) => {
2932
1994
  validateRequired(args, 'epicId');
2933
1995
  // Must provide either title or number
@@ -2965,42 +2027,6 @@ export function createToolHandlers(apiClient) {
2965
2027
  });
2966
2028
  },
2967
2029
  // ========================================================================
2968
- // Core Operations - Dependencies
2969
- // ========================================================================
2970
- add_dependency: async (_client, args) => {
2971
- validateRequired(args, 'ticketId');
2972
- validateRequired(args, 'dependsOnId');
2973
- return await apiClient.call('add_dependency', {
2974
- ticketId: args.ticketId,
2975
- dependsOnId: args.dependsOnId,
2976
- type: args.type,
2977
- });
2978
- },
2979
- remove_dependency: async (_client, args) => {
2980
- // Either dependencyId or (ticketId + dependsOnId) required
2981
- if (!args.dependencyId && !args.ticketId) {
2982
- throw new Error('Either dependencyId or ticketId is required');
2983
- }
2984
- return await apiClient.call('remove_dependency', {
2985
- ticketId: args.ticketId,
2986
- dependsOnId: args.dependsOnId,
2987
- dependencyId: args.dependencyId,
2988
- });
2989
- },
2990
- get_dependency_tree: async (_client, args) => {
2991
- validateRequired(args, 'specificationId');
2992
- return await apiClient.call('get_dependency_tree', {
2993
- specificationId: args.specificationId,
2994
- });
2995
- },
2996
- check_circular_dependencies: async (_client, args) => {
2997
- const argsWithContext = injectContext(args, ['specificationId', 'projectId']);
2998
- return await apiClient.call('check_circular_dependencies', {
2999
- specificationId: argsWithContext.specificationId,
3000
- projectId: argsWithContext.projectId,
3001
- });
3002
- },
3003
- // ========================================================================
3004
2030
  // Context & AI Tools
3005
2031
  // ========================================================================
3006
2032
  get_implementation_context: async (_client, args) => {
@@ -3075,16 +2101,6 @@ export function createToolHandlers(apiClient) {
3075
2101
  specificationId: argsWithContext.specificationId,
3076
2102
  });
3077
2103
  },
3078
- get_critical_path: async (_client, args) => {
3079
- // Inject specificationId from .specforge.json if not provided
3080
- const argsWithContext = injectContext(args, ['specificationId']);
3081
- if (!argsWithContext.specificationId) {
3082
- throw new Error('specificationId is required. Set working context with "specforge switch" or provide explicitly.');
3083
- }
3084
- return await apiClient.call('get_critical_path', {
3085
- specificationId: argsWithContext.specificationId,
3086
- });
3087
- },
3088
2104
  get_patterns: async (_client, args) => {
3089
2105
  // Inject specificationId from .specforge.json if not provided
3090
2106
  const argsWithContext = injectContext(args, ['specificationId']);
@@ -3261,6 +2277,7 @@ export function createToolHandlers(apiClient) {
3261
2277
  filesDeleted: args.filesDeleted,
3262
2278
  blockReason: args.blockReason,
3263
2279
  clearBlockReason: args.clearBlockReason,
2280
+ getTicket: args.getTicket,
3264
2281
  });
3265
2282
  },
3266
2283
  // ========================================================================
@@ -3375,79 +2392,6 @@ export function createToolHandlers(apiClient) {
3375
2392
  });
3376
2393
  return formatWriteResponse(result, responseMode, 'Specification created');
3377
2394
  },
3378
- create_epic: async (_client, args) => {
3379
- validateRequired(args, 'specificationId', 'title', 'description', 'objective');
3380
- const responseMode = getResponseModeFromArgs(args);
3381
- const result = await apiClient.call('create_epic', {
3382
- specificationId: args.specificationId,
3383
- title: args.title,
3384
- description: args.description,
3385
- objective: args.objective,
3386
- epicNumber: args.epicNumber,
3387
- content: args.content,
3388
- scope: args.scope,
3389
- goals: args.goals,
3390
- acceptanceCriteria: args.acceptanceCriteria,
3391
- priority: args.priority,
3392
- tags: args.tags,
3393
- estimatedHours: args.estimatedHours,
3394
- order: args.order,
3395
- // FI-003 fields
3396
- guardrails: args.guardrails,
3397
- risks: args.risks,
3398
- constraints: args.constraints,
3399
- assumptions: args.assumptions,
3400
- architecture: args.architecture,
3401
- fileStructure: args.fileStructure,
3402
- techStack: args.techStack,
3403
- dependencies: args.dependencies,
3404
- apiContracts: args.apiContracts,
3405
- // Pattern inheritance fields (F7-002)
3406
- sharedPatterns: args.sharedPatterns,
3407
- additionalImports: args.additionalImports,
3408
- commonFiles: args.commonFiles,
3409
- });
3410
- return formatWriteResponse(result, responseMode, 'Epic created');
3411
- },
3412
- create_ticket: async (_client, args) => {
3413
- validateRequired(args, 'epicId', 'title');
3414
- const responseMode = getResponseModeFromArgs(args);
3415
- // Extract validation options
3416
- const validationStrictness = args.validationStrictness === 'lenient' || args.validationStrictness === 'strict'
3417
- ? args.validationStrictness
3418
- : 'normal';
3419
- // Create the ticket
3420
- const result = await apiClient.call('create_ticket', {
3421
- epicId: args.epicId,
3422
- title: args.title,
3423
- ticketNumber: args.ticketNumber,
3424
- description: args.description,
3425
- implementation: args.implementation,
3426
- technicalDetails: args.technicalDetails,
3427
- acceptanceCriteria: args.acceptanceCriteria,
3428
- priority: args.priority,
3429
- complexity: args.complexity,
3430
- tags: args.tags,
3431
- estimatedHours: args.estimatedHours,
3432
- order: args.order,
3433
- dependsOn: args.dependsOn,
3434
- notes: args.notes, // F8-001: Add missing notes field
3435
- });
3436
- // Run validation
3437
- const validation = validateTicket({
3438
- complexity: args.complexity,
3439
- implementation: args.implementation,
3440
- technicalDetails: args.technicalDetails,
3441
- notes: args.notes,
3442
- acceptanceCriteria: args.acceptanceCriteria,
3443
- });
3444
- // Filter warnings by strictness level
3445
- const warnings = filterWarningsByStrictness(validation.warnings, validationStrictness);
3446
- // Add validation results to response
3447
- result.warnings = warnings;
3448
- result.completenessScore = validation.completenessScore;
3449
- return formatWriteResponse(result, responseMode, 'Ticket created');
3450
- },
3451
2395
  import_specification: async (_client, args) => {
3452
2396
  validateRequired(args, 'projectId', 'content');
3453
2397
  return await apiClient.call('import_specification', {
@@ -3458,145 +2402,6 @@ export function createToolHandlers(apiClient) {
3458
2402
  });
3459
2403
  },
3460
2404
  // ========================================================================
3461
- // Update Operations
3462
- // ========================================================================
3463
- update_ticket: async (_client, args) => {
3464
- validateRequired(args, 'ticketId');
3465
- const responseMode = getResponseModeFromArgs(args);
3466
- // Extract validation options
3467
- const validationStrictness = args.validationStrictness === 'lenient' || args.validationStrictness === 'strict'
3468
- ? args.validationStrictness
3469
- : 'normal';
3470
- // Get current ticket to calculate previous completeness score
3471
- let previousCompletenessScore;
3472
- try {
3473
- const currentTicket = await apiClient.call('get_ticket', {
3474
- ticketId: args.ticketId,
3475
- });
3476
- // Calculate previous completeness score
3477
- const prevValidation = validateTicket({
3478
- complexity: currentTicket.complexity,
3479
- implementation: currentTicket.implementation,
3480
- technicalDetails: currentTicket.technicalDetails,
3481
- notes: currentTicket.notes,
3482
- acceptanceCriteria: currentTicket.acceptanceCriteria,
3483
- });
3484
- previousCompletenessScore = prevValidation.completenessScore;
3485
- }
3486
- catch {
3487
- // If we can't get the current ticket, skip previous score tracking
3488
- previousCompletenessScore = undefined;
3489
- }
3490
- // Update the ticket
3491
- const result = await apiClient.call('update_ticket', {
3492
- ticketId: args.ticketId,
3493
- title: args.title,
3494
- description: args.description,
3495
- status: args.status,
3496
- priority: args.priority,
3497
- estimatedHours: args.estimatedHours,
3498
- tags: args.tags,
3499
- acceptanceCriteria: args.acceptanceCriteria,
3500
- // Additional fields
3501
- complexity: args.complexity,
3502
- notes: args.notes,
3503
- implementation: args.implementation,
3504
- technicalDetails: args.technicalDetails,
3505
- blockReason: args.blockReason,
3506
- });
3507
- // Run validation on updated ticket
3508
- // Use the updated values (from args) merged with existing values (from result)
3509
- // The result should contain the final state after update
3510
- const validation = validateTicket({
3511
- complexity: (args.complexity || result.complexity),
3512
- implementation: (args.implementation || result.implementation),
3513
- technicalDetails: (args.technicalDetails || result.technicalDetails),
3514
- notes: (args.notes || result.notes),
3515
- acceptanceCriteria: (args.acceptanceCriteria || result.acceptanceCriteria),
3516
- });
3517
- // Filter warnings by strictness level
3518
- const warnings = filterWarningsByStrictness(validation.warnings, validationStrictness);
3519
- // Add validation results to response
3520
- result.warnings = warnings;
3521
- result.completenessScore = validation.completenessScore;
3522
- if (previousCompletenessScore !== undefined) {
3523
- result.previousCompletenessScore = previousCompletenessScore;
3524
- }
3525
- return formatWriteResponse(result, responseMode, 'Ticket updated');
3526
- },
3527
- update_epic: async (_client, args) => {
3528
- validateRequired(args, 'epicId');
3529
- const responseMode = getResponseModeFromArgs(args);
3530
- const result = await apiClient.call('update_epic', {
3531
- epicId: args.epicId,
3532
- title: args.title,
3533
- description: args.description,
3534
- status: args.status,
3535
- objective: args.objective,
3536
- priority: args.priority,
3537
- // FI-003 fields
3538
- scope: args.scope,
3539
- goals: args.goals,
3540
- guardrails: args.guardrails,
3541
- risks: args.risks,
3542
- constraints: args.constraints,
3543
- assumptions: args.assumptions,
3544
- architecture: args.architecture,
3545
- fileStructure: args.fileStructure,
3546
- techStack: args.techStack,
3547
- dependencies: args.dependencies,
3548
- apiContracts: args.apiContracts,
3549
- acceptanceCriteria: args.acceptanceCriteria,
3550
- tags: args.tags,
3551
- estimatedHours: args.estimatedHours,
3552
- // Pattern inheritance fields (F7-002)
3553
- sharedPatterns: args.sharedPatterns,
3554
- additionalImports: args.additionalImports,
3555
- commonFiles: args.commonFiles,
3556
- });
3557
- return formatWriteResponse(result, responseMode, 'Epic updated');
3558
- },
3559
- update_specification: async (_client, args) => {
3560
- validateRequired(args, 'specificationId');
3561
- const responseMode = getResponseModeFromArgs(args);
3562
- const result = await apiClient.call('update_specification', {
3563
- specificationId: args.specificationId,
3564
- title: args.title,
3565
- description: args.description,
3566
- status: args.status,
3567
- background: args.background,
3568
- scope: args.scope,
3569
- priority: args.priority,
3570
- // FI-003 fields
3571
- goals: args.goals,
3572
- requirements: args.requirements,
3573
- nonFunctionalRequirements: args.nonFunctionalRequirements,
3574
- successMetrics: args.successMetrics,
3575
- constraints: args.constraints,
3576
- assumptions: args.assumptions,
3577
- risks: args.risks,
3578
- guardrails: args.guardrails,
3579
- architecture: args.architecture,
3580
- fileStructure: args.fileStructure,
3581
- techStack: args.techStack,
3582
- dependencies: args.dependencies,
3583
- apiContracts: args.apiContracts,
3584
- acceptanceCriteria: args.acceptanceCriteria,
3585
- tags: args.tags,
3586
- estimatedHours: args.estimatedHours,
3587
- targetAudience: args.targetAudience,
3588
- // Pattern inheritance fields (F7-001)
3589
- codeStandards: args.codeStandards,
3590
- commonImports: args.commonImports,
3591
- returnTypes: args.returnTypes,
3592
- // Validation and workflow fields
3593
- validationCommands: args.validationCommands,
3594
- workingDirectory: args.workingDirectory,
3595
- outputDirectory: args.outputDirectory,
3596
- });
3597
- return formatWriteResponse(result, responseMode, 'Specification updated');
3598
- },
3599
- // ========================================================================
3600
2405
  // Implementation Session Operations
3601
2406
  // ========================================================================
3602
2407
  start_implementation_session: async (_client, args) => {
@@ -3615,33 +2420,6 @@ export function createToolHandlers(apiClient) {
3615
2420
  summary: args.summary,
3616
2421
  });
3617
2422
  },
3618
- // ========================================================================
3619
- // Bulk Operations
3620
- // ========================================================================
3621
- bulk_add_dependencies: async (_client, args) => {
3622
- validateRequired(args, 'dependencies');
3623
- if (!Array.isArray(args.dependencies) || args.dependencies.length === 0) {
3624
- throw new Error('dependencies array is required and must not be empty');
3625
- }
3626
- // Validate each dependency has required fields
3627
- const deps = args.dependencies;
3628
- for (let i = 0; i < deps.length; i++) {
3629
- if (!deps[i].ticketId || typeof deps[i].ticketId !== 'string') {
3630
- throw new Error(`dependencies[${i}].ticketId is required`);
3631
- }
3632
- if (!deps[i].dependsOnId || typeof deps[i].dependsOnId !== 'string') {
3633
- throw new Error(`dependencies[${i}].dependsOnId is required`);
3634
- }
3635
- if (deps[i].ticketId === deps[i].dependsOnId) {
3636
- throw new Error(`dependencies[${i}]: ticket cannot depend on itself`);
3637
- }
3638
- }
3639
- return await apiClient.call('bulk_add_dependencies', {
3640
- dependencies: args.dependencies,
3641
- skipCircularCheck: args.skipCircularCheck,
3642
- onError: args.onError,
3643
- });
3644
- },
3645
2423
  bulk_update_tickets: async (_client, args) => {
3646
2424
  if (!args.updates || !Array.isArray(args.updates) || args.updates.length === 0) {
3647
2425
  throw new Error('updates array is required and must not be empty');
@@ -3771,18 +2549,6 @@ export function createToolHandlers(apiClient) {
3771
2549
  // ========================================================================
3772
2550
  // Delete Operations
3773
2551
  // ========================================================================
3774
- delete_ticket: async (_client, args) => {
3775
- validateRequired(args, 'ticketId');
3776
- return await apiClient.call('delete_ticket', {
3777
- ticketId: args.ticketId,
3778
- });
3779
- },
3780
- delete_epic: async (_client, args) => {
3781
- validateRequired(args, 'epicId');
3782
- return await apiClient.call('delete_epic', {
3783
- epicId: args.epicId,
3784
- });
3785
- },
3786
2552
  delete_specification: async (_client, args) => {
3787
2553
  validateRequired(args, 'specificationId');
3788
2554
  return await apiClient.call('delete_specification', {
@@ -3832,15 +2598,6 @@ export function createToolHandlers(apiClient) {
3832
2598
  // ========================================================================
3833
2599
  // Review & Completion
3834
2600
  // ========================================================================
3835
- review_planning: async (_client, args) => {
3836
- const argsWithContext = injectContextRequired(args, ['specificationId']);
3837
- return await apiClient.call('review_planning', {
3838
- specificationId: argsWithContext.specificationId,
3839
- page: argsWithContext.page,
3840
- pageSize: argsWithContext.pageSize,
3841
- includeFullReport: argsWithContext.includeFullReport,
3842
- });
3843
- },
3844
2601
  review_implementation: async (_client, args) => {
3845
2602
  const argsWithContext = injectContextRequired(args, ['specificationId']);
3846
2603
  return await apiClient.call('review_implementation', {
@@ -3853,12 +2610,44 @@ export function createToolHandlers(apiClient) {
3853
2610
  specificationId: argsWithContext.specificationId,
3854
2611
  });
3855
2612
  },
2613
+ reopen_specification: async (_client, args) => {
2614
+ const argsWithContext = injectContextRequired(args, ['specificationId']);
2615
+ return await apiClient.call('reopen_specification', {
2616
+ specificationId: argsWithContext.specificationId,
2617
+ });
2618
+ },
3856
2619
  // ========================================================================
3857
2620
  // Agent Teams - Workspace Files (Local-only)
3858
2621
  // ========================================================================
3859
2622
  get_workspace_files: async (_client, args) => {
3860
2623
  return await getWorkspaceFiles(args);
3861
2624
  },
2625
+ // ========================================================================
2626
+ // Planning Session Operations
2627
+ // ========================================================================
2628
+ start_planning_session: async (_client, args) => {
2629
+ validateRequired(args, 'specificationId');
2630
+ return await apiClient.call('start_planning_session', {
2631
+ specificationId: args.specificationId,
2632
+ });
2633
+ },
2634
+ action_planning_session: async (_client, args) => {
2635
+ validateRequired(args, 'specificationId');
2636
+ if (!args.operation || typeof args.operation !== 'object') {
2637
+ throw new Error('Missing required argument: operation');
2638
+ }
2639
+ return await apiClient.call('action_planning_session', {
2640
+ specificationId: args.specificationId,
2641
+ operation: args.operation,
2642
+ responseDetail: args.responseDetail,
2643
+ });
2644
+ },
2645
+ complete_planning_session: async (_client, args) => {
2646
+ validateRequired(args, 'specificationId');
2647
+ return await apiClient.call('complete_planning_session', {
2648
+ specificationId: args.specificationId,
2649
+ });
2650
+ },
3862
2651
  };
3863
2652
  }
3864
2653
  /**