@specforge/canary-cli 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAML,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAQhC;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,IAAI,EAAE,CAumCjC;AAED;;GAEG;AACH,KAAK,WAAW,GAAG,CACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AA6EtB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,GACnB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA6S7B;AAiBD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,CAAC,CA4DlB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,GAAG,gBAAgB,CAAC,CAOrC;AAGD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAML,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAQhC;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,IAAI,EAAE,CAwlCjC;AAED;;GAEG;AACH,KAAK,WAAW,GAAG,CACjB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,OAAO,CAAC,CAAC;AA6EtB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,GACnB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAkT7B;AAiBD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,CAAC,CA4DlB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,GAAE,OAAe,GACrB,OAAO,CAAC,OAAO,GAAG,gBAAgB,CAAC,CAOrC;AAGD,OAAO,EACL,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC"}
@@ -24,19 +24,15 @@ function getTools() {
24
24
  properties: {
25
25
  type: {
26
26
  type: "string",
27
- enum: ["project", "specification", "epic", "ticket", "implementation_session"],
27
+ enum: ["project", "specification", "epic", "ticket", "blueprint"],
28
28
  description: "Entity type to retrieve"
29
29
  },
30
30
  id: {
31
31
  type: "string",
32
- description: "Entity ID (for project, specification, epic, ticket)"
33
- },
34
- specificationId: {
35
- type: "string",
36
- description: "Specification ID (for implementation_session)"
32
+ description: "Entity ID"
37
33
  }
38
34
  },
39
- required: ["type"]
35
+ required: ["type", "id"]
40
36
  }
41
37
  },
42
38
  {
@@ -47,7 +43,7 @@ function getTools() {
47
43
  properties: {
48
44
  type: {
49
45
  type: "string",
50
- enum: ["projects", "specifications", "epics", "tickets"],
46
+ enum: ["projects", "specifications", "epics", "tickets", "blueprints"],
51
47
  description: "Entity type to list"
52
48
  },
53
49
  projectId: {
@@ -120,14 +116,6 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
120
116
  },
121
117
  description: "Filter by complexity"
122
118
  },
123
- priority: {
124
- type: "array",
125
- items: {
126
- type: "string",
127
- enum: ["low", "medium", "high", "critical"]
128
- },
129
- description: "Filter by priority"
130
- },
131
119
  projectId: {
132
120
  type: "string",
133
121
  description: "Limit search to project"
@@ -147,38 +135,6 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
147
135
  offset: {
148
136
  type: "number",
149
137
  description: "Pagination offset (default: 0)"
150
- },
151
- fields: {
152
- type: "array",
153
- items: {
154
- type: "string",
155
- enum: [
156
- "id",
157
- "epicId",
158
- "ticketNumber",
159
- "title",
160
- "description",
161
- "status",
162
- "priority",
163
- "complexity",
164
- "estimatedHours",
165
- "actualHours",
166
- "acceptanceCriteria",
167
- "implementation",
168
- "technicalDetails",
169
- "notes",
170
- "tags",
171
- "blockReason",
172
- "progress",
173
- "testsPassed",
174
- "order",
175
- "startedAt",
176
- "completedAt",
177
- "createdAt",
178
- "updatedAt"
179
- ]
180
- },
181
- description: "Select specific fields to return. Returns all fields if not specified. id is always included."
182
138
  }
183
139
  }
184
140
  }
@@ -206,7 +162,7 @@ At least one scope filter (projectId, specificationId, or epicId) is required.`,
206
162
  },
207
163
  {
208
164
  name: "get_blocked_tickets",
209
- description: 'Get tickets with status "pending" and their statusReason explaining why they are blocked (unsatisfied dependencies or external block)',
165
+ description: 'Get tickets with status "pending", each with the `blockedBy` list of unsatisfied dependency tickets computed from the dependency tree.',
210
166
  inputSchema: {
211
167
  type: "object",
212
168
  properties: {
@@ -227,7 +183,6 @@ Report types:
227
183
  - 'time': Estimated vs actual hours (replaces get_time_report)
228
184
  - 'blockers': Blocked tickets with reasons (replaces get_blockers_report)
229
185
  - 'work': Completed work summary from WorkSession records (replaces get_work_summary)
230
- - 'implementation_analysis': Deeper implementation insights
231
186
  - 'sessions': Live planning/work/review sessions for a project (requires scope='project')
232
187
 
233
188
  Format options:
@@ -238,7 +193,7 @@ Format options:
238
193
  properties: {
239
194
  type: {
240
195
  type: "string",
241
- enum: ["implementation", "time", "blockers", "work", "implementation_analysis", "sessions"],
196
+ enum: ["implementation", "time", "blockers", "work", "sessions"],
242
197
  description: "Type of report to generate"
243
198
  },
244
199
  scope: {
@@ -257,6 +212,11 @@ Format options:
257
212
  endDate: {
258
213
  type: "string",
259
214
  description: "End date for work report (ISO 8601)"
215
+ },
216
+ format: {
217
+ type: "string",
218
+ enum: ["json", "summary"],
219
+ description: "Response format: 'json' (default) or 'summary'."
260
220
  }
261
221
  },
262
222
  required: ["type", "scope", "scopeId"]
@@ -267,23 +227,27 @@ Format options:
267
227
  // ========================================================================
268
228
  {
269
229
  name: "start_planning_session",
270
- description: "Start or resume a guided planning session for a specification. Project-scoped lock: only one active planning session per project (the project is derived from the spec \u2014 you do not pass it). Calling with the same spec resumes the existing session (idempotent). Calling with a different spec while one is active returns a rejection with the active session details. Planning is independent of implementation and review \u2014 they can run concurrently.",
230
+ description: "Start or resume a guided planning session for a specification. Project-scoped lock: only one active planning session per project. Calling with the same spec resumes the existing session (idempotent). Calling with a different spec while one is active returns a rejection with the active session details. Planning is independent of implementation and review \u2014 they can run concurrently.",
271
231
  inputSchema: {
272
232
  type: "object",
273
233
  properties: {
274
234
  specificationId: {
275
235
  type: "string",
276
- description: "The specification to plan. Optional \u2014 defaults to the active spec in the local config (.specforge/config.json), so you normally omit it. Do NOT pass projectId; it is derived from the spec."
236
+ description: "The specification to plan. Optional \u2014 defaults to the active spec in the local config (.specforge/config.json), so you normally omit it."
237
+ },
238
+ projectId: {
239
+ type: "string",
240
+ description: "The owning project. Optional \u2014 defaults to the active project in the local config (.specforge/config.json); injected automatically, so you normally omit it."
277
241
  }
278
242
  },
279
- // Nothing is required: specificationId falls back to local config, and the
280
- // returned sessionId is persisted + injected into subsequent calls.
243
+ // Nothing is required: specificationId/projectId fall back to local config, and
244
+ // the returned sessionId is persisted + injected into subsequent calls.
281
245
  required: []
282
246
  }
283
247
  },
284
248
  {
285
249
  name: "action_planning_session",
286
- description: "Execute a planning action within an active session. Wraps all planning operations (create/update/delete epics, tickets, dependencies, blueprints) plus get_planning_status (readiness X-ray, worst-first) with automatic status tracking. The operation.type IS the backend PlanningOperationName. 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. To read a single ticket, use the `get` tool (type:'ticket'). Use responseDetail to control verbosity: 'minimal' (~80 tokens) for rapid iteration, 'standard' (~200 tokens, default) for normal work, 'full' (~500 tokens) for debugging.",
250
+ description: "Execute a planning action within an active session. Wraps all planning operations (create/update/delete epics, tickets, dependencies, blueprints) plus get_planning_status (readiness X-ray, worst-first) with automatic status tracking. The operation.type IS the backend PlanningOperationName. 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. To read a single ticket, use the `get` tool (type:'ticket').",
287
251
  inputSchema: {
288
252
  type: "object",
289
253
  properties: {
@@ -297,17 +261,17 @@ Format options:
297
261
  "update_spec",
298
262
  "create_epic",
299
263
  "update_epic",
264
+ "delete_epic",
300
265
  "create_ticket",
301
266
  "update_ticket",
302
- "delete_epic",
303
267
  "delete_ticket",
304
- "create_dependencies",
305
- "delete_dependencies",
306
268
  "create_blueprint",
307
269
  "update_blueprint",
308
270
  "delete_blueprint",
309
271
  "link_blueprint_to_tickets",
310
272
  "unlink_blueprint_to_tickets",
273
+ "create_dependencies",
274
+ "delete_dependencies",
311
275
  "get_planning_status"
312
276
  ],
313
277
  description: "The planning operation to perform (lifecycle vocabulary). The type IS the backend PlanningOperationName; remaining fields are the operation payload."
@@ -322,15 +286,15 @@ Format options:
322
286
  },
323
287
  required: ["type", "fields"]
324
288
  },
289
+ // create_epic — SHELL only (epic_decomposition). Body fields are authored
290
+ // by update_epic in epic_expansion; only title/description/objective are
291
+ // persisted on create, so only those are advertised.
325
292
  {
326
293
  properties: {
327
294
  type: { const: "create_epic" },
328
295
  title: { type: "string", minLength: 1, description: "Epic title (non-empty)" },
329
296
  description: { type: "string", description: "What this epic delivers" },
330
- objective: { type: "string", description: "Goal achieved for the user" },
331
- goals: { type: "array", items: { type: "string" } },
332
- acceptanceCriteria: { type: "array", items: { type: "string" } },
333
- tickets: { type: "array", description: "Optional bulk-create tickets within the epic" }
297
+ objective: { type: "string", description: "Goal achieved for the user" }
334
298
  },
335
299
  required: ["type", "title"]
336
300
  },
@@ -345,26 +309,33 @@ Format options:
345
309
  title: { type: "string" },
346
310
  description: { type: "string" },
347
311
  objective: { type: "string", description: "Goal achieved for the user." },
348
- priority: { type: "string", enum: ["high", "medium", "low"] },
349
- goals: { type: "array", items: { type: "string" } },
350
- acceptanceCriteria: { type: "array", items: { type: "string" } }
312
+ architecture: { type: "string", description: "Structural approach specific to this epic." },
313
+ scope: { type: "object", description: "Epic scope.", properties: { inScope: { type: "array", items: { type: "string" } }, outOfScope: { type: "array", items: { type: "string" } }, assumptions: { type: "array", items: { type: "string" } }, externalDependencies: { type: "array", items: { type: "string" } } } },
314
+ goals: { type: "array", description: "Epic goals as objects (Epic.goals is a json object[], not string[]).", items: { type: "object", properties: { title: { type: "string" }, description: { type: "string" }, type: { type: "string", enum: ["business", "technical", "user", "operational"] }, successCriteria: { type: "array", items: { type: "string" } } }, required: ["title", "description"] } },
315
+ acceptanceCriteria: { type: "array", description: "BDD criteria objects (Epic.acceptanceCriteria is a json object[], not string[]).", items: { type: "object", properties: { given: { type: "string" }, when: { type: "string" }, then: { type: "string" } }, required: ["given", "when", "then"] } },
316
+ validationCommands: { type: "array", items: { type: "string" }, description: "Commands that verify this epic end-to-end." },
317
+ apiContracts: { type: "array", description: "API contracts this epic exposes.", items: { type: "object", properties: { id: { type: "string" }, name: { type: "string" }, type: { type: "string" }, description: { type: "string" } } } },
318
+ sharedPatterns: { type: "array", description: "Reusable patterns the epic's tickets should follow.", items: { type: "object" } },
319
+ fileStructures: { type: "array", description: "Concrete files this epic creates/modifies.", items: { type: "object", properties: { id: { type: "string" }, scope: { type: "string" }, description: { type: "string" }, content: { type: "string" } } } },
320
+ requirementsCovered: { type: "array", items: { type: "string" }, description: "Spec requirement ids this epic covers." },
321
+ nfrsCovered: { type: "array", items: { type: "string" }, description: "Spec NFR ids this epic covers." },
322
+ goalsCovered: { type: "array", items: { type: "string" }, description: "Spec goal ids this epic advances." }
351
323
  }
352
324
  }
353
325
  },
354
326
  required: ["type", "id", "fields"]
355
327
  },
328
+ // create_ticket — SHELL only (ticket_decomposition). Body fields
329
+ // (ticketType, complexity, acceptanceCriteria, implementationSteps, …)
330
+ // are authored by update_ticket in ticket_expansion; dependencies via
331
+ // create_dependencies in cross_validation. Only epicId/title/description
332
+ // are persisted on create, so only those are advertised.
356
333
  {
357
334
  properties: {
358
335
  type: { const: "create_ticket" },
359
336
  epicId: { type: "string", description: "Parent epic id" },
360
337
  title: { type: "string", minLength: 1, description: "Ticket title (non-empty)" },
361
- description: { type: "string" },
362
- ticketType: { type: "string", enum: ["implementation", "verification"], description: "Ticket type \u2014 implementation (default) or verification (tests/QA). Drives which fields the readiness rubric expects." },
363
- priority: { type: "string", enum: ["high", "medium", "low"] },
364
- complexity: { type: "string", enum: ["small", "medium", "large", "xlarge"] },
365
- acceptanceCriteria: { type: "array", items: { type: "string" } },
366
- implementationSteps: { type: "array", items: { type: "string" }, description: "Implementation steps; persisted as TicketImplementationStep rows" },
367
- dependsOn: { type: "array", items: { type: "string" }, description: "Other ticket ids this depends on; created post-insert" }
338
+ description: { type: "string" }
368
339
  },
369
340
  required: ["type", "epicId", "title"]
370
341
  },
@@ -388,7 +359,9 @@ Format options:
388
359
  filesToBeDeleted: { type: "array", items: { type: "string" } },
389
360
  filesToBeReferenced: { type: "array", items: { type: "string" } },
390
361
  guardrails: { type: "array", items: { type: "string" } },
391
- testSpecification: { type: "object", properties: { testTypes: { type: "array", items: { type: "string", enum: ["unit", "integration", "e2e", "typecheck", "lint", "build", "contract", "structural", "layout", "a11y", "performance"] } }, qualityGates: { type: "array", items: { type: "string" } }, testCommands: { type: "array", items: { type: "string" } }, coverageTarget: { type: "number", minimum: 0, maximum: 100 } } },
362
+ testSpecification: { type: "object", properties: { testTypes: { type: "array", items: { type: "string", enum: ["unit", "integration", "e2e", "typecheck", "lint", "build", "contract", "structural", "layout", "a11y", "performance"] } }, qualityGates: { type: "array", items: { type: "string" } }, testCommands: { type: "array", items: { type: "string" } }, coverageTarget: { type: "integer", minimum: 0, maximum: 100 } } },
363
+ codeReferences: { type: "array", description: "Existing code to reuse/anchor on.", items: { type: "object", properties: { filePath: { type: "string" }, symbol: { type: "string" }, description: { type: "string" } }, required: ["filePath"] } },
364
+ typeReferences: { type: "array", description: "Existing types to use.", items: { type: "object", properties: { filePath: { type: "string" }, typeName: { type: "string" }, description: { type: "string" } }, required: ["filePath", "typeName"] } },
392
365
  codeSnippets: { type: "array", items: { type: "object", properties: { language: { type: "string" }, content: { type: "string" }, description: { type: "string" } }, required: ["language", "content"] } },
393
366
  typeSnippets: { type: "array", items: { type: "object", properties: { language: { type: "string" }, content: { type: "string" }, description: { type: "string" } }, required: ["language", "content"] } },
394
367
  blueprintReferences: { type: "array", items: { type: "object", properties: { blueprintId: { type: "string" }, context: { type: "string" }, section: { type: "string" } }, required: ["blueprintId"] } },
@@ -401,14 +374,16 @@ Format options:
401
374
  {
402
375
  properties: {
403
376
  type: { const: "delete_epic" },
404
- id: { type: "string", description: "Epic id; cascades to all tickets in the epic." }
377
+ id: { type: "string", description: "Epic id; cascades to all tickets in the epic." },
378
+ cascadeRemoveDependencies: { type: "boolean", description: "Confirm removing dependency edges pointing at this epic's tickets from outside the epic. Required (true) when such referrers exist, else the delete is denied." }
405
379
  },
406
380
  required: ["type", "id"]
407
381
  },
408
382
  {
409
383
  properties: {
410
384
  type: { const: "delete_ticket" },
411
- id: { type: "string", description: "Ticket id (use list_tickets / lookup_ticket to find)." }
385
+ id: { type: "string", description: "Ticket id (use list_tickets / lookup_ticket to find)." },
386
+ cascadeRemoveDependencies: { type: "boolean", description: "Confirm removing dependency edges from other tickets that point at this ticket. Required (true) when such referrers exist, else the delete is denied." }
412
387
  },
413
388
  required: ["type", "id"]
414
389
  },
@@ -418,14 +393,13 @@ Format options:
418
393
  dependencies: {
419
394
  type: "array",
420
395
  minItems: 1,
421
- maxItems: 100,
422
- description: "Up to 100 dependency pairs. Valid pairs commit; malformed pairs come back in failed[] with a per-entry reason.",
396
+ maxItems: 5e3,
397
+ description: 'Up to 5000 dependency pairs, each a "requires" edge (fromTicketId depends on toTicketId). The batch is validated atomically: a cycle or an all-duplicate batch is rejected with guidance; already-existing edges are skipped.',
423
398
  items: {
424
399
  type: "object",
425
400
  properties: {
426
401
  fromTicketId: { type: "string", description: "The dependent ticket (this one depends on the other)." },
427
- toTicketId: { type: "string", description: "The blocker ticket it depends on." },
428
- type: { type: "string", enum: ["requires", "blocks"], description: 'Defaults to "requires"' }
402
+ toTicketId: { type: "string", description: "The blocker ticket it depends on." }
429
403
  },
430
404
  required: ["fromTicketId", "toTicketId"]
431
405
  }
@@ -444,9 +418,9 @@ Format options:
444
418
  properties: {
445
419
  type: { const: "create_blueprint" },
446
420
  title: { type: "string", minLength: 1, description: "Blueprint title (non-empty)" },
447
- content: { type: "string", description: "Body. Mermaid format extracts ```mermaid``` fences automatically." },
448
- format: { type: "string", description: 'Defaults to "mermaid"' },
449
- category: { type: "string", description: "Blueprint category (model enum, e.g. flowchart | architecture | sequence | data_model)." },
421
+ content: { type: "string", description: "Body \u2014 diagram source or markdown, persisted as-is on create." },
422
+ format: { type: "string", enum: ["markdown", "mermaid", "ascii", "mixed", "html", "svg", "image"], description: 'Defaults to "mermaid"' },
423
+ category: { type: "string", enum: ["flowchart", "architecture", "state", "sequence", "erd", "mockup", "adr", "component", "deployment", "api", "algorithm", "protocol", "glossary", "design_system"], description: "Blueprint category (SpecificationBlueprint.category model enum)." },
450
424
  description: { type: "string" },
451
425
  tags: { type: "array", items: { type: "string" } }
452
426
  },
@@ -481,9 +455,7 @@ Format options:
481
455
  properties: {
482
456
  type: { const: "link_blueprint_to_tickets" },
483
457
  blueprintId: { type: "string", description: "Blueprint to link." },
484
- ticketIds: { type: "array", minItems: 1, items: { type: "string" }, description: "Tickets to link the blueprint to." },
485
- context: { type: "string", description: "Optional context annotation" },
486
- section: { type: "string", description: "Optional section reference" }
458
+ ticketIds: { type: "array", minItems: 1, items: { type: "string" }, description: "Tickets to link the blueprint to." }
487
459
  },
488
460
  required: ["type", "blueprintId", "ticketIds"]
489
461
  },
@@ -498,17 +470,11 @@ Format options:
498
470
  {
499
471
  // Read-only poll/resume. To read a single ticket, use the `get` tool (type:'ticket').
500
472
  properties: {
501
- type: { const: "get_planning_status" },
502
- responseDetail: { type: "string", enum: ["minimal", "standard", "full"] }
473
+ type: { const: "get_planning_status" }
503
474
  },
504
475
  required: ["type"]
505
476
  }
506
477
  ]
507
- },
508
- responseDetail: {
509
- type: "string",
510
- enum: ["minimal", "standard", "full"],
511
- description: "Response detail level: minimal (~80 tokens), standard (~200, default), full (~500)"
512
478
  }
513
479
  },
514
480
  required: ["operation"]
@@ -574,7 +540,7 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
574
540
  properties: {
575
541
  index: {
576
542
  type: "number",
577
- description: "Zero-based index of the step in the implementation.steps array"
543
+ description: "Zero-based index of the step among the ticket's implementation steps (TicketImplementationStep rows, ordered by `order`)"
578
544
  },
579
545
  completed: {
580
546
  type: "boolean",
@@ -781,22 +747,22 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
781
747
  properties: {
782
748
  tests: {
783
749
  type: "string",
784
- enum: ["passed", "failed", "skipped", "na"],
750
+ enum: ["passed", "failed", "partial", "pending"],
785
751
  description: "Unit/integration test results"
786
752
  },
787
753
  lint: {
788
754
  type: "string",
789
- enum: ["passed", "failed", "skipped", "na"],
755
+ enum: ["passed", "failed", "partial", "pending"],
790
756
  description: "Linting results"
791
757
  },
792
758
  typeCheck: {
793
759
  type: "string",
794
- enum: ["passed", "failed", "skipped", "na"],
760
+ enum: ["passed", "failed", "partial", "pending"],
795
761
  description: "TypeScript type checking results"
796
762
  },
797
763
  build: {
798
764
  type: "string",
799
- enum: ["passed", "failed", "skipped", "na"],
765
+ enum: ["passed", "failed", "partial", "pending"],
800
766
  description: "Build/compilation results"
801
767
  },
802
768
  notes: {
@@ -860,9 +826,8 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
860
826
  title: { type: "string", description: "Ticket title" },
861
827
  description: { type: "string", description: "Ticket description" },
862
828
  ticketType: { type: "string", enum: ["implementation", "verification"], description: "Ticket type \u2014 defaults to implementation." },
863
- priority: { type: "string", enum: ["low", "medium", "high", "critical"] },
864
829
  complexity: { type: "string", enum: ["small", "medium", "large", "xlarge"] },
865
- estimatedHours: { type: "number" },
830
+ estimatedMinutes: { type: "integer", minimum: 0 },
866
831
  acceptanceCriteria: { type: "array", items: { type: "string" } },
867
832
  implementationSteps: { type: "array", items: { type: "string" }, description: "Implementation steps; persisted as TicketImplementationStep rows" },
868
833
  tags: { type: "array", items: { type: "string" } }
@@ -1123,6 +1088,23 @@ Set getTicket: true to fetch full ticket details in the response \u2014 useful f
1123
1088
  }
1124
1089
  }
1125
1090
  ];
1091
+ const IN_DEVELOPMENT_PLANNED_FOR = {
1092
+ start_work_session: "0.2.0",
1093
+ action_work_session: "0.2.0",
1094
+ complete_work_session: "0.2.0",
1095
+ reset_work_session: "0.2.0",
1096
+ start_review_session: "0.3.0",
1097
+ action_review_session: "0.3.0",
1098
+ complete_review_session: "0.3.0"
1099
+ };
1100
+ for (const t of tools) {
1101
+ const plannedFor = IN_DEVELOPMENT_PLANNED_FOR[t.name];
1102
+ if (plannedFor) {
1103
+ t.description = `**In development \u2014 ships with ${plannedFor}.** Calling returns a typed stub response the client should render as a "coming soon" affordance.
1104
+
1105
+ ${t.description}`;
1106
+ }
1107
+ }
1126
1108
  return tools;
1127
1109
  }
1128
1110
  const RETRY_CONFIG = {
@@ -1260,9 +1242,13 @@ function createToolHandlers(apiClient) {
1260
1242
  if (!specificationId) {
1261
1243
  throw new Error("No active specification. Run `specforge switch <spec-id>` or pass specificationId.");
1262
1244
  }
1245
+ const projectId = args.projectId ?? cfg?.projectId;
1246
+ if (!projectId) {
1247
+ throw new Error("No active project. Run `specforge switch <spec-id>` or pass projectId.");
1248
+ }
1263
1249
  const agentResponse = await callLocal(
1264
1250
  "start_planning_session",
1265
- { specificationId }
1251
+ { projectId, specificationId }
1266
1252
  );
1267
1253
  if (agentResponse?.sessionId) {
1268
1254
  saveProjectConfig({ planningSessionId: agentResponse.sessionId });
@@ -1390,7 +1376,6 @@ function createToolHandlers(apiClient) {
1390
1376
  fromTicketId: args.fromTicketId,
1391
1377
  epicId: args.epicId,
1392
1378
  allTickets: args.allTickets,
1393
- targetStatus: args.targetStatus,
1394
1379
  resetDependents: args.resetDependents,
1395
1380
  includeCompleted: args.includeCompleted,
1396
1381
  preserveNotes: args.preserveNotes,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tools/index.ts"],"sourcesContent":["/**\n * MCP Tools Registry\n *\n * This module defines and exports all available MCP tools.\n * 22 tools organized into: Queries, Lifecycle, Mutation, Utilities, Orchestration.\n */\n\nimport { ApiClient } from '../client/api-client.js';\nimport {\n ValidationError,\n ApiError,\n validateToolArgs,\n formatMCPError,\n transformError,\n MCPErrorResponse,\n} from '../validation/index.js';\nimport { injectContext, injectContextRequired } from './core/context-helper.js';\nimport { tryLoadProjectConfig, saveProjectConfig } from '../cli/config/index.js';\nimport {\n appendPlanningSessionRegistry,\n markPlanningSessionRegistryCompleted,\n} from '../cli/config/planning-sessions-registry.js';\n\n/**\n * Tool definition matching MCP protocol schema\n */\nexport interface Tool {\n name: string;\n description: string;\n inputSchema: {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\n/**\n * Get list of all available tools\n *\n * @returns Array of tool definitions (22 tools)\n */\nexport function getTools(): Tool[] {\n const tools: Tool[] = [\n // ========================================================================\n // Queries (6)\n // ========================================================================\n {\n name: 'get',\n description: 'Get a single entity by type and ID.',\n inputSchema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['project', 'specification', 'epic', 'ticket', 'implementation_session'],\n description: 'Entity type to retrieve',\n },\n id: {\n type: 'string',\n description: 'Entity ID (for project, specification, epic, ticket)',\n },\n specificationId: {\n type: 'string',\n description: 'Specification ID (for implementation_session)',\n },\n },\n required: ['type'],\n },\n },\n {\n name: 'list',\n description: 'List entities by type.',\n inputSchema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['projects', 'specifications', 'epics', 'tickets'],\n description: 'Entity type to list',\n },\n projectId: {\n type: 'string',\n description: 'Filter by project (for specifications)',\n },\n specificationId: {\n type: 'string',\n description: 'Filter by specification (for epics, tickets)',\n },\n epicId: {\n type: 'string',\n description: 'Filter by epic (for tickets)',\n },\n },\n required: ['type'],\n },\n },\n {\n name: 'search',\n description: `Unified ticket search with multiple filter options.\n\nCombines:\n- Full-text search (query)\n- File matching (files) - replaces find_tickets_by_file\n- Tag filtering (tags) - replaces find_tickets_by_tag\n- Related tickets (relatedTo) - replaces find_related_tickets\n- Status, complexity, priority filters\n\nAt least one of: query, files, tags, or relatedTo is required.\nAt least one scope filter (projectId, specificationId, or epicId) is required.`,\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Full-text search query',\n },\n files: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns to match ticket files (e.g., \"**/channel/*.ts\")',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Tags to filter by',\n },\n matchAllTags: {\n type: 'boolean',\n description: 'If true, match all tags (AND). If false, match any (OR). Default: false',\n },\n relatedTo: {\n type: 'string',\n description: 'Find tickets related to this ticket ID (by tags, files, tech stack)',\n },\n status: {\n type: 'array',\n items: {\n type: 'string',\n enum: ['pending', 'ready', 'active', 'done'],\n },\n description: 'Filter by status',\n },\n complexity: {\n type: 'array',\n items: {\n type: 'string',\n enum: ['small', 'medium', 'large', 'xlarge'],\n },\n description: 'Filter by complexity',\n },\n priority: {\n type: 'array',\n items: {\n type: 'string',\n enum: ['low', 'medium', 'high', 'critical'],\n },\n description: 'Filter by priority',\n },\n projectId: {\n type: 'string',\n description: 'Limit search to project',\n },\n specificationId: {\n type: 'string',\n description: 'Limit search to specification',\n },\n epicId: {\n type: 'string',\n description: 'Limit search to epic',\n },\n limit: {\n type: 'number',\n description: 'Maximum results (default: 20, max: 100)',\n },\n offset: {\n type: 'number',\n description: 'Pagination offset (default: 0)',\n },\n fields: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'id',\n 'epicId',\n 'ticketNumber',\n 'title',\n 'description',\n 'status',\n 'priority',\n 'complexity',\n 'estimatedHours',\n 'actualHours',\n 'acceptanceCriteria',\n 'implementation',\n 'technicalDetails',\n 'notes',\n 'tags',\n 'blockReason',\n 'progress',\n 'testsPassed',\n 'order',\n 'startedAt',\n 'completedAt',\n 'createdAt',\n 'updatedAt',\n ],\n },\n description:\n 'Select specific fields to return. Returns all fields if not specified. id is always included.',\n },\n },\n },\n },\n {\n name: 'get_next_actionable_tickets',\n description: 'Get tickets with status \"ready\" (all dependencies satisfied). Use start_work_session() to begin work on these tickets.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification (optional if projectId provided)',\n },\n projectId: {\n type: 'string',\n description: 'The ID of the project to get actionable tickets across all specifications',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of tickets to return (default: 5)',\n },\n },\n },\n },\n {\n name: 'get_blocked_tickets',\n description: 'Get tickets with status \"pending\" and their statusReason explaining why they are blocked (unsatisfied dependencies or external block)',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'get_report',\n description: `Generate unified reports for implementation, time tracking, blockers, work summary, or active sessions.\n\nReport types:\n- 'implementation': Progress, velocity, completions (replaces get_implementation_summary)\n- 'time': Estimated vs actual hours (replaces get_time_report)\n- 'blockers': Blocked tickets with reasons (replaces get_blockers_report)\n- 'work': Completed work summary from WorkSession records (replaces get_work_summary)\n- 'implementation_analysis': Deeper implementation insights\n- 'sessions': Live planning/work/review sessions for a project (requires scope='project')\n\nFormat options:\n- 'json': Full structured data (default)\n- 'summary': Condensed text summary`,\n inputSchema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['implementation', 'time', 'blockers', 'work', 'implementation_analysis', 'sessions'],\n description: 'Type of report to generate',\n },\n scope: {\n type: 'string',\n enum: ['project', 'specification', 'epic'],\n description: \"Scope of the report. 'sessions' requires scope='project'.\",\n },\n scopeId: {\n type: 'string',\n description: 'ID of the scoped entity (projectId, specificationId, or epicId)',\n },\n startDate: {\n type: 'string',\n description: 'Start date for work report (ISO 8601)',\n },\n endDate: {\n type: 'string',\n description: 'End date for work report (ISO 8601)',\n },\n },\n required: ['type', 'scope', 'scopeId'],\n },\n },\n\n // ========================================================================\n // Lifecycle (10)\n // ========================================================================\n {\n name: 'start_planning_session',\n description: 'Start or resume a guided planning session for a specification. Project-scoped lock: only one active planning session per project (the project is derived from the spec — you do not pass it). Calling with the same spec resumes the existing session (idempotent). Calling with a different spec while one is active returns a rejection with the active session details. Planning is independent of implementation and review — they can run concurrently.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The specification to plan. Optional — defaults to the active spec in the local config (.specforge/config.json), so you normally omit it. Do NOT pass projectId; it is derived from the spec.',\n },\n },\n // Nothing is required: specificationId falls back to local config, and the\n // returned sessionId is persisted + injected into subsequent calls.\n required: [],\n },\n },\n {\n name: 'action_planning_session',\n description: \"Execute a planning action within an active session. Wraps all planning operations (create/update/delete epics, tickets, dependencies, blueprints) plus get_planning_status (readiness X-ray, worst-first) with automatic status tracking. The operation.type IS the backend PlanningOperationName. 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. To read a single ticket, use the `get` tool (type:'ticket'). Use responseDetail to control verbosity: 'minimal' (~80 tokens) for rapid iteration, 'standard' (~200 tokens, default) for normal work, 'full' (~500 tokens) for debugging.\",\n inputSchema: {\n type: 'object',\n properties: {\n operation: {\n type: 'object',\n description: 'The operation to perform. Must include a \"type\" field. Per-op required fields are declared in `oneOf` below — agents should consult their own tool schema parser for the exact shape per type. Do NOT pass sessionId/projectId/specificationId: the active planning session is injected from local config.',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'update_spec',\n 'create_epic',\n 'update_epic',\n 'create_ticket',\n 'update_ticket',\n 'delete_epic',\n 'delete_ticket',\n 'create_dependencies',\n 'delete_dependencies',\n 'create_blueprint',\n 'update_blueprint',\n 'delete_blueprint',\n 'link_blueprint_to_tickets',\n 'unlink_blueprint_to_tickets',\n 'get_planning_status',\n ],\n description: 'The planning operation to perform (lifecycle vocabulary). The type IS the backend PlanningOperationName; remaining fields are the operation payload.',\n },\n },\n required: ['type'],\n oneOf: [\n {\n properties: {\n type: { const: 'update_spec' },\n fields: { type: 'object', description: 'Partial spec update — only the keys you send are changed (e.g. background, goals, nonGoals, constraints, successCriteria).' },\n },\n required: ['type', 'fields'],\n },\n {\n properties: {\n type: { const: 'create_epic' },\n title: { type: 'string', minLength: 1, description: 'Epic title (non-empty)' },\n description: { type: 'string', description: 'What this epic delivers' },\n objective: { type: 'string', description: 'Goal achieved for the user' },\n goals: { type: 'array', items: { type: 'string' } },\n acceptanceCriteria: { type: 'array', items: { type: 'string' } },\n tickets: { type: 'array', description: 'Optional bulk-create tickets within the epic' },\n },\n required: ['type', 'title'],\n },\n {\n properties: {\n type: { const: 'update_epic' },\n id: { type: 'string', description: 'Epic id (use list_epics / lookup_epic to find).' },\n fields: {\n type: 'object',\n description: 'Partial epic update — only the keys you send are changed.',\n properties: {\n title: { type: 'string' },\n description: { type: 'string' },\n objective: { type: 'string', description: 'Goal achieved for the user.' },\n priority: { type: 'string', enum: ['high', 'medium', 'low'] },\n goals: { type: 'array', items: { type: 'string' } },\n acceptanceCriteria: { type: 'array', items: { type: 'string' } },\n },\n },\n },\n required: ['type', 'id', 'fields'],\n },\n {\n properties: {\n type: { const: 'create_ticket' },\n epicId: { type: 'string', description: 'Parent epic id' },\n title: { type: 'string', minLength: 1, description: 'Ticket title (non-empty)' },\n description: { type: 'string' },\n ticketType: { type: 'string', enum: ['implementation', 'verification'], description: 'Ticket type — implementation (default) or verification (tests/QA). Drives which fields the readiness rubric expects.' },\n priority: { type: 'string', enum: ['high', 'medium', 'low'] },\n complexity: { type: 'string', enum: ['small', 'medium', 'large', 'xlarge'] },\n acceptanceCriteria: { type: 'array', items: { type: 'string' } },\n implementationSteps: { type: 'array', items: { type: 'string' }, description: 'Implementation steps; persisted as TicketImplementationStep rows' },\n dependsOn: { type: 'array', items: { type: 'string' }, description: 'Other ticket ids this depends on; created post-insert' },\n },\n required: ['type', 'epicId', 'title'],\n },\n {\n properties: {\n type: { const: 'update_ticket' },\n id: { type: 'string', description: 'Ticket id (use list_tickets / lookup_ticket to find).' },\n fields: {\n type: 'object',\n description: 'Partial ticket update — only the keys you send are changed. Child-backed arrays (acceptanceCriteria, implementationSteps, filesToBe*, testSpecification.testTypes, blueprintReferences, codeSnippets, typeSnippets) replace the whole set.',\n properties: {\n title: { type: 'string' },\n description: { type: 'string' },\n ticketType: { type: 'string', enum: ['implementation', 'verification'] },\n complexity: { type: 'string', enum: ['small', 'medium', 'large', 'xlarge'] },\n estimatedMinutes: { type: 'integer', minimum: 0 },\n acceptanceCriteria: { type: 'array', items: { type: 'object', properties: { given: { type: 'string' }, when: { type: 'string' }, then: { type: 'string' } }, required: ['given', 'when', 'then'] } },\n implementationSteps: { type: 'array', items: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] } },\n filesToBeCreated: { type: 'array', items: { type: 'string' } },\n filesToBeModified: { type: 'array', items: { type: 'string' } },\n filesToBeDeleted: { type: 'array', items: { type: 'string' } },\n filesToBeReferenced: { type: 'array', items: { type: 'string' } },\n guardrails: { type: 'array', items: { type: 'string' } },\n testSpecification: { type: 'object', properties: { testTypes: { type: 'array', items: { type: 'string', enum: ['unit', 'integration', 'e2e', 'typecheck', 'lint', 'build', 'contract', 'structural', 'layout', 'a11y', 'performance'] } }, qualityGates: { type: 'array', items: { type: 'string' } }, testCommands: { type: 'array', items: { type: 'string' } }, coverageTarget: { type: 'number', minimum: 0, maximum: 100 } } },\n codeSnippets: { type: 'array', items: { type: 'object', properties: { language: { type: 'string' }, content: { type: 'string' }, description: { type: 'string' } }, required: ['language', 'content'] } },\n typeSnippets: { type: 'array', items: { type: 'object', properties: { language: { type: 'string' }, content: { type: 'string' }, description: { type: 'string' } }, required: ['language', 'content'] } },\n blueprintReferences: { type: 'array', items: { type: 'object', properties: { blueprintId: { type: 'string' }, context: { type: 'string' }, section: { type: 'string' } }, required: ['blueprintId'] } },\n tags: { type: 'array', items: { type: 'string' } },\n },\n },\n },\n required: ['type', 'id', 'fields'],\n },\n {\n properties: {\n type: { const: 'delete_epic' },\n id: { type: 'string', description: 'Epic id; cascades to all tickets in the epic.' },\n },\n required: ['type', 'id'],\n },\n {\n properties: {\n type: { const: 'delete_ticket' },\n id: { type: 'string', description: 'Ticket id (use list_tickets / lookup_ticket to find).' },\n },\n required: ['type', 'id'],\n },\n {\n properties: {\n type: { const: 'create_dependencies' },\n dependencies: {\n type: 'array',\n minItems: 1,\n maxItems: 100,\n description: 'Up to 100 dependency pairs. Valid pairs commit; malformed pairs come back in failed[] with a per-entry reason.',\n items: {\n type: 'object',\n properties: {\n fromTicketId: { type: 'string', description: 'The dependent ticket (this one depends on the other).' },\n toTicketId: { type: 'string', description: 'The blocker ticket it depends on.' },\n type: { type: 'string', enum: ['requires', 'blocks'], description: 'Defaults to \"requires\"' },\n },\n required: ['fromTicketId', 'toTicketId'],\n },\n },\n },\n required: ['type', 'dependencies'],\n },\n {\n properties: {\n type: { const: 'delete_dependencies' },\n dependencyIds: { type: 'array', minItems: 1, items: { type: 'string' }, description: 'TicketDependency ids to remove (use lookup/list to find).' },\n },\n required: ['type', 'dependencyIds'],\n },\n {\n properties: {\n type: { const: 'create_blueprint' },\n title: { type: 'string', minLength: 1, description: 'Blueprint title (non-empty)' },\n content: { type: 'string', description: 'Body. Mermaid format extracts ```mermaid``` fences automatically.' },\n format: { type: 'string', description: 'Defaults to \"mermaid\"' },\n category: { type: 'string', description: 'Blueprint category (model enum, e.g. flowchart | architecture | sequence | data_model).' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n },\n required: ['type', 'title', 'category'],\n },\n {\n properties: {\n type: { const: 'update_blueprint' },\n id: { type: 'string', description: 'Blueprint id.' },\n fields: {\n type: 'object',\n description: 'Partial blueprint update — only the keys you send are changed.',\n properties: {\n title: { type: 'string' },\n content: { type: 'string' },\n category: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n },\n },\n },\n required: ['type', 'id', 'fields'],\n },\n {\n properties: {\n type: { const: 'delete_blueprint' },\n id: { type: 'string', description: 'Blueprint id.' },\n },\n required: ['type', 'id'],\n },\n {\n properties: {\n type: { const: 'link_blueprint_to_tickets' },\n blueprintId: { type: 'string', description: 'Blueprint to link.' },\n ticketIds: { type: 'array', minItems: 1, items: { type: 'string' }, description: 'Tickets to link the blueprint to.' },\n context: { type: 'string', description: 'Optional context annotation' },\n section: { type: 'string', description: 'Optional section reference' },\n },\n required: ['type', 'blueprintId', 'ticketIds'],\n },\n {\n properties: {\n type: { const: 'unlink_blueprint_to_tickets' },\n blueprintId: { type: 'string', description: 'Blueprint to unlink.' },\n ticketIds: { type: 'array', minItems: 1, items: { type: 'string' }, description: 'Tickets to unlink the blueprint from.' },\n },\n required: ['type', 'blueprintId', 'ticketIds'],\n },\n {\n // Read-only poll/resume. To read a single ticket, use the `get` tool (type:'ticket').\n properties: {\n type: { const: 'get_planning_status' },\n responseDetail: { type: 'string', enum: ['minimal', 'standard', 'full'] },\n },\n required: ['type'],\n },\n ],\n },\n responseDetail: {\n type: 'string',\n enum: ['minimal', 'standard', 'full'],\n description: 'Response detail level: minimal (~80 tokens), standard (~200, default), full (~500)',\n },\n },\n required: ['operation'],\n },\n },\n {\n name: 'complete_planning_session',\n description: \"Complete the planning session and submit the spec for final review. Spec must be in 'planning' status. Runs the planning gate (consistency checks + readinessThreshold from project/spec settings). Transitions the spec directly to 'ready' on pass. Takes no arguments — the active planning session is injected from local config.\",\n inputSchema: {\n type: 'object',\n // No inputs: the active planning session (sessionId) is injected from\n // local config (.specforge/config.json). Do NOT pass sessionId/projectId/specificationId.\n properties: {},\n required: [],\n },\n },\n {\n name: 'start_work_session',\n 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.',\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket to start',\n },\n },\n required: ['ticketId'],\n },\n },\n {\n name: 'action_work_session',\n description: `Update checklist state during an active WorkSession. Combines step completion, AC validation, test result reporting, file tracking, reference review confirmation, and discovery reporting into a single atomic operation. All state changes are recorded on the WorkSession and its related validation/completion records.\n\nUse this instead of calling update_ticket for checklist changes. Provides:\n- Step completion (individual or bulk via WorkSessionStepCompletion)\n- Acceptance criteria validation (individual or bulk via WorkSessionACValidation)\n- Test result reporting (merged by test type via WorkSessionTestResult)\n- File tracking (created, modified, deleted on WorkSession)\n- Discovery reporting (create discoveries for blockers, bugs, tech debt)\n- Blocker management (set block reason; requires existing discovery)\n- Reference review tracking (codeSnippetsReviewed, typeReferencesReviewed)\n- Auto-calculated progress percentage\n- Completion readiness hints\n\nIMPORTANT: 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.\n\nIf the ticket has codeReferences or typeReferences, set codeSnippetsReviewed/typeReferencesReviewed to true after reviewing them — completion readiness will block until these are confirmed.\n\nSet 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.`,\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket being worked on (must be in active status)',\n },\n steps: {\n type: 'array',\n description: 'Individual step completion updates',\n items: {\n type: 'object',\n properties: {\n index: {\n type: 'number',\n description: 'Zero-based index of the step in the implementation.steps array',\n },\n completed: {\n type: 'boolean',\n description: 'Whether the step is completed',\n },\n notes: {\n type: 'string',\n description: 'Optional note about this step',\n },\n },\n required: ['index', 'completed'],\n },\n },\n allStepsDone: {\n type: 'boolean',\n description: 'Shortcut: mark all steps as completed',\n },\n acceptanceCriteria: {\n type: 'array',\n description: 'Individual AC validation updates',\n items: {\n type: 'object',\n properties: {\n index: {\n type: 'number',\n description: 'Zero-based index of the AC in the acceptanceCriteria array',\n },\n validated: {\n type: 'boolean',\n description: 'Whether the AC is validated',\n },\n notes: {\n type: 'string',\n description: 'Optional note about this AC',\n },\n },\n required: ['index', 'validated'],\n },\n },\n allACValidated: {\n type: 'boolean',\n description: 'Shortcut: mark all acceptance criteria as validated',\n },\n testResults: {\n type: 'array',\n description: 'Test result reports to append (merged by testType)',\n items: {\n type: 'object',\n properties: {\n testType: {\n type: 'string',\n description: 'Type of test (e.g., \"unit\", \"integration\", \"e2e\", \"lint\", \"typeCheck\")',\n },\n passed: {\n type: 'number',\n description: 'Number of tests that passed',\n },\n failed: {\n type: 'number',\n description: 'Number of tests that failed',\n },\n skipped: {\n type: 'number',\n description: 'Number of tests skipped',\n },\n command: {\n type: 'string',\n description: 'Command used to run the tests',\n },\n output: {\n type: 'string',\n description: 'Test output (truncated if needed)',\n },\n duration: {\n type: 'number',\n description: 'Duration in milliseconds',\n },\n suites: {\n type: 'array',\n description: 'Optional suite-level breakdown',\n items: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Suite name' },\n passed: { type: 'number', description: 'Passed tests in suite' },\n failed: { type: 'number', description: 'Failed tests in suite' },\n skipped: { type: 'number', description: 'Skipped tests in suite' },\n duration: { type: 'number', description: 'Suite duration in ms' },\n },\n required: ['name', 'passed', 'failed'],\n },\n },\n tests: {\n type: 'array',\n description: 'Optional individual test breakdown',\n items: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Test name' },\n suite: { type: 'string', description: 'Parent suite name' },\n status: { type: 'string', enum: ['passed', 'failed', 'skipped'], description: 'Test result' },\n duration: { type: 'number', description: 'Test duration in ms' },\n },\n required: ['name', 'status'],\n },\n },\n },\n required: ['testType', 'passed', 'failed'],\n },\n },\n notes: {\n type: 'string',\n description: 'Additional notes to append to the ticket',\n },\n filesCreated: {\n type: 'array',\n items: { type: 'string' },\n description: 'Files created during this session. Accumulated incrementally.',\n },\n filesModified: {\n type: 'array',\n items: { type: 'string' },\n description: 'Files modified during this session. Accumulated incrementally.',\n },\n filesDeleted: {\n type: 'array',\n items: { type: 'string' },\n description: 'Files deleted during this session. Accumulated incrementally.',\n },\n discovery: {\n type: 'object',\n description: 'Create a discovery (observation about the implementation). Use this to report blockers, bugs, tech debt, scope changes, etc.',\n properties: {\n description: { type: 'string', description: 'Description of the discovery' },\n type: { type: 'string', description: 'Discovery type: bug, tech_debt, blocker, clarification, scope_change, dependency, risk, ticket, epic' },\n severity: { type: 'string', description: 'Severity: blocker, critical, major, minor' },\n suggestedTitle: { type: 'string', description: 'Suggested title for the new ticket/epic' },\n suggestedPriority: { type: 'string', description: 'Suggested priority: high, medium, low' },\n relatedFiles: { type: 'array', items: { type: 'string' }, description: 'Related file paths' },\n notes: { type: 'string', description: 'Additional notes' },\n },\n required: ['description'],\n },\n blockReason: {\n type: 'string',\n description: 'Set a blocker on this ticket. Requires an existing discovery (create via discovery parameter first).',\n },\n getTicket: {\n type: 'boolean',\n description: 'Fetch full ticket details. Can be the sole operation or combined with other actions.',\n },\n includeFullContext: {\n type: 'boolean',\n description: 'Include full implementation context in response',\n },\n codeSnippetsReviewed: {\n type: 'boolean',\n description: 'Confirm that code snippets (codeReferences) on the ticket have been reviewed. Required before completion when the ticket has non-empty codeReferences.',\n },\n typeReferencesReviewed: {\n type: 'boolean',\n description: 'Confirm that type references (typeReferences) on the ticket have been reviewed. Required before completion when the ticket has non-empty typeReferences.',\n },\n },\n required: ['ticketId'],\n },\n },\n {\n name: 'complete_work_session',\n description:\n 'Mark a ticket as complete and finalize the active WorkSession. Transitions active -> done. Session data (files, test results, time) is stored on the WorkSession record.\\n\\n' +\n 'All acceptance criteria must be validated and all implementation steps must be completed via action_work_session before calling this. The completion gate enforces this — shortcuts are not available.\\n\\n' +\n 'Automatically recalculates status for dependent tickets and returns cascade info.\\n\\n' +\n 'Optional validation flags can be provided to report test results inline:\\n' +\n '- tests: Unit/integration test results\\n' +\n '- lint: Linting results\\n' +\n '- typeCheck: TypeScript type checking\\n' +\n '- build: Build/compilation results',\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket',\n },\n summary: {\n type: 'string',\n description: 'Summary of work completed',\n },\n filesModified: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of files modified',\n },\n filesCreated: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of files created',\n },\n filesDeleted: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of files deleted',\n },\n actualHours: {\n type: 'number',\n description: 'Actual hours spent on the ticket',\n },\n validation: {\n type: 'object',\n description: 'Detailed validation flags for reporting test/lint/build results',\n properties: {\n tests: {\n type: 'string',\n enum: ['passed', 'failed', 'skipped', 'na'],\n description: 'Unit/integration test results',\n },\n lint: {\n type: 'string',\n enum: ['passed', 'failed', 'skipped', 'na'],\n description: 'Linting results',\n },\n typeCheck: {\n type: 'string',\n enum: ['passed', 'failed', 'skipped', 'na'],\n description: 'TypeScript type checking results',\n },\n build: {\n type: 'string',\n enum: ['passed', 'failed', 'skipped', 'na'],\n description: 'Build/compilation results',\n },\n notes: {\n type: 'string',\n description: 'Additional validation notes',\n },\n },\n },\n },\n required: ['ticketId', 'summary'],\n },\n },\n {\n name: 'start_review_session',\n description: 'Start the implementation review lifecycle. Runs the implementation gate and either auto-transitions to \"reviewed\" (on pass) or transitions to \"in_review\" with an active ReviewSession (on fail). Creates correction tickets via action_review_session, then call complete_review_session.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification to review (must be in ready_for_review status)',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'action_review_session',\n description: 'Address findings in an active review session. Create correction tickets inline or dismiss findings with justification. Only available when specification is in \"in_review\" status.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification',\n },\n reviewSessionId: {\n type: 'string',\n description: 'The review session ID (auto-detected if omitted)',\n },\n findingsAddressed: {\n type: 'array',\n description: 'Findings to address in this action',\n items: {\n type: 'object',\n properties: {\n findingId: {\n type: 'string',\n description: 'The finding ID to address',\n },\n action: {\n type: 'string',\n enum: ['correction_ticket', 'dismissed'],\n description: 'How to address the finding',\n },\n correctionTicket: {\n type: 'object',\n description: 'Inline ticket creation params (required for correction_ticket action)',\n properties: {\n epicId: { type: 'string', description: 'Epic to add the correction ticket to' },\n title: { type: 'string', description: 'Ticket title' },\n description: { type: 'string', description: 'Ticket description' },\n ticketType: { type: 'string', enum: ['implementation', 'verification'], description: 'Ticket type — defaults to implementation.' },\n priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },\n complexity: { type: 'string', enum: ['small', 'medium', 'large', 'xlarge'] },\n estimatedHours: { type: 'number' },\n acceptanceCriteria: { type: 'array', items: { type: 'string' } },\n implementationSteps: { type: 'array', items: { type: 'string' }, description: 'Implementation steps; persisted as TicketImplementationStep rows' },\n tags: { type: 'array', items: { type: 'string' } },\n },\n required: ['epicId', 'title'],\n },\n justification: {\n type: 'string',\n description: 'Required justification when action is \"dismissed\"',\n },\n },\n required: ['findingId', 'action'],\n },\n },\n notes: {\n type: 'string',\n description: 'Optional notes for this review action',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'complete_review_session',\n description: 'Complete an active review session. All error-severity findings must be addressed. If correction tickets exist, transitions to \"in_progress\". If all findings dismissed, triggers user confirmation flow.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification',\n },\n reviewSessionId: {\n type: 'string',\n description: 'The review session ID (auto-detected if omitted)',\n },\n summary: {\n type: 'string',\n description: 'Optional completion summary',\n },\n confirmAllDismissed: {\n type: 'boolean',\n description: 'Set to true when all findings were dismissed to trigger user confirmation flow',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'reopen_specification',\n description: 'Reopen a specification in \"ready\" status, regressing to \"planning\". After reopening, call start_planning_session to begin a new planning session.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification to reopen',\n },\n },\n required: ['specificationId'],\n },\n },\n\n // Spec creation is a HUMAN bootstrap step, NOT an agent MCP tool: specs are\n // created via `specforge init` (cli-rest surface), which also writes the new\n // spec id into the local config so the agent's per-call injection finds it.\n // The agent assumes the spec already exists and starts from\n // `start_planning_session`. (Backend keeps `create_specification` REST-only;\n // it was never dispatchable on /local.)\n\n // ========================================================================\n // Utilities (3)\n // ========================================================================\n {\n name: 'feedback',\n description: `Submit and manage feedback about MCP tools. Operations:\n- submit: Submit new feedback (requires category, summary)\n- list: List recent feedback entries\n- get: Get a specific feedback entry by ID`,\n inputSchema: {\n type: 'object',\n properties: {\n operation: {\n type: 'string',\n enum: ['submit', 'list', 'get'],\n description: 'The operation to perform',\n },\n // For submit operation\n category: {\n type: 'string',\n enum: ['bug', 'feature_request', 'usability', 'documentation', 'performance'],\n description: 'Feedback category (required for submit)',\n },\n summary: {\n type: 'string',\n description: 'Brief summary of the feedback (required for submit)',\n },\n severity: {\n type: 'string',\n enum: ['critical', 'high', 'medium', 'low'],\n description: 'Severity level (default: medium)',\n },\n tool: {\n type: 'string',\n description: 'Which MCP tool this relates to',\n },\n toolOperation: {\n type: 'string',\n description: 'Specific operation within the tool',\n },\n details: {\n type: 'string',\n description: 'Extended description',\n },\n expected: {\n type: 'string',\n description: 'Expected behavior',\n },\n actual: {\n type: 'string',\n description: 'Actual behavior',\n },\n errorMessage: {\n type: 'string',\n description: 'Error message if reporting a bug',\n },\n ticketId: {\n type: 'string',\n description: 'Related ticket ID',\n },\n // For list operation\n limit: {\n type: 'number',\n description: 'Maximum entries to return (default: 10)',\n },\n categoryFilter: {\n type: 'string',\n enum: ['bug', 'feature_request', 'usability', 'documentation', 'performance'],\n description: 'Filter by category',\n },\n // For get operation\n feedbackId: {\n type: 'string',\n description: 'Feedback ID to retrieve (required for get)',\n },\n },\n required: ['operation'],\n },\n },\n {\n name: 'reset_work_session',\n description: 'Reset tickets to pending/ready status (calculated from dependencies). Returns statusCalculation showing how many became pending vs ready.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The specification containing the tickets',\n },\n ticketIds: {\n type: 'array',\n items: { type: 'string' },\n description: 'Specific ticket IDs to reset',\n },\n fromTicketId: {\n type: 'string',\n description: 'Reset this ticket and all its dependents',\n },\n epicId: {\n type: 'string',\n description: 'Reset all tickets in this epic',\n },\n allTickets: {\n type: 'boolean',\n description: 'Reset all tickets in the specification',\n },\n resetDependents: {\n type: 'boolean',\n description: 'Also reset tickets that depend on the specified tickets (default: false)',\n },\n includeCompleted: {\n type: 'boolean',\n description: 'Include tickets with done status in the reset (default: false)',\n },\n preserveNotes: {\n type: 'boolean',\n description: 'Keep existing notes on tickets (default: true)',\n },\n clearTestResults: {\n type: 'boolean',\n description: 'Clear test result history (default: false)',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'link_pull_request',\n description: 'Associate a pull request with a ticket',\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket',\n },\n prNumber: {\n type: 'number',\n description: 'PR number (provide this or prUrl)',\n },\n prUrl: {\n type: 'string',\n description: 'Full PR URL (GitHub, GitLab, or Bitbucket)',\n },\n title: {\n type: 'string',\n description: 'PR title',\n },\n author: {\n type: 'string',\n description: 'PR author',\n },\n repoUrl: {\n type: 'string',\n description: 'Repository URL (required if using prNumber)',\n },\n },\n required: ['ticketId'],\n },\n },\n\n // ========================================================================\n // Orchestration (2)\n // ========================================================================\n {\n name: 'get_critical_path',\n description: 'Get the critical execution path for a specification.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'Specification ID',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'get_dependency_tree',\n description: 'Get the full dependency tree for a specification.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'Specification ID',\n },\n },\n required: ['specificationId'],\n },\n },\n ];\n\n return tools;\n}\n\n/**\n * Tool handler type - processes arguments and returns a result\n */\ntype ToolHandler = (\n apiClient: ApiClient,\n args: Record<string, unknown>\n) => Promise<unknown>;\n\n/**\n * Retry configuration for transient failures\n */\nconst RETRY_CONFIG = {\n maxRetries: 3,\n initialDelayMs: 500,\n maxDelayMs: 5000,\n backoffMultiplier: 2,\n};\n\n/**\n * Transient error patterns that should trigger retry\n */\nconst TRANSIENT_ERROR_PATTERNS = [\n /ETIMEDOUT/i,\n /ECONNRESET/i,\n /ECONNREFUSED/i,\n /socket hang up/i,\n /network error/i,\n /too many requests/i,\n /rate limit/i,\n /5\\d{2}/, // 5xx status codes\n];\n\n/**\n * Check if an error is transient and should be retried\n */\nfunction isTransientError(error: Error): boolean {\n return TRANSIENT_ERROR_PATTERNS.some(pattern =>\n pattern.test(error.message)\n );\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Execute a function with retry logic for transient failures\n */\nasync function withRetry<T>(\n fn: () => Promise<T>,\n toolName: string,\n debug: boolean\n): Promise<T> {\n let lastError: Error | null = null;\n let delay = RETRY_CONFIG.initialDelayMs;\n\n for (let attempt = 1; attempt <= RETRY_CONFIG.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt < RETRY_CONFIG.maxRetries && isTransientError(lastError)) {\n if (debug) {\n console.error(\n `[DEBUG] Tool ${toolName} attempt ${attempt} failed with transient error, retrying in ${delay}ms:`,\n lastError.message\n );\n }\n await sleep(delay);\n delay = Math.min(delay * RETRY_CONFIG.backoffMultiplier, RETRY_CONFIG.maxDelayMs);\n } else {\n break;\n }\n }\n }\n\n throw lastError;\n}\n\n/**\n * Create tool handlers that call the API with proper request formatting\n *\n * @param apiClient - The API client to use for making requests\n * @returns Record of tool handlers keyed by tool name\n */\nexport function createToolHandlers(\n apiClient: ApiClient\n): Record<string, ToolHandler> {\n // Agent `/local` path (M9, approach A): the transport returns the raw M8 body;\n // interpret the envelope here. Lifecycle → unwrap to `agentResponse`; standard\n // error → throw the composed guidance prose (M9.3); raw success → pass through.\n const callLocal = async <T = unknown>(\n op: string,\n args: Record<string, unknown>,\n ): Promise<T> => {\n const body = await apiClient.getTransport().execute<Record<string, unknown>>(op, args);\n if (body && typeof body === 'object') {\n if (body.kind === 'standard_error') {\n // M9.3: the error-guidance composer's `guidance.prose` is the canonical\n // agent-facing message (same verbatim convention as lifecycle guidance);\n // surface it for query-tool errors, falling back to `message` (and to a\n // generic line for INTERNAL, where guidance is always null).\n const guidance = body.guidance as { prose?: unknown } | null | undefined;\n const prose = guidance && typeof guidance.prose === 'string' ? guidance.prose : undefined;\n throw new Error(\n prose ?? (typeof body.message === 'string' ? body.message : `Operation failed: ${op}`),\n );\n }\n if (body.kind === 'lifecycle' && 'agentResponse' in body) {\n return body.agentResponse as T;\n }\n }\n return body as T;\n };\n\n return {\n // ========================================================================\n // Queries — forward the canonical super-tools straight through (the backend\n // owns the `type` dispatch; M9 dropped the old granular-op fan-out).\n // ========================================================================\n get: async (_client, args) => {\n if (!args.type) throw new Error('Missing required argument: type');\n // Project/spec ids inject from config when the agent omits them.\n const withCtx = injectContext(args, ['projectId', 'specificationId']);\n return await callLocal('get', withCtx);\n },\n\n list: async (_client, args) => {\n if (!args.type) throw new Error('Missing required argument: type');\n const withCtx = injectContext(args, ['projectId', 'specificationId']);\n return await callLocal('list', withCtx);\n },\n\n search: async (_client, args) => {\n if (!args.query && !args.files && !args.tags && !args.relatedTo) {\n throw new Error('At least one filter is required: query, files, tags, or relatedTo');\n }\n const withCtx = injectContext(args, ['projectId', 'specificationId']);\n if (!withCtx.projectId && !withCtx.specificationId && !withCtx.epicId) {\n throw new Error('One of projectId, specificationId, or epicId is required. Run \"specforge switch\" or provide explicitly.');\n }\n return await callLocal('search', withCtx);\n },\n\n get_next_actionable_tickets: async (_client, args) => {\n // Inject projectId/specificationId from .specforge.json if not provided\n const argsWithContext = injectContext(args, ['projectId', 'specificationId']);\n\n // Either specificationId or projectId is required (after injection)\n if (!argsWithContext.specificationId && !argsWithContext.projectId) {\n throw new Error('Either specificationId or projectId is required. Set working context with \"specforge switch\" or provide explicitly.');\n }\n return await callLocal('get_next_actionable_tickets', {\n specificationId: argsWithContext.specificationId,\n projectId: argsWithContext.projectId,\n limit: argsWithContext.limit ?? 5,\n });\n },\n\n get_blocked_tickets: async (_client, args) => {\n // Inject specificationId from .specforge.json if not provided\n const argsWithContext = injectContext(args, ['specificationId']);\n\n if (!argsWithContext.specificationId) {\n throw new Error('specificationId is required. Set working context with \"specforge switch\" or provide explicitly.');\n }\n return await callLocal('get_blocked_tickets', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n get_report: async (_client, args) => {\n validateRequired(args, 'type', 'scope', 'scopeId');\n return await callLocal('get_report', {\n type: args.type,\n scope: args.scope,\n scopeId: args.scopeId,\n format: args.format ?? 'json',\n startDate: args.startDate,\n endDate: args.endDate,\n });\n },\n\n // ========================================================================\n // Lifecycle\n // ========================================================================\n // Planning lifecycle (M9.6b) — identity/session injected from the\n // `.specforge` config; SPS persists the session id, a `closed` status\n // clears it. Payloads match the post-M8 boundary (SPS {specificationId};\n // APS {sessionId, operation:{type,...}}; CPS {sessionId}).\n start_planning_session: async (_client, args) => {\n const cfg = tryLoadProjectConfig();\n const specificationId = (args.specificationId as string) ?? cfg?.specificationId;\n if (!specificationId) {\n throw new Error('No active specification. Run `specforge switch <spec-id>` or pass specificationId.');\n }\n const agentResponse = await callLocal<{ sessionId?: string }>(\n 'start_planning_session',\n { specificationId },\n );\n if (agentResponse?.sessionId) {\n saveProjectConfig({ planningSessionId: agentResponse.sessionId });\n appendPlanningSessionRegistry({\n specificationId,\n planningSessionId: agentResponse.sessionId,\n startedAt: new Date().toISOString(),\n });\n }\n return agentResponse;\n },\n\n action_planning_session: async (_client, args) => {\n if (!args.operation || typeof args.operation !== 'object') {\n throw new Error('Missing required argument: operation (e.g. { type: \"get_planning_status\" })');\n }\n const cfg = tryLoadProjectConfig();\n const sessionId = (args.sessionId as string) ?? cfg?.planningSessionId;\n if (!sessionId) {\n throw new Error('No active planning session. Call start_planning_session first.');\n }\n const agentResponse = await callLocal<{ planningStatus?: string }>(\n 'action_planning_session',\n { sessionId, operation: args.operation },\n );\n // Close detection: clear the persisted session id once it closes.\n if (agentResponse?.planningStatus === 'closed' && cfg?.specificationId) {\n saveProjectConfig({ planningSessionId: undefined });\n markPlanningSessionRegistryCompleted({\n specificationId: cfg.specificationId,\n completedAt: new Date().toISOString(),\n });\n }\n return agentResponse;\n },\n\n complete_planning_session: async (_client, args) => {\n const cfg = tryLoadProjectConfig();\n const sessionId = (args.sessionId as string) ?? cfg?.planningSessionId;\n if (!sessionId) {\n throw new Error('No active planning session. Call start_planning_session first.');\n }\n // CPS-success flips to awaiting_human_review (not closed) — keep the id.\n return await callLocal('complete_planning_session', { sessionId });\n },\n\n start_work_session: async (_client, args) => {\n validateRequired(args, 'ticketId');\n return await callLocal('start_work_session', {\n ticketId: args.ticketId,\n });\n },\n\n action_work_session: async (_client, args) => {\n validateRequired(args, 'ticketId');\n return await callLocal('action_work_session', {\n ticketId: args.ticketId,\n steps: args.steps,\n allStepsDone: args.allStepsDone,\n acceptanceCriteria: args.acceptanceCriteria,\n allACValidated: args.allACValidated,\n testResults: args.testResults,\n notes: args.notes,\n filesCreated: args.filesCreated,\n filesModified: args.filesModified,\n filesDeleted: args.filesDeleted,\n discovery: args.discovery,\n blockReason: args.blockReason,\n getTicket: args.getTicket,\n includeFullContext: args.includeFullContext,\n codeSnippetsReviewed: args.codeSnippetsReviewed,\n typeReferencesReviewed: args.typeReferencesReviewed,\n });\n },\n\n complete_work_session: async (_client, args) => {\n validateRequired(args, 'ticketId', 'summary');\n return await callLocal('complete_work_session', {\n ticketId: args.ticketId,\n summary: args.summary,\n filesModified: args.filesModified,\n filesCreated: args.filesCreated,\n filesDeleted: args.filesDeleted,\n actualHours: args.actualHours,\n validation: args.validation,\n });\n },\n\n start_review_session: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('start_review_session', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n action_review_session: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('action_review_session', {\n specificationId: argsWithContext.specificationId,\n reviewSessionId: args.reviewSessionId,\n findingsAddressed: args.findingsAddressed,\n notes: args.notes,\n });\n },\n\n complete_review_session: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('complete_review_session', {\n specificationId: argsWithContext.specificationId,\n reviewSessionId: args.reviewSessionId,\n summary: args.summary,\n confirmAllDismissed: args.confirmAllDismissed,\n });\n },\n\n reopen_specification: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('reopen_specification', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n // ========================================================================\n // Mutation\n // ========================================================================\n\n // ========================================================================\n // Utilities\n // ========================================================================\n feedback: async (_client, args) => {\n // M9.7: origin is server-derived from the `X-SpecForge-Origin` header\n // (default `mcp` on the agent transport) — never a request-body `source`.\n return await callLocal('feedback', args);\n },\n\n reset_work_session: async (_client, args) => {\n validateRequired(args, 'specificationId');\n return await callLocal('reset_work_session', {\n specificationId: args.specificationId,\n ticketIds: args.ticketIds,\n fromTicketId: args.fromTicketId,\n epicId: args.epicId,\n allTickets: args.allTickets,\n targetStatus: args.targetStatus,\n resetDependents: args.resetDependents,\n includeCompleted: args.includeCompleted,\n preserveNotes: args.preserveNotes,\n clearTestResults: args.clearTestResults,\n });\n },\n\n link_pull_request: async (_client, args) => {\n validateRequired(args, 'ticketId');\n if (!args.prNumber && !args.prUrl) {\n throw new Error('Either prNumber or prUrl must be provided');\n }\n return await callLocal('link_pull_request', {\n ticketId: args.ticketId,\n prNumber: args.prNumber,\n prUrl: args.prUrl,\n title: args.title,\n author: args.author,\n repoUrl: args.repoUrl,\n });\n },\n\n // ========================================================================\n // Orchestration\n // ========================================================================\n get_critical_path: async (_client, args) => {\n const argsWithContext = injectContext(args, ['specificationId']);\n if (!argsWithContext.specificationId) {\n throw new Error('specificationId is required');\n }\n return await callLocal('get_critical_path', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n get_dependency_tree: async (_client, args) => {\n const argsWithContext = injectContext(args, ['specificationId']);\n if (!argsWithContext.specificationId) {\n throw new Error('specificationId is required');\n }\n return await callLocal('get_dependency_tree', {\n specificationId: argsWithContext.specificationId,\n });\n },\n };\n}\n\n/**\n * Validate that required arguments are present\n * @throws Error if any required argument is missing\n */\nfunction validateRequired(args: Record<string, unknown>, ...required: string[]): void {\n for (const field of required) {\n if (args[field] === undefined || args[field] === null || args[field] === '') {\n throw new Error(`Missing required argument: ${field}`);\n }\n }\n}\n\n// Create a cached instance of tool handlers\nlet cachedHandlers: Record<string, ToolHandler> | null = null;\n\n/**\n * Reset the cached tool handlers (for testing purposes)\n */\nexport function resetToolHandlers(): void {\n cachedHandlers = null;\n}\n\n/**\n * Handle a tool call by routing to the appropriate handler\n *\n * @param apiClient - The API client to use for making requests\n * @param toolName - Name of the tool being called\n * @param args - Arguments passed to the tool\n * @param debug - Whether to enable debug logging\n * @returns Promise resolving to the tool result\n */\nexport async function handleToolCall(\n apiClient: ApiClient,\n toolName: string,\n args: Record<string, unknown>,\n debug: boolean = false\n): Promise<unknown> {\n const startTime = Date.now();\n\n // Create handlers if not cached\n if (!cachedHandlers) {\n cachedHandlers = createToolHandlers(apiClient);\n }\n\n // Get the handler for this tool\n const handler = cachedHandlers[toolName];\n if (!handler) {\n throw new Error(`Unknown tool: ${toolName}`);\n }\n\n if (debug) {\n console.error(`[DEBUG] Calling tool: ${toolName}`, {\n args: JSON.stringify(args),\n });\n }\n\n try {\n // Run comprehensive validation before executing\n validateToolArgs(toolName, args);\n\n // Execute with retry logic\n const result = await withRetry(\n () => handler(apiClient, args),\n toolName,\n debug\n );\n\n const duration = Date.now() - startTime;\n if (debug) {\n console.error(`[DEBUG] Tool ${toolName} completed in ${duration}ms`);\n }\n\n return result;\n } catch (error) {\n const duration = Date.now() - startTime;\n\n // Transform error for proper handling\n const transformedError = transformError(error);\n const message = transformedError.message;\n\n if (debug) {\n console.error(`[DEBUG] Tool ${toolName} failed after ${duration}ms:`, message);\n if (transformedError instanceof ValidationError) {\n console.error(`[DEBUG] Validation field: ${transformedError.field}, code: ${transformedError.code}`);\n }\n }\n\n // Rethrow with context\n if (transformedError instanceof ValidationError) {\n throw transformedError;\n }\n if (transformedError instanceof ApiError) {\n throw transformedError;\n }\n throw new Error(`Tool ${toolName} failed: ${message}`);\n }\n}\n\n/**\n * Handle a tool call and return MCP-formatted response\n * This wraps handleToolCall with proper error formatting for MCP protocol\n */\nexport async function handleToolCallSafe(\n apiClient: ApiClient,\n toolName: string,\n args: Record<string, unknown>,\n debug: boolean = false\n): Promise<unknown | MCPErrorResponse> {\n try {\n return await handleToolCall(apiClient, toolName, args, debug);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return formatMCPError(err);\n }\n}\n\n// Re-export validation utilities for use by other modules\nexport {\n ValidationError,\n ApiError,\n validateToolArgs,\n formatMCPError,\n transformError,\n type MCPErrorResponse,\n} from '../validation/index.js';\n"],"mappings":"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","names":["ValidationError","ApiError","validateToolArgs","formatMCPError","transformError"]}
1
+ {"version":3,"sources":["../../src/tools/index.ts"],"sourcesContent":["/**\n * MCP Tools Registry\n *\n * This module defines and exports all available MCP tools.\n * 22 tools organized into: Queries, Lifecycle, Mutation, Utilities, Orchestration.\n */\n\nimport { ApiClient } from '../client/api-client.js';\nimport {\n ValidationError,\n ApiError,\n validateToolArgs,\n formatMCPError,\n transformError,\n MCPErrorResponse,\n} from '../validation/index.js';\nimport { injectContext, injectContextRequired } from './core/context-helper.js';\nimport { tryLoadProjectConfig, saveProjectConfig } from '../cli/config/index.js';\nimport {\n appendPlanningSessionRegistry,\n markPlanningSessionRegistryCompleted,\n} from '../cli/config/planning-sessions-registry.js';\n\n/**\n * Tool definition matching MCP protocol schema\n */\nexport interface Tool {\n name: string;\n description: string;\n inputSchema: {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\n/**\n * Get list of all available tools\n *\n * @returns Array of tool definitions (22 tools)\n */\nexport function getTools(): Tool[] {\n const tools: Tool[] = [\n // ========================================================================\n // Queries (6)\n // ========================================================================\n {\n name: 'get',\n description: 'Get a single entity by type and ID.',\n inputSchema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['project', 'specification', 'epic', 'ticket', 'blueprint'],\n description: 'Entity type to retrieve',\n },\n id: {\n type: 'string',\n description: 'Entity ID',\n },\n },\n required: ['type', 'id'],\n },\n },\n {\n name: 'list',\n description: 'List entities by type.',\n inputSchema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['projects', 'specifications', 'epics', 'tickets', 'blueprints'],\n description: 'Entity type to list',\n },\n projectId: {\n type: 'string',\n description: 'Filter by project (for specifications)',\n },\n specificationId: {\n type: 'string',\n description: 'Filter by specification (for epics, tickets)',\n },\n epicId: {\n type: 'string',\n description: 'Filter by epic (for tickets)',\n },\n },\n required: ['type'],\n },\n },\n {\n name: 'search',\n description: `Unified ticket search with multiple filter options.\n\nCombines:\n- Full-text search (query)\n- File matching (files) - replaces find_tickets_by_file\n- Tag filtering (tags) - replaces find_tickets_by_tag\n- Related tickets (relatedTo) - replaces find_related_tickets\n- Status, complexity, priority filters\n\nAt least one of: query, files, tags, or relatedTo is required.\nAt least one scope filter (projectId, specificationId, or epicId) is required.`,\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Full-text search query',\n },\n files: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns to match ticket files (e.g., \"**/channel/*.ts\")',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Tags to filter by',\n },\n matchAllTags: {\n type: 'boolean',\n description: 'If true, match all tags (AND). If false, match any (OR). Default: false',\n },\n relatedTo: {\n type: 'string',\n description: 'Find tickets related to this ticket ID (by tags, files, tech stack)',\n },\n status: {\n type: 'array',\n items: {\n type: 'string',\n enum: ['pending', 'ready', 'active', 'done'],\n },\n description: 'Filter by status',\n },\n complexity: {\n type: 'array',\n items: {\n type: 'string',\n enum: ['small', 'medium', 'large', 'xlarge'],\n },\n description: 'Filter by complexity',\n },\n projectId: {\n type: 'string',\n description: 'Limit search to project',\n },\n specificationId: {\n type: 'string',\n description: 'Limit search to specification',\n },\n epicId: {\n type: 'string',\n description: 'Limit search to epic',\n },\n limit: {\n type: 'number',\n description: 'Maximum results (default: 20, max: 100)',\n },\n offset: {\n type: 'number',\n description: 'Pagination offset (default: 0)',\n },\n },\n },\n },\n {\n name: 'get_next_actionable_tickets',\n description: 'Get tickets with status \"ready\" (all dependencies satisfied). Use start_work_session() to begin work on these tickets.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification (optional if projectId provided)',\n },\n projectId: {\n type: 'string',\n description: 'The ID of the project to get actionable tickets across all specifications',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of tickets to return (default: 5)',\n },\n },\n },\n },\n {\n name: 'get_blocked_tickets',\n description: 'Get tickets with status \"pending\", each with the `blockedBy` list of unsatisfied dependency tickets computed from the dependency tree.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'get_report',\n description: `Generate unified reports for implementation, time tracking, blockers, work summary, or active sessions.\n\nReport types:\n- 'implementation': Progress, velocity, completions (replaces get_implementation_summary)\n- 'time': Estimated vs actual hours (replaces get_time_report)\n- 'blockers': Blocked tickets with reasons (replaces get_blockers_report)\n- 'work': Completed work summary from WorkSession records (replaces get_work_summary)\n- 'sessions': Live planning/work/review sessions for a project (requires scope='project')\n\nFormat options:\n- 'json': Full structured data (default)\n- 'summary': Condensed text summary`,\n inputSchema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['implementation', 'time', 'blockers', 'work', 'sessions'],\n description: 'Type of report to generate',\n },\n scope: {\n type: 'string',\n enum: ['project', 'specification', 'epic'],\n description: \"Scope of the report. 'sessions' requires scope='project'.\",\n },\n scopeId: {\n type: 'string',\n description: 'ID of the scoped entity (projectId, specificationId, or epicId)',\n },\n startDate: {\n type: 'string',\n description: 'Start date for work report (ISO 8601)',\n },\n endDate: {\n type: 'string',\n description: 'End date for work report (ISO 8601)',\n },\n format: {\n type: 'string',\n enum: ['json', 'summary'],\n description: \"Response format: 'json' (default) or 'summary'.\",\n },\n },\n required: ['type', 'scope', 'scopeId'],\n },\n },\n\n // ========================================================================\n // Lifecycle (10)\n // ========================================================================\n {\n name: 'start_planning_session',\n description: 'Start or resume a guided planning session for a specification. Project-scoped lock: only one active planning session per project. Calling with the same spec resumes the existing session (idempotent). Calling with a different spec while one is active returns a rejection with the active session details. Planning is independent of implementation and review — they can run concurrently.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The specification to plan. Optional — defaults to the active spec in the local config (.specforge/config.json), so you normally omit it.',\n },\n projectId: {\n type: 'string',\n description: 'The owning project. Optional — defaults to the active project in the local config (.specforge/config.json); injected automatically, so you normally omit it.',\n },\n },\n // Nothing is required: specificationId/projectId fall back to local config, and\n // the returned sessionId is persisted + injected into subsequent calls.\n required: [],\n },\n },\n {\n name: 'action_planning_session',\n description: \"Execute a planning action within an active session. Wraps all planning operations (create/update/delete epics, tickets, dependencies, blueprints) plus get_planning_status (readiness X-ray, worst-first) with automatic status tracking. The operation.type IS the backend PlanningOperationName. 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. To read a single ticket, use the `get` tool (type:'ticket').\",\n inputSchema: {\n type: 'object',\n properties: {\n operation: {\n type: 'object',\n description: 'The operation to perform. Must include a \"type\" field. Per-op required fields are declared in `oneOf` below — agents should consult their own tool schema parser for the exact shape per type. Do NOT pass sessionId/projectId/specificationId: the active planning session is injected from local config.',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'update_spec',\n 'create_epic',\n 'update_epic',\n 'delete_epic',\n 'create_ticket',\n 'update_ticket',\n 'delete_ticket',\n 'create_blueprint',\n 'update_blueprint',\n 'delete_blueprint',\n 'link_blueprint_to_tickets',\n 'unlink_blueprint_to_tickets',\n 'create_dependencies',\n 'delete_dependencies',\n 'get_planning_status',\n ],\n description: 'The planning operation to perform (lifecycle vocabulary). The type IS the backend PlanningOperationName; remaining fields are the operation payload.',\n },\n },\n required: ['type'],\n oneOf: [\n {\n properties: {\n type: { const: 'update_spec' },\n fields: { type: 'object', description: 'Partial spec update — only the keys you send are changed (e.g. background, goals, nonGoals, constraints, successCriteria).' },\n },\n required: ['type', 'fields'],\n },\n // create_epic — SHELL only (epic_decomposition). Body fields are authored\n // by update_epic in epic_expansion; only title/description/objective are\n // persisted on create, so only those are advertised.\n {\n properties: {\n type: { const: 'create_epic' },\n title: { type: 'string', minLength: 1, description: 'Epic title (non-empty)' },\n description: { type: 'string', description: 'What this epic delivers' },\n objective: { type: 'string', description: 'Goal achieved for the user' },\n },\n required: ['type', 'title'],\n },\n {\n properties: {\n type: { const: 'update_epic' },\n id: { type: 'string', description: 'Epic id (use list_epics / lookup_epic to find).' },\n fields: {\n type: 'object',\n description: 'Partial epic update — only the keys you send are changed.',\n properties: {\n title: { type: 'string' },\n description: { type: 'string' },\n objective: { type: 'string', description: 'Goal achieved for the user.' },\n architecture: { type: 'string', description: 'Structural approach specific to this epic.' },\n scope: { type: 'object', description: 'Epic scope.', properties: { inScope: { type: 'array', items: { type: 'string' } }, outOfScope: { type: 'array', items: { type: 'string' } }, assumptions: { type: 'array', items: { type: 'string' } }, externalDependencies: { type: 'array', items: { type: 'string' } } } },\n goals: { type: 'array', description: 'Epic goals as objects (Epic.goals is a json object[], not string[]).', items: { type: 'object', properties: { title: { type: 'string' }, description: { type: 'string' }, type: { type: 'string', enum: ['business', 'technical', 'user', 'operational'] }, successCriteria: { type: 'array', items: { type: 'string' } } }, required: ['title', 'description'] } },\n acceptanceCriteria: { type: 'array', description: 'BDD criteria objects (Epic.acceptanceCriteria is a json object[], not string[]).', items: { type: 'object', properties: { given: { type: 'string' }, when: { type: 'string' }, then: { type: 'string' } }, required: ['given', 'when', 'then'] } },\n validationCommands: { type: 'array', items: { type: 'string' }, description: 'Commands that verify this epic end-to-end.' },\n apiContracts: { type: 'array', description: 'API contracts this epic exposes.', items: { type: 'object', properties: { id: { type: 'string' }, name: { type: 'string' }, type: { type: 'string' }, description: { type: 'string' } } } },\n sharedPatterns: { type: 'array', description: 'Reusable patterns the epic\\'s tickets should follow.', items: { type: 'object' } },\n fileStructures: { type: 'array', description: 'Concrete files this epic creates/modifies.', items: { type: 'object', properties: { id: { type: 'string' }, scope: { type: 'string' }, description: { type: 'string' }, content: { type: 'string' } } } },\n requirementsCovered: { type: 'array', items: { type: 'string' }, description: 'Spec requirement ids this epic covers.' },\n nfrsCovered: { type: 'array', items: { type: 'string' }, description: 'Spec NFR ids this epic covers.' },\n goalsCovered: { type: 'array', items: { type: 'string' }, description: 'Spec goal ids this epic advances.' },\n },\n },\n },\n required: ['type', 'id', 'fields'],\n },\n // create_ticket — SHELL only (ticket_decomposition). Body fields\n // (ticketType, complexity, acceptanceCriteria, implementationSteps, …)\n // are authored by update_ticket in ticket_expansion; dependencies via\n // create_dependencies in cross_validation. Only epicId/title/description\n // are persisted on create, so only those are advertised.\n {\n properties: {\n type: { const: 'create_ticket' },\n epicId: { type: 'string', description: 'Parent epic id' },\n title: { type: 'string', minLength: 1, description: 'Ticket title (non-empty)' },\n description: { type: 'string' },\n },\n required: ['type', 'epicId', 'title'],\n },\n {\n properties: {\n type: { const: 'update_ticket' },\n id: { type: 'string', description: 'Ticket id (use list_tickets / lookup_ticket to find).' },\n fields: {\n type: 'object',\n description: 'Partial ticket update — only the keys you send are changed. Child-backed arrays (acceptanceCriteria, implementationSteps, filesToBe*, testSpecification.testTypes, blueprintReferences, codeSnippets, typeSnippets) replace the whole set.',\n properties: {\n title: { type: 'string' },\n description: { type: 'string' },\n ticketType: { type: 'string', enum: ['implementation', 'verification'] },\n complexity: { type: 'string', enum: ['small', 'medium', 'large', 'xlarge'] },\n estimatedMinutes: { type: 'integer', minimum: 0 },\n acceptanceCriteria: { type: 'array', items: { type: 'object', properties: { given: { type: 'string' }, when: { type: 'string' }, then: { type: 'string' } }, required: ['given', 'when', 'then'] } },\n implementationSteps: { type: 'array', items: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] } },\n filesToBeCreated: { type: 'array', items: { type: 'string' } },\n filesToBeModified: { type: 'array', items: { type: 'string' } },\n filesToBeDeleted: { type: 'array', items: { type: 'string' } },\n filesToBeReferenced: { type: 'array', items: { type: 'string' } },\n guardrails: { type: 'array', items: { type: 'string' } },\n testSpecification: { type: 'object', properties: { testTypes: { type: 'array', items: { type: 'string', enum: ['unit', 'integration', 'e2e', 'typecheck', 'lint', 'build', 'contract', 'structural', 'layout', 'a11y', 'performance'] } }, qualityGates: { type: 'array', items: { type: 'string' } }, testCommands: { type: 'array', items: { type: 'string' } }, coverageTarget: { type: 'integer', minimum: 0, maximum: 100 } } },\n codeReferences: { type: 'array', description: 'Existing code to reuse/anchor on.', items: { type: 'object', properties: { filePath: { type: 'string' }, symbol: { type: 'string' }, description: { type: 'string' } }, required: ['filePath'] } },\n typeReferences: { type: 'array', description: 'Existing types to use.', items: { type: 'object', properties: { filePath: { type: 'string' }, typeName: { type: 'string' }, description: { type: 'string' } }, required: ['filePath', 'typeName'] } },\n codeSnippets: { type: 'array', items: { type: 'object', properties: { language: { type: 'string' }, content: { type: 'string' }, description: { type: 'string' } }, required: ['language', 'content'] } },\n typeSnippets: { type: 'array', items: { type: 'object', properties: { language: { type: 'string' }, content: { type: 'string' }, description: { type: 'string' } }, required: ['language', 'content'] } },\n blueprintReferences: { type: 'array', items: { type: 'object', properties: { blueprintId: { type: 'string' }, context: { type: 'string' }, section: { type: 'string' } }, required: ['blueprintId'] } },\n tags: { type: 'array', items: { type: 'string' } },\n },\n },\n },\n required: ['type', 'id', 'fields'],\n },\n {\n properties: {\n type: { const: 'delete_epic' },\n id: { type: 'string', description: 'Epic id; cascades to all tickets in the epic.' },\n cascadeRemoveDependencies: { type: 'boolean', description: 'Confirm removing dependency edges pointing at this epic\\'s tickets from outside the epic. Required (true) when such referrers exist, else the delete is denied.' },\n },\n required: ['type', 'id'],\n },\n {\n properties: {\n type: { const: 'delete_ticket' },\n id: { type: 'string', description: 'Ticket id (use list_tickets / lookup_ticket to find).' },\n cascadeRemoveDependencies: { type: 'boolean', description: 'Confirm removing dependency edges from other tickets that point at this ticket. Required (true) when such referrers exist, else the delete is denied.' },\n },\n required: ['type', 'id'],\n },\n {\n properties: {\n type: { const: 'create_dependencies' },\n dependencies: {\n type: 'array',\n minItems: 1,\n maxItems: 5000,\n description: 'Up to 5000 dependency pairs, each a \"requires\" edge (fromTicketId depends on toTicketId). The batch is validated atomically: a cycle or an all-duplicate batch is rejected with guidance; already-existing edges are skipped.',\n items: {\n type: 'object',\n properties: {\n fromTicketId: { type: 'string', description: 'The dependent ticket (this one depends on the other).' },\n toTicketId: { type: 'string', description: 'The blocker ticket it depends on.' },\n },\n required: ['fromTicketId', 'toTicketId'],\n },\n },\n },\n required: ['type', 'dependencies'],\n },\n {\n properties: {\n type: { const: 'delete_dependencies' },\n dependencyIds: { type: 'array', minItems: 1, items: { type: 'string' }, description: 'TicketDependency ids to remove (use lookup/list to find).' },\n },\n required: ['type', 'dependencyIds'],\n },\n {\n properties: {\n type: { const: 'create_blueprint' },\n title: { type: 'string', minLength: 1, description: 'Blueprint title (non-empty)' },\n content: { type: 'string', description: 'Body — diagram source or markdown, persisted as-is on create.' },\n format: { type: 'string', enum: ['markdown', 'mermaid', 'ascii', 'mixed', 'html', 'svg', 'image'], description: 'Defaults to \"mermaid\"' },\n category: { type: 'string', enum: ['flowchart', 'architecture', 'state', 'sequence', 'erd', 'mockup', 'adr', 'component', 'deployment', 'api', 'algorithm', 'protocol', 'glossary', 'design_system'], description: 'Blueprint category (SpecificationBlueprint.category model enum).' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n },\n required: ['type', 'title', 'category'],\n },\n {\n properties: {\n type: { const: 'update_blueprint' },\n id: { type: 'string', description: 'Blueprint id.' },\n fields: {\n type: 'object',\n description: 'Partial blueprint update — only the keys you send are changed.',\n properties: {\n title: { type: 'string' },\n content: { type: 'string' },\n category: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n },\n },\n },\n required: ['type', 'id', 'fields'],\n },\n {\n properties: {\n type: { const: 'delete_blueprint' },\n id: { type: 'string', description: 'Blueprint id.' },\n },\n required: ['type', 'id'],\n },\n {\n properties: {\n type: { const: 'link_blueprint_to_tickets' },\n blueprintId: { type: 'string', description: 'Blueprint to link.' },\n ticketIds: { type: 'array', minItems: 1, items: { type: 'string' }, description: 'Tickets to link the blueprint to.' },\n },\n required: ['type', 'blueprintId', 'ticketIds'],\n },\n {\n properties: {\n type: { const: 'unlink_blueprint_to_tickets' },\n blueprintId: { type: 'string', description: 'Blueprint to unlink.' },\n ticketIds: { type: 'array', minItems: 1, items: { type: 'string' }, description: 'Tickets to unlink the blueprint from.' },\n },\n required: ['type', 'blueprintId', 'ticketIds'],\n },\n {\n // Read-only poll/resume. To read a single ticket, use the `get` tool (type:'ticket').\n properties: {\n type: { const: 'get_planning_status' },\n },\n required: ['type'],\n },\n ],\n },\n },\n required: ['operation'],\n },\n },\n {\n name: 'complete_planning_session',\n description: \"Complete the planning session and submit the spec for final review. Spec must be in 'planning' status. Runs the planning gate (consistency checks + readinessThreshold from project/spec settings). Transitions the spec directly to 'ready' on pass. Takes no arguments — the active planning session is injected from local config.\",\n inputSchema: {\n type: 'object',\n // No inputs: the active planning session (sessionId) is injected from\n // local config (.specforge/config.json). Do NOT pass sessionId/projectId/specificationId.\n properties: {},\n required: [],\n },\n },\n {\n name: 'start_work_session',\n 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.',\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket to start',\n },\n },\n required: ['ticketId'],\n },\n },\n {\n name: 'action_work_session',\n description: `Update checklist state during an active WorkSession. Combines step completion, AC validation, test result reporting, file tracking, reference review confirmation, and discovery reporting into a single atomic operation. All state changes are recorded on the WorkSession and its related validation/completion records.\n\nUse this instead of calling update_ticket for checklist changes. Provides:\n- Step completion (individual or bulk via WorkSessionStepCompletion)\n- Acceptance criteria validation (individual or bulk via WorkSessionACValidation)\n- Test result reporting (merged by test type via WorkSessionTestResult)\n- File tracking (created, modified, deleted on WorkSession)\n- Discovery reporting (create discoveries for blockers, bugs, tech debt)\n- Blocker management (set block reason; requires existing discovery)\n- Reference review tracking (codeSnippetsReviewed, typeReferencesReviewed)\n- Auto-calculated progress percentage\n- Completion readiness hints\n\nIMPORTANT: 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.\n\nIf the ticket has codeReferences or typeReferences, set codeSnippetsReviewed/typeReferencesReviewed to true after reviewing them — completion readiness will block until these are confirmed.\n\nSet 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.`,\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket being worked on (must be in active status)',\n },\n steps: {\n type: 'array',\n description: 'Individual step completion updates',\n items: {\n type: 'object',\n properties: {\n index: {\n type: 'number',\n description: \"Zero-based index of the step among the ticket's implementation steps (TicketImplementationStep rows, ordered by `order`)\",\n },\n completed: {\n type: 'boolean',\n description: 'Whether the step is completed',\n },\n notes: {\n type: 'string',\n description: 'Optional note about this step',\n },\n },\n required: ['index', 'completed'],\n },\n },\n allStepsDone: {\n type: 'boolean',\n description: 'Shortcut: mark all steps as completed',\n },\n acceptanceCriteria: {\n type: 'array',\n description: 'Individual AC validation updates',\n items: {\n type: 'object',\n properties: {\n index: {\n type: 'number',\n description: 'Zero-based index of the AC in the acceptanceCriteria array',\n },\n validated: {\n type: 'boolean',\n description: 'Whether the AC is validated',\n },\n notes: {\n type: 'string',\n description: 'Optional note about this AC',\n },\n },\n required: ['index', 'validated'],\n },\n },\n allACValidated: {\n type: 'boolean',\n description: 'Shortcut: mark all acceptance criteria as validated',\n },\n testResults: {\n type: 'array',\n description: 'Test result reports to append (merged by testType)',\n items: {\n type: 'object',\n properties: {\n testType: {\n type: 'string',\n description: 'Type of test (e.g., \"unit\", \"integration\", \"e2e\", \"lint\", \"typeCheck\")',\n },\n passed: {\n type: 'number',\n description: 'Number of tests that passed',\n },\n failed: {\n type: 'number',\n description: 'Number of tests that failed',\n },\n skipped: {\n type: 'number',\n description: 'Number of tests skipped',\n },\n command: {\n type: 'string',\n description: 'Command used to run the tests',\n },\n output: {\n type: 'string',\n description: 'Test output (truncated if needed)',\n },\n duration: {\n type: 'number',\n description: 'Duration in milliseconds',\n },\n suites: {\n type: 'array',\n description: 'Optional suite-level breakdown',\n items: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Suite name' },\n passed: { type: 'number', description: 'Passed tests in suite' },\n failed: { type: 'number', description: 'Failed tests in suite' },\n skipped: { type: 'number', description: 'Skipped tests in suite' },\n duration: { type: 'number', description: 'Suite duration in ms' },\n },\n required: ['name', 'passed', 'failed'],\n },\n },\n tests: {\n type: 'array',\n description: 'Optional individual test breakdown',\n items: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Test name' },\n suite: { type: 'string', description: 'Parent suite name' },\n status: { type: 'string', enum: ['passed', 'failed', 'skipped'], description: 'Test result' },\n duration: { type: 'number', description: 'Test duration in ms' },\n },\n required: ['name', 'status'],\n },\n },\n },\n required: ['testType', 'passed', 'failed'],\n },\n },\n notes: {\n type: 'string',\n description: 'Additional notes to append to the ticket',\n },\n filesCreated: {\n type: 'array',\n items: { type: 'string' },\n description: 'Files created during this session. Accumulated incrementally.',\n },\n filesModified: {\n type: 'array',\n items: { type: 'string' },\n description: 'Files modified during this session. Accumulated incrementally.',\n },\n filesDeleted: {\n type: 'array',\n items: { type: 'string' },\n description: 'Files deleted during this session. Accumulated incrementally.',\n },\n discovery: {\n type: 'object',\n description: 'Create a discovery (observation about the implementation). Use this to report blockers, bugs, tech debt, scope changes, etc.',\n properties: {\n description: { type: 'string', description: 'Description of the discovery' },\n type: { type: 'string', description: 'Discovery type: bug, tech_debt, blocker, clarification, scope_change, dependency, risk, ticket, epic' },\n severity: { type: 'string', description: 'Severity: blocker, critical, major, minor' },\n suggestedTitle: { type: 'string', description: 'Suggested title for the new ticket/epic' },\n suggestedPriority: { type: 'string', description: 'Suggested priority: high, medium, low' },\n relatedFiles: { type: 'array', items: { type: 'string' }, description: 'Related file paths' },\n notes: { type: 'string', description: 'Additional notes' },\n },\n required: ['description'],\n },\n blockReason: {\n type: 'string',\n description: 'Set a blocker on this ticket. Requires an existing discovery (create via discovery parameter first).',\n },\n getTicket: {\n type: 'boolean',\n description: 'Fetch full ticket details. Can be the sole operation or combined with other actions.',\n },\n includeFullContext: {\n type: 'boolean',\n description: 'Include full implementation context in response',\n },\n codeSnippetsReviewed: {\n type: 'boolean',\n description: 'Confirm that code snippets (codeReferences) on the ticket have been reviewed. Required before completion when the ticket has non-empty codeReferences.',\n },\n typeReferencesReviewed: {\n type: 'boolean',\n description: 'Confirm that type references (typeReferences) on the ticket have been reviewed. Required before completion when the ticket has non-empty typeReferences.',\n },\n },\n required: ['ticketId'],\n },\n },\n {\n name: 'complete_work_session',\n description:\n 'Mark a ticket as complete and finalize the active WorkSession. Transitions active -> done. Session data (files, test results, time) is stored on the WorkSession record.\\n\\n' +\n 'All acceptance criteria must be validated and all implementation steps must be completed via action_work_session before calling this. The completion gate enforces this — shortcuts are not available.\\n\\n' +\n 'Automatically recalculates status for dependent tickets and returns cascade info.\\n\\n' +\n 'Optional validation flags can be provided to report test results inline:\\n' +\n '- tests: Unit/integration test results\\n' +\n '- lint: Linting results\\n' +\n '- typeCheck: TypeScript type checking\\n' +\n '- build: Build/compilation results',\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket',\n },\n summary: {\n type: 'string',\n description: 'Summary of work completed',\n },\n filesModified: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of files modified',\n },\n filesCreated: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of files created',\n },\n filesDeleted: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of files deleted',\n },\n actualHours: {\n type: 'number',\n description: 'Actual hours spent on the ticket',\n },\n validation: {\n type: 'object',\n description: 'Detailed validation flags for reporting test/lint/build results',\n properties: {\n tests: {\n type: 'string',\n enum: ['passed', 'failed', 'partial', 'pending'],\n description: 'Unit/integration test results',\n },\n lint: {\n type: 'string',\n enum: ['passed', 'failed', 'partial', 'pending'],\n description: 'Linting results',\n },\n typeCheck: {\n type: 'string',\n enum: ['passed', 'failed', 'partial', 'pending'],\n description: 'TypeScript type checking results',\n },\n build: {\n type: 'string',\n enum: ['passed', 'failed', 'partial', 'pending'],\n description: 'Build/compilation results',\n },\n notes: {\n type: 'string',\n description: 'Additional validation notes',\n },\n },\n },\n },\n required: ['ticketId', 'summary'],\n },\n },\n {\n name: 'start_review_session',\n description: 'Start the implementation review lifecycle. Runs the implementation gate and either auto-transitions to \"reviewed\" (on pass) or transitions to \"in_review\" with an active ReviewSession (on fail). Creates correction tickets via action_review_session, then call complete_review_session.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification to review (must be in ready_for_review status)',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'action_review_session',\n description: 'Address findings in an active review session. Create correction tickets inline or dismiss findings with justification. Only available when specification is in \"in_review\" status.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification',\n },\n reviewSessionId: {\n type: 'string',\n description: 'The review session ID (auto-detected if omitted)',\n },\n findingsAddressed: {\n type: 'array',\n description: 'Findings to address in this action',\n items: {\n type: 'object',\n properties: {\n findingId: {\n type: 'string',\n description: 'The finding ID to address',\n },\n action: {\n type: 'string',\n enum: ['correction_ticket', 'dismissed'],\n description: 'How to address the finding',\n },\n correctionTicket: {\n type: 'object',\n description: 'Inline ticket creation params (required for correction_ticket action)',\n properties: {\n epicId: { type: 'string', description: 'Epic to add the correction ticket to' },\n title: { type: 'string', description: 'Ticket title' },\n description: { type: 'string', description: 'Ticket description' },\n ticketType: { type: 'string', enum: ['implementation', 'verification'], description: 'Ticket type — defaults to implementation.' },\n complexity: { type: 'string', enum: ['small', 'medium', 'large', 'xlarge'] },\n estimatedMinutes: { type: 'integer', minimum: 0 },\n acceptanceCriteria: { type: 'array', items: { type: 'string' } },\n implementationSteps: { type: 'array', items: { type: 'string' }, description: 'Implementation steps; persisted as TicketImplementationStep rows' },\n tags: { type: 'array', items: { type: 'string' } },\n },\n required: ['epicId', 'title'],\n },\n justification: {\n type: 'string',\n description: 'Required justification when action is \"dismissed\"',\n },\n },\n required: ['findingId', 'action'],\n },\n },\n notes: {\n type: 'string',\n description: 'Optional notes for this review action',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'complete_review_session',\n description: 'Complete an active review session. All error-severity findings must be addressed. If correction tickets exist, transitions to \"in_progress\". If all findings dismissed, triggers user confirmation flow.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification',\n },\n reviewSessionId: {\n type: 'string',\n description: 'The review session ID (auto-detected if omitted)',\n },\n summary: {\n type: 'string',\n description: 'Optional completion summary',\n },\n confirmAllDismissed: {\n type: 'boolean',\n description: 'Set to true when all findings were dismissed to trigger user confirmation flow',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'reopen_specification',\n description: 'Reopen a specification in \"ready\" status, regressing to \"planning\". After reopening, call start_planning_session to begin a new planning session.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The ID of the specification to reopen',\n },\n },\n required: ['specificationId'],\n },\n },\n\n // Spec creation is a HUMAN bootstrap step, NOT an agent MCP tool: specs are\n // created via `specforge init` (cli-rest surface), which also writes the new\n // spec id into the local config so the agent's per-call injection finds it.\n // The agent assumes the spec already exists and starts from\n // `start_planning_session`. (Backend keeps `create_specification` REST-only;\n // it was never dispatchable on /local.)\n\n // ========================================================================\n // Utilities (3)\n // ========================================================================\n {\n name: 'feedback',\n description: `Submit and manage feedback about MCP tools. Operations:\n- submit: Submit new feedback (requires category, summary)\n- list: List recent feedback entries\n- get: Get a specific feedback entry by ID`,\n inputSchema: {\n type: 'object',\n properties: {\n operation: {\n type: 'string',\n enum: ['submit', 'list', 'get'],\n description: 'The operation to perform',\n },\n // For submit operation\n category: {\n type: 'string',\n enum: ['bug', 'feature_request', 'usability', 'documentation', 'performance'],\n description: 'Feedback category (required for submit)',\n },\n summary: {\n type: 'string',\n description: 'Brief summary of the feedback (required for submit)',\n },\n severity: {\n type: 'string',\n enum: ['critical', 'high', 'medium', 'low'],\n description: 'Severity level (default: medium)',\n },\n tool: {\n type: 'string',\n description: 'Which MCP tool this relates to',\n },\n toolOperation: {\n type: 'string',\n description: 'Specific operation within the tool',\n },\n details: {\n type: 'string',\n description: 'Extended description',\n },\n expected: {\n type: 'string',\n description: 'Expected behavior',\n },\n actual: {\n type: 'string',\n description: 'Actual behavior',\n },\n errorMessage: {\n type: 'string',\n description: 'Error message if reporting a bug',\n },\n ticketId: {\n type: 'string',\n description: 'Related ticket ID',\n },\n // For list operation\n limit: {\n type: 'number',\n description: 'Maximum entries to return (default: 10)',\n },\n categoryFilter: {\n type: 'string',\n enum: ['bug', 'feature_request', 'usability', 'documentation', 'performance'],\n description: 'Filter by category',\n },\n // For get operation\n feedbackId: {\n type: 'string',\n description: 'Feedback ID to retrieve (required for get)',\n },\n },\n required: ['operation'],\n },\n },\n {\n name: 'reset_work_session',\n description: 'Reset tickets to pending/ready status (calculated from dependencies). Returns statusCalculation showing how many became pending vs ready.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'The specification containing the tickets',\n },\n ticketIds: {\n type: 'array',\n items: { type: 'string' },\n description: 'Specific ticket IDs to reset',\n },\n fromTicketId: {\n type: 'string',\n description: 'Reset this ticket and all its dependents',\n },\n epicId: {\n type: 'string',\n description: 'Reset all tickets in this epic',\n },\n allTickets: {\n type: 'boolean',\n description: 'Reset all tickets in the specification',\n },\n resetDependents: {\n type: 'boolean',\n description: 'Also reset tickets that depend on the specified tickets (default: false)',\n },\n includeCompleted: {\n type: 'boolean',\n description: 'Include tickets with done status in the reset (default: false)',\n },\n preserveNotes: {\n type: 'boolean',\n description: 'Keep existing notes on tickets (default: true)',\n },\n clearTestResults: {\n type: 'boolean',\n description: 'Clear test result history (default: false)',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'link_pull_request',\n description: 'Associate a pull request with a ticket',\n inputSchema: {\n type: 'object',\n properties: {\n ticketId: {\n type: 'string',\n description: 'The ID of the ticket',\n },\n prNumber: {\n type: 'number',\n description: 'PR number (provide this or prUrl)',\n },\n prUrl: {\n type: 'string',\n description: 'Full PR URL (GitHub, GitLab, or Bitbucket)',\n },\n title: {\n type: 'string',\n description: 'PR title',\n },\n author: {\n type: 'string',\n description: 'PR author',\n },\n repoUrl: {\n type: 'string',\n description: 'Repository URL (required if using prNumber)',\n },\n },\n required: ['ticketId'],\n },\n },\n\n // ========================================================================\n // Orchestration (2)\n // ========================================================================\n {\n name: 'get_critical_path',\n description: 'Get the critical execution path for a specification.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'Specification ID',\n },\n },\n required: ['specificationId'],\n },\n },\n {\n name: 'get_dependency_tree',\n description: 'Get the full dependency tree for a specification.',\n inputSchema: {\n type: 'object',\n properties: {\n specificationId: {\n type: 'string',\n description: 'Specification ID',\n },\n },\n required: ['specificationId'],\n },\n },\n ];\n\n // Mark the 7 work+review verbs as in_development — mirrors @specforge/core\n // getToolDefinitions so a mcp-local agent also gets the \"coming soon\" affordance\n // (calling them returns a typed stub) instead of believing they are stable.\n const IN_DEVELOPMENT_PLANNED_FOR: Record<string, string> = {\n start_work_session: '0.2.0',\n action_work_session: '0.2.0',\n complete_work_session: '0.2.0',\n reset_work_session: '0.2.0',\n start_review_session: '0.3.0',\n action_review_session: '0.3.0',\n complete_review_session: '0.3.0',\n };\n for (const t of tools) {\n const plannedFor = IN_DEVELOPMENT_PLANNED_FOR[t.name];\n if (plannedFor) {\n t.description =\n `**In development — ships with ${plannedFor}.** Calling returns a typed stub ` +\n `response the client should render as a \"coming soon\" affordance.\\n\\n${t.description}`;\n }\n }\n\n return tools;\n}\n\n/**\n * Tool handler type - processes arguments and returns a result\n */\ntype ToolHandler = (\n apiClient: ApiClient,\n args: Record<string, unknown>\n) => Promise<unknown>;\n\n/**\n * Retry configuration for transient failures\n */\nconst RETRY_CONFIG = {\n maxRetries: 3,\n initialDelayMs: 500,\n maxDelayMs: 5000,\n backoffMultiplier: 2,\n};\n\n/**\n * Transient error patterns that should trigger retry\n */\nconst TRANSIENT_ERROR_PATTERNS = [\n /ETIMEDOUT/i,\n /ECONNRESET/i,\n /ECONNREFUSED/i,\n /socket hang up/i,\n /network error/i,\n /too many requests/i,\n /rate limit/i,\n /5\\d{2}/, // 5xx status codes\n];\n\n/**\n * Check if an error is transient and should be retried\n */\nfunction isTransientError(error: Error): boolean {\n return TRANSIENT_ERROR_PATTERNS.some(pattern =>\n pattern.test(error.message)\n );\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Execute a function with retry logic for transient failures\n */\nasync function withRetry<T>(\n fn: () => Promise<T>,\n toolName: string,\n debug: boolean\n): Promise<T> {\n let lastError: Error | null = null;\n let delay = RETRY_CONFIG.initialDelayMs;\n\n for (let attempt = 1; attempt <= RETRY_CONFIG.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt < RETRY_CONFIG.maxRetries && isTransientError(lastError)) {\n if (debug) {\n console.error(\n `[DEBUG] Tool ${toolName} attempt ${attempt} failed with transient error, retrying in ${delay}ms:`,\n lastError.message\n );\n }\n await sleep(delay);\n delay = Math.min(delay * RETRY_CONFIG.backoffMultiplier, RETRY_CONFIG.maxDelayMs);\n } else {\n break;\n }\n }\n }\n\n throw lastError;\n}\n\n/**\n * Create tool handlers that call the API with proper request formatting\n *\n * @param apiClient - The API client to use for making requests\n * @returns Record of tool handlers keyed by tool name\n */\nexport function createToolHandlers(\n apiClient: ApiClient\n): Record<string, ToolHandler> {\n // Agent `/local` path (M9, approach A): the transport returns the raw M8 body;\n // interpret the envelope here. Lifecycle → unwrap to `agentResponse`; standard\n // error → throw the composed guidance prose (M9.3); raw success → pass through.\n const callLocal = async <T = unknown>(\n op: string,\n args: Record<string, unknown>,\n ): Promise<T> => {\n const body = await apiClient.getTransport().execute<Record<string, unknown>>(op, args);\n if (body && typeof body === 'object') {\n if (body.kind === 'standard_error') {\n // M9.3: the error-guidance composer's `guidance.prose` is the canonical\n // agent-facing message (same verbatim convention as lifecycle guidance);\n // surface it for query-tool errors, falling back to `message` (and to a\n // generic line for INTERNAL, where guidance is always null).\n const guidance = body.guidance as { prose?: unknown } | null | undefined;\n const prose = guidance && typeof guidance.prose === 'string' ? guidance.prose : undefined;\n throw new Error(\n prose ?? (typeof body.message === 'string' ? body.message : `Operation failed: ${op}`),\n );\n }\n if (body.kind === 'lifecycle' && 'agentResponse' in body) {\n return body.agentResponse as T;\n }\n }\n return body as T;\n };\n\n return {\n // ========================================================================\n // Queries — forward the canonical super-tools straight through (the backend\n // owns the `type` dispatch; M9 dropped the old granular-op fan-out).\n // ========================================================================\n get: async (_client, args) => {\n if (!args.type) throw new Error('Missing required argument: type');\n // Project/spec ids inject from config when the agent omits them.\n const withCtx = injectContext(args, ['projectId', 'specificationId']);\n return await callLocal('get', withCtx);\n },\n\n list: async (_client, args) => {\n if (!args.type) throw new Error('Missing required argument: type');\n const withCtx = injectContext(args, ['projectId', 'specificationId']);\n return await callLocal('list', withCtx);\n },\n\n search: async (_client, args) => {\n if (!args.query && !args.files && !args.tags && !args.relatedTo) {\n throw new Error('At least one filter is required: query, files, tags, or relatedTo');\n }\n const withCtx = injectContext(args, ['projectId', 'specificationId']);\n if (!withCtx.projectId && !withCtx.specificationId && !withCtx.epicId) {\n throw new Error('One of projectId, specificationId, or epicId is required. Run \"specforge switch\" or provide explicitly.');\n }\n return await callLocal('search', withCtx);\n },\n\n get_next_actionable_tickets: async (_client, args) => {\n // Inject projectId/specificationId from .specforge.json if not provided\n const argsWithContext = injectContext(args, ['projectId', 'specificationId']);\n\n // Either specificationId or projectId is required (after injection)\n if (!argsWithContext.specificationId && !argsWithContext.projectId) {\n throw new Error('Either specificationId or projectId is required. Set working context with \"specforge switch\" or provide explicitly.');\n }\n return await callLocal('get_next_actionable_tickets', {\n specificationId: argsWithContext.specificationId,\n projectId: argsWithContext.projectId,\n limit: argsWithContext.limit ?? 5,\n });\n },\n\n get_blocked_tickets: async (_client, args) => {\n // Inject specificationId from .specforge.json if not provided\n const argsWithContext = injectContext(args, ['specificationId']);\n\n if (!argsWithContext.specificationId) {\n throw new Error('specificationId is required. Set working context with \"specforge switch\" or provide explicitly.');\n }\n return await callLocal('get_blocked_tickets', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n get_report: async (_client, args) => {\n validateRequired(args, 'type', 'scope', 'scopeId');\n return await callLocal('get_report', {\n type: args.type,\n scope: args.scope,\n scopeId: args.scopeId,\n format: args.format ?? 'json',\n startDate: args.startDate,\n endDate: args.endDate,\n });\n },\n\n // ========================================================================\n // Lifecycle\n // ========================================================================\n // Planning lifecycle (M9.6b) — identity/session injected from the\n // `.specforge` config; SPS persists the session id, a `closed` status\n // clears it. Payloads match the post-M8 boundary (SPS {specificationId};\n // APS {sessionId, operation:{type,...}}; CPS {sessionId}).\n start_planning_session: async (_client, args) => {\n const cfg = tryLoadProjectConfig();\n const specificationId = (args.specificationId as string) ?? cfg?.specificationId;\n if (!specificationId) {\n throw new Error('No active specification. Run `specforge switch <spec-id>` or pass specificationId.');\n }\n // projectId is injected from local config (client-authoritative scope);\n // SPS no longer derives it server-side from the spec row.\n const projectId = (args.projectId as string) ?? cfg?.projectId;\n if (!projectId) {\n throw new Error('No active project. Run `specforge switch <spec-id>` or pass projectId.');\n }\n const agentResponse = await callLocal<{ sessionId?: string }>(\n 'start_planning_session',\n { projectId, specificationId },\n );\n if (agentResponse?.sessionId) {\n saveProjectConfig({ planningSessionId: agentResponse.sessionId });\n appendPlanningSessionRegistry({\n specificationId,\n planningSessionId: agentResponse.sessionId,\n startedAt: new Date().toISOString(),\n });\n }\n return agentResponse;\n },\n\n action_planning_session: async (_client, args) => {\n if (!args.operation || typeof args.operation !== 'object') {\n throw new Error('Missing required argument: operation (e.g. { type: \"get_planning_status\" })');\n }\n const cfg = tryLoadProjectConfig();\n const sessionId = (args.sessionId as string) ?? cfg?.planningSessionId;\n if (!sessionId) {\n throw new Error('No active planning session. Call start_planning_session first.');\n }\n const agentResponse = await callLocal<{ planningStatus?: string }>(\n 'action_planning_session',\n { sessionId, operation: args.operation },\n );\n // Close detection: clear the persisted session id once it closes.\n if (agentResponse?.planningStatus === 'closed' && cfg?.specificationId) {\n saveProjectConfig({ planningSessionId: undefined });\n markPlanningSessionRegistryCompleted({\n specificationId: cfg.specificationId,\n completedAt: new Date().toISOString(),\n });\n }\n return agentResponse;\n },\n\n complete_planning_session: async (_client, args) => {\n const cfg = tryLoadProjectConfig();\n const sessionId = (args.sessionId as string) ?? cfg?.planningSessionId;\n if (!sessionId) {\n throw new Error('No active planning session. Call start_planning_session first.');\n }\n // CPS-success flips to awaiting_human_review (not closed) — keep the id.\n return await callLocal('complete_planning_session', { sessionId });\n },\n\n start_work_session: async (_client, args) => {\n validateRequired(args, 'ticketId');\n return await callLocal('start_work_session', {\n ticketId: args.ticketId,\n });\n },\n\n action_work_session: async (_client, args) => {\n validateRequired(args, 'ticketId');\n return await callLocal('action_work_session', {\n ticketId: args.ticketId,\n steps: args.steps,\n allStepsDone: args.allStepsDone,\n acceptanceCriteria: args.acceptanceCriteria,\n allACValidated: args.allACValidated,\n testResults: args.testResults,\n notes: args.notes,\n filesCreated: args.filesCreated,\n filesModified: args.filesModified,\n filesDeleted: args.filesDeleted,\n discovery: args.discovery,\n blockReason: args.blockReason,\n getTicket: args.getTicket,\n includeFullContext: args.includeFullContext,\n codeSnippetsReviewed: args.codeSnippetsReviewed,\n typeReferencesReviewed: args.typeReferencesReviewed,\n });\n },\n\n complete_work_session: async (_client, args) => {\n validateRequired(args, 'ticketId', 'summary');\n return await callLocal('complete_work_session', {\n ticketId: args.ticketId,\n summary: args.summary,\n filesModified: args.filesModified,\n filesCreated: args.filesCreated,\n filesDeleted: args.filesDeleted,\n actualHours: args.actualHours,\n validation: args.validation,\n });\n },\n\n start_review_session: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('start_review_session', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n action_review_session: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('action_review_session', {\n specificationId: argsWithContext.specificationId,\n reviewSessionId: args.reviewSessionId,\n findingsAddressed: args.findingsAddressed,\n notes: args.notes,\n });\n },\n\n complete_review_session: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('complete_review_session', {\n specificationId: argsWithContext.specificationId,\n reviewSessionId: args.reviewSessionId,\n summary: args.summary,\n confirmAllDismissed: args.confirmAllDismissed,\n });\n },\n\n reopen_specification: async (_client, args) => {\n const argsWithContext = injectContextRequired(args, ['specificationId']);\n return await callLocal('reopen_specification', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n // ========================================================================\n // Mutation\n // ========================================================================\n\n // ========================================================================\n // Utilities\n // ========================================================================\n feedback: async (_client, args) => {\n // M9.7: origin is server-derived from the `X-SpecForge-Origin` header\n // (default `mcp` on the agent transport) — never a request-body `source`.\n return await callLocal('feedback', args);\n },\n\n reset_work_session: async (_client, args) => {\n validateRequired(args, 'specificationId');\n return await callLocal('reset_work_session', {\n specificationId: args.specificationId,\n ticketIds: args.ticketIds,\n fromTicketId: args.fromTicketId,\n epicId: args.epicId,\n allTickets: args.allTickets,\n resetDependents: args.resetDependents,\n includeCompleted: args.includeCompleted,\n preserveNotes: args.preserveNotes,\n clearTestResults: args.clearTestResults,\n });\n },\n\n link_pull_request: async (_client, args) => {\n validateRequired(args, 'ticketId');\n if (!args.prNumber && !args.prUrl) {\n throw new Error('Either prNumber or prUrl must be provided');\n }\n return await callLocal('link_pull_request', {\n ticketId: args.ticketId,\n prNumber: args.prNumber,\n prUrl: args.prUrl,\n title: args.title,\n author: args.author,\n repoUrl: args.repoUrl,\n });\n },\n\n // ========================================================================\n // Orchestration\n // ========================================================================\n get_critical_path: async (_client, args) => {\n const argsWithContext = injectContext(args, ['specificationId']);\n if (!argsWithContext.specificationId) {\n throw new Error('specificationId is required');\n }\n return await callLocal('get_critical_path', {\n specificationId: argsWithContext.specificationId,\n });\n },\n\n get_dependency_tree: async (_client, args) => {\n const argsWithContext = injectContext(args, ['specificationId']);\n if (!argsWithContext.specificationId) {\n throw new Error('specificationId is required');\n }\n return await callLocal('get_dependency_tree', {\n specificationId: argsWithContext.specificationId,\n });\n },\n };\n}\n\n/**\n * Validate that required arguments are present\n * @throws Error if any required argument is missing\n */\nfunction validateRequired(args: Record<string, unknown>, ...required: string[]): void {\n for (const field of required) {\n if (args[field] === undefined || args[field] === null || args[field] === '') {\n throw new Error(`Missing required argument: ${field}`);\n }\n }\n}\n\n// Create a cached instance of tool handlers\nlet cachedHandlers: Record<string, ToolHandler> | null = null;\n\n/**\n * Reset the cached tool handlers (for testing purposes)\n */\nexport function resetToolHandlers(): void {\n cachedHandlers = null;\n}\n\n/**\n * Handle a tool call by routing to the appropriate handler\n *\n * @param apiClient - The API client to use for making requests\n * @param toolName - Name of the tool being called\n * @param args - Arguments passed to the tool\n * @param debug - Whether to enable debug logging\n * @returns Promise resolving to the tool result\n */\nexport async function handleToolCall(\n apiClient: ApiClient,\n toolName: string,\n args: Record<string, unknown>,\n debug: boolean = false\n): Promise<unknown> {\n const startTime = Date.now();\n\n // Create handlers if not cached\n if (!cachedHandlers) {\n cachedHandlers = createToolHandlers(apiClient);\n }\n\n // Get the handler for this tool\n const handler = cachedHandlers[toolName];\n if (!handler) {\n throw new Error(`Unknown tool: ${toolName}`);\n }\n\n if (debug) {\n console.error(`[DEBUG] Calling tool: ${toolName}`, {\n args: JSON.stringify(args),\n });\n }\n\n try {\n // Run comprehensive validation before executing\n validateToolArgs(toolName, args);\n\n // Execute with retry logic\n const result = await withRetry(\n () => handler(apiClient, args),\n toolName,\n debug\n );\n\n const duration = Date.now() - startTime;\n if (debug) {\n console.error(`[DEBUG] Tool ${toolName} completed in ${duration}ms`);\n }\n\n return result;\n } catch (error) {\n const duration = Date.now() - startTime;\n\n // Transform error for proper handling\n const transformedError = transformError(error);\n const message = transformedError.message;\n\n if (debug) {\n console.error(`[DEBUG] Tool ${toolName} failed after ${duration}ms:`, message);\n if (transformedError instanceof ValidationError) {\n console.error(`[DEBUG] Validation field: ${transformedError.field}, code: ${transformedError.code}`);\n }\n }\n\n // Rethrow with context\n if (transformedError instanceof ValidationError) {\n throw transformedError;\n }\n if (transformedError instanceof ApiError) {\n throw transformedError;\n }\n throw new Error(`Tool ${toolName} failed: ${message}`);\n }\n}\n\n/**\n * Handle a tool call and return MCP-formatted response\n * This wraps handleToolCall with proper error formatting for MCP protocol\n */\nexport async function handleToolCallSafe(\n apiClient: ApiClient,\n toolName: string,\n args: Record<string, unknown>,\n debug: boolean = false\n): Promise<unknown | MCPErrorResponse> {\n try {\n return await handleToolCall(apiClient, toolName, args, debug);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return formatMCPError(err);\n }\n}\n\n// Re-export validation utilities for use by other modules\nexport {\n ValidationError,\n ApiError,\n validateToolArgs,\n formatMCPError,\n transformError,\n type MCPErrorResponse,\n} from '../validation/index.js';\n"],"mappings":"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","names":["ValidationError","ApiError","validateToolArgs","formatMCPError","transformError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specforge/canary-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "MCP server for SpecForge - AI agent integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "tsx": "^4.7.0",
30
30
  "typescript": "^5.0.0",
31
31
  "vitest": "4.0.18",
32
- "@specforge/lifecycle": "0.1.18"
32
+ "@specforge/lifecycle": "0.1.23"
33
33
  },
34
34
  "engines": {
35
35
  "node": ">=18.0.0"
@@ -54,7 +54,7 @@
54
54
  "bundleDependencies": [
55
55
  "@specforge/types"
56
56
  ],
57
- "gitHead": "a0298c8b22d384b4b95731e757541e6988d43626",
57
+ "gitHead": "b12eed06f3baacf0f68764aafb785e0602eceda7",
58
58
  "scripts": {
59
59
  "build": "tsup && tsc --emitDeclarationOnly --outDir dist",
60
60
  "typecheck": "tsc --noEmit",