@stackmemoryai/stackmemory 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/src/cli/codex-sm.js +6 -8
  2. package/dist/src/cli/commands/config.js +0 -81
  3. package/dist/src/cli/commands/context-rehydrate.js +133 -47
  4. package/dist/src/cli/commands/db.js +35 -8
  5. package/dist/src/cli/commands/handoff.js +1 -1
  6. package/dist/src/cli/commands/linear.js +9 -0
  7. package/dist/src/cli/commands/ralph.js +2 -2
  8. package/dist/src/cli/commands/setup.js +2 -2
  9. package/dist/src/cli/commands/signup.js +3 -1
  10. package/dist/src/cli/commands/storage-tier.js +26 -8
  11. package/dist/src/cli/index.js +1 -57
  12. package/dist/src/core/config/feature-flags.js +0 -4
  13. package/dist/src/core/context/dual-stack-manager.js +10 -3
  14. package/dist/src/core/context/frame-database.js +32 -0
  15. package/dist/src/core/context/frame-handoff-manager.js +2 -2
  16. package/dist/src/core/context/{refactored-frame-manager.js → frame-manager.js} +3 -3
  17. package/dist/src/core/context/index.js +2 -2
  18. package/dist/src/core/database/sqlite-adapter.js +161 -1
  19. package/dist/src/core/digest/frame-digest-integration.js +1 -1
  20. package/dist/src/core/digest/index.js +1 -1
  21. package/dist/src/core/execution/parallel-executor.js +5 -1
  22. package/dist/src/core/projects/project-isolation.js +18 -4
  23. package/dist/src/core/security/index.js +2 -0
  24. package/dist/src/core/security/input-sanitizer.js +23 -0
  25. package/dist/src/core/utils/update-checker.js +10 -6
  26. package/dist/src/daemon/daemon-config.js +2 -1
  27. package/dist/src/daemon/services/auto-save-service.js +121 -0
  28. package/dist/src/daemon/services/maintenance-service.js +76 -1
  29. package/dist/src/features/sweep/prompt-builder.js +2 -2
  30. package/dist/src/integrations/linear/config.js +3 -1
  31. package/dist/src/integrations/linear/sync.js +18 -5
  32. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +33 -7
  33. package/dist/src/integrations/mcp/handlers/cord-handlers.js +397 -0
  34. package/dist/src/integrations/mcp/handlers/index.js +55 -1
  35. package/dist/src/integrations/mcp/handlers/task-handlers.js +55 -12
  36. package/dist/src/integrations/mcp/handlers/team-handlers.js +211 -0
  37. package/dist/src/integrations/mcp/handlers/trace-handlers.js +25 -9
  38. package/dist/src/integrations/mcp/index.js +2 -2
  39. package/dist/src/integrations/mcp/refactored-server.js +31 -10
  40. package/dist/src/integrations/mcp/tool-definitions.js +215 -1
  41. package/dist/src/integrations/ralph/context/context-budget-manager.js +10 -2
  42. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +54 -22
  43. package/dist/src/integrations/ralph/learning/pattern-learner.js +59 -24
  44. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +81 -35
  45. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +12 -4
  46. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +32 -9
  47. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +25 -8
  48. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +17 -5
  49. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +73 -22
  50. package/dist/src/skills/claude-skills.js +0 -102
  51. package/dist/src/utils/hook-installer.js +8 -0
  52. package/package.json +5 -5
  53. package/scripts/install-claude-hooks-auto.js +8 -0
  54. package/templates/claude-hooks/cord-trace.js +225 -0
  55. package/dist/src/core/config/storage-config.js +0 -114
  56. package/dist/src/core/storage/chromadb-adapter.js +0 -379
  57. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +0 -458
  58. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +0 -409
  59. package/dist/src/skills/repo-ingestion-skill.js +0 -631
  60. package/templates/claude-hooks/chromadb-wrapper +0 -21
  61. /package/dist/src/core/context/{enhanced-rehydration.js → rehydration.js} +0 -0
  62. /package/dist/src/core/digest/{enhanced-hybrid-digest.js → hybrid-digest.js} +0 -0
  63. /package/dist/src/core/session/{enhanced-handoff.js → handoff.js} +0 -0
@@ -0,0 +1,397 @@
1
+ import { fileURLToPath as __fileURLToPath } from 'url';
2
+ import { dirname as __pathDirname } from 'path';
3
+ const __filename = __fileURLToPath(import.meta.url);
4
+ const __dirname = __pathDirname(__filename);
5
+ import { randomUUID } from "crypto";
6
+ import { logger } from "../../../core/monitoring/logger.js";
7
+ class CordHandlers {
8
+ constructor(deps) {
9
+ this.deps = deps;
10
+ }
11
+ MAX_DEPTH = 10;
12
+ MAX_TASKS = 50;
13
+ /**
14
+ * cord_spawn — create a child task with clean context (only blocker results visible)
15
+ */
16
+ async handleCordSpawn(args) {
17
+ return this.createTask(args, "spawn");
18
+ }
19
+ /**
20
+ * cord_fork — create a child task with full sibling context
21
+ */
22
+ async handleCordFork(args) {
23
+ return this.createTask(args, "fork");
24
+ }
25
+ /**
26
+ * cord_complete — mark a task as completed and unblock dependents
27
+ */
28
+ async handleCordComplete(args) {
29
+ try {
30
+ const { task_id, result } = args;
31
+ if (!task_id) throw new Error("task_id is required");
32
+ if (result === void 0 || result === null) {
33
+ throw new Error("result is required");
34
+ }
35
+ const db = this.deps.dbAdapter.getRawDatabase();
36
+ if (!db) throw new Error("Database not available");
37
+ const task = db.prepare("SELECT * FROM cord_tasks WHERE task_id = ?").get(task_id);
38
+ if (!task) throw new Error(`Task not found: ${task_id}`);
39
+ if (task.status === "completed") {
40
+ throw new Error(`Task already completed: ${task_id}`);
41
+ }
42
+ const now = Math.floor(Date.now() / 1e3);
43
+ db.prepare(
44
+ "UPDATE cord_tasks SET status = ?, result = ?, completed_at = ? WHERE task_id = ?"
45
+ ).run("completed", String(result), now, task_id);
46
+ const unblocked = this.checkAndUnblockDependents(db, task_id);
47
+ logger.info("Cord task completed", { task_id, unblocked });
48
+ return {
49
+ content: [
50
+ {
51
+ type: "text",
52
+ text: `Task ${task_id} completed.${unblocked.length > 0 ? ` Unblocked: ${unblocked.join(", ")}` : ""}`
53
+ }
54
+ ],
55
+ metadata: { task_id, status: "completed", unblocked }
56
+ };
57
+ } catch (error) {
58
+ logger.error(
59
+ "Error completing cord task",
60
+ error instanceof Error ? error : new Error(String(error))
61
+ );
62
+ throw error;
63
+ }
64
+ }
65
+ /**
66
+ * cord_ask — create an "ask" task (question with optional options)
67
+ */
68
+ async handleCordAsk(args) {
69
+ try {
70
+ const { question, options, parent_id } = args;
71
+ if (!question) throw new Error("question is required");
72
+ const db = this.deps.dbAdapter.getRawDatabase();
73
+ if (!db) throw new Error("Database not available");
74
+ const projectId = this.getProjectId();
75
+ const runId = this.getRunId();
76
+ const taskId = randomUUID();
77
+ this.checkTaskLimit(db, projectId);
78
+ let depth = 0;
79
+ if (parent_id) {
80
+ depth = this.computeDepth(db, parent_id);
81
+ }
82
+ const prompt = options ? JSON.stringify({ question, options }) : JSON.stringify({ question });
83
+ db.prepare(
84
+ `INSERT INTO cord_tasks (task_id, parent_id, project_id, run_id, goal, prompt, status, context_mode, depth)
85
+ VALUES (?, ?, ?, ?, ?, ?, 'asked', 'ask', ?)`
86
+ ).run(
87
+ taskId,
88
+ parent_id || null,
89
+ projectId,
90
+ runId,
91
+ question,
92
+ prompt,
93
+ depth
94
+ );
95
+ logger.info("Cord ask created", { task_id: taskId });
96
+ return {
97
+ content: [
98
+ {
99
+ type: "text",
100
+ text: `Ask created: ${taskId} \u2014 "${question}"`
101
+ }
102
+ ],
103
+ metadata: {
104
+ task_id: taskId,
105
+ status: "asked",
106
+ context_mode: "ask",
107
+ question,
108
+ options: options || null
109
+ }
110
+ };
111
+ } catch (error) {
112
+ logger.error(
113
+ "Error creating cord ask",
114
+ error instanceof Error ? error : new Error(String(error))
115
+ );
116
+ throw error;
117
+ }
118
+ }
119
+ /**
120
+ * cord_tree — view the task tree with context scoping
121
+ */
122
+ async handleCordTree(args) {
123
+ try {
124
+ const { task_id, include_results = false } = args;
125
+ const db = this.deps.dbAdapter.getRawDatabase();
126
+ if (!db) throw new Error("Database not available");
127
+ const projectId = this.getProjectId();
128
+ let tasks;
129
+ if (task_id) {
130
+ tasks = this.getSubtree(db, task_id);
131
+ } else {
132
+ tasks = db.prepare(
133
+ "SELECT * FROM cord_tasks WHERE project_id = ? ORDER BY depth ASC, created_at ASC"
134
+ ).all(projectId);
135
+ }
136
+ if (tasks.length === 0) {
137
+ return {
138
+ content: [{ type: "text", text: "No cord tasks found." }],
139
+ metadata: { tasks: [] }
140
+ };
141
+ }
142
+ const taskMap = /* @__PURE__ */ new Map();
143
+ for (const t of tasks) taskMap.set(t.task_id, t);
144
+ const allTasks = db.prepare(
145
+ "SELECT * FROM cord_tasks WHERE project_id = ? ORDER BY depth ASC, created_at ASC"
146
+ ).all(projectId);
147
+ const allTaskMap = /* @__PURE__ */ new Map();
148
+ for (const t of allTasks) allTaskMap.set(t.task_id, t);
149
+ const treeNodes = tasks.map((t) => {
150
+ const blockedBy = JSON.parse(t.blocked_by);
151
+ const node = {
152
+ task_id: t.task_id,
153
+ goal: t.goal,
154
+ status: t.status,
155
+ context_mode: t.context_mode,
156
+ depth: t.depth,
157
+ blocked_by: blockedBy,
158
+ parent_id: t.parent_id
159
+ };
160
+ if (include_results && t.result !== null) {
161
+ node.result = t.result;
162
+ }
163
+ node.visible_context = this.computeVisibleContext(
164
+ t,
165
+ allTaskMap,
166
+ include_results
167
+ );
168
+ return node;
169
+ });
170
+ const summary = tasks.map(
171
+ (t) => `${" ".repeat(t.depth)}[${t.status}] ${t.goal}${t.context_mode === "ask" ? " (ask)" : ""}`
172
+ ).join("\n");
173
+ return {
174
+ content: [
175
+ {
176
+ type: "text",
177
+ text: `Cord Tree (${tasks.length} tasks):
178
+ ${summary}`
179
+ }
180
+ ],
181
+ metadata: { tasks: treeNodes }
182
+ };
183
+ } catch (error) {
184
+ logger.error(
185
+ "Error getting cord tree",
186
+ error instanceof Error ? error : new Error(String(error))
187
+ );
188
+ throw error;
189
+ }
190
+ }
191
+ // --- Private helpers ---
192
+ async createTask(args, contextMode) {
193
+ try {
194
+ const { goal, prompt = "", blocked_by = [], parent_id } = args;
195
+ if (!goal) throw new Error("goal is required");
196
+ const db = this.deps.dbAdapter.getRawDatabase();
197
+ if (!db) throw new Error("Database not available");
198
+ const projectId = this.getProjectId();
199
+ const runId = this.getRunId();
200
+ const taskId = randomUUID();
201
+ this.checkTaskLimit(db, projectId);
202
+ let depth = 0;
203
+ if (parent_id) {
204
+ depth = this.computeDepth(db, parent_id);
205
+ }
206
+ const blockerIds = Array.isArray(blocked_by) ? blocked_by : [];
207
+ if (blockerIds.length > 0) {
208
+ this.validateBlockers(db, blockerIds);
209
+ this.detectCircularDeps(db, taskId, blockerIds);
210
+ }
211
+ const status = this.initialStatus(db, blockerIds);
212
+ db.prepare(
213
+ `INSERT INTO cord_tasks (task_id, parent_id, project_id, run_id, goal, prompt, status, context_mode, blocked_by, depth)
214
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
215
+ ).run(
216
+ taskId,
217
+ parent_id || null,
218
+ projectId,
219
+ runId,
220
+ goal,
221
+ prompt,
222
+ status,
223
+ contextMode,
224
+ JSON.stringify(blockerIds),
225
+ depth
226
+ );
227
+ logger.info("Cord task created", {
228
+ task_id: taskId,
229
+ context_mode: contextMode,
230
+ status
231
+ });
232
+ return {
233
+ content: [
234
+ {
235
+ type: "text",
236
+ text: `Task ${taskId} created (${contextMode}, ${status}): ${goal}`
237
+ }
238
+ ],
239
+ metadata: {
240
+ task_id: taskId,
241
+ status,
242
+ context_mode: contextMode,
243
+ depth,
244
+ blocked_by: blockerIds
245
+ }
246
+ };
247
+ } catch (error) {
248
+ logger.error(
249
+ "Error creating cord task",
250
+ error instanceof Error ? error : new Error(String(error))
251
+ );
252
+ throw error;
253
+ }
254
+ }
255
+ checkTaskLimit(db, projectId) {
256
+ const row = db.prepare("SELECT COUNT(*) as count FROM cord_tasks WHERE project_id = ?").get(projectId);
257
+ if (row.count >= this.MAX_TASKS) {
258
+ throw new Error(
259
+ `Task limit reached: ${this.MAX_TASKS} tasks per project`
260
+ );
261
+ }
262
+ }
263
+ computeDepth(db, parentId) {
264
+ const parent = db.prepare("SELECT depth FROM cord_tasks WHERE task_id = ?").get(parentId);
265
+ if (!parent) throw new Error(`Parent task not found: ${parentId}`);
266
+ const depth = parent.depth + 1;
267
+ if (depth >= this.MAX_DEPTH) {
268
+ throw new Error(`Max depth exceeded: ${this.MAX_DEPTH}`);
269
+ }
270
+ return depth;
271
+ }
272
+ validateBlockers(db, blockerIds) {
273
+ for (const id of blockerIds) {
274
+ const exists = db.prepare("SELECT 1 FROM cord_tasks WHERE task_id = ?").get(id);
275
+ if (!exists) throw new Error(`Blocker task not found: ${id}`);
276
+ }
277
+ }
278
+ detectCircularDeps(db, newTaskId, blockerIds) {
279
+ const visited = /* @__PURE__ */ new Set();
280
+ const queue = [...blockerIds];
281
+ while (queue.length > 0) {
282
+ const current = queue.shift();
283
+ if (current === newTaskId) {
284
+ throw new Error("Circular dependency detected");
285
+ }
286
+ if (visited.has(current)) continue;
287
+ visited.add(current);
288
+ const task = db.prepare("SELECT blocked_by FROM cord_tasks WHERE task_id = ?").get(current);
289
+ if (task) {
290
+ const deps = JSON.parse(task.blocked_by);
291
+ for (const dep of deps) {
292
+ if (!visited.has(dep)) queue.push(dep);
293
+ }
294
+ }
295
+ }
296
+ }
297
+ initialStatus(db, blockerIds) {
298
+ if (blockerIds.length === 0) return "active";
299
+ for (const id of blockerIds) {
300
+ const task = db.prepare("SELECT status FROM cord_tasks WHERE task_id = ?").get(id);
301
+ if (!task || task.status !== "completed") return "blocked";
302
+ }
303
+ return "active";
304
+ }
305
+ checkAndUnblockDependents(db, completedTaskId) {
306
+ const allBlocked = db.prepare("SELECT * FROM cord_tasks WHERE status = 'blocked'").all();
307
+ const unblocked = [];
308
+ for (const task of allBlocked) {
309
+ const blockers = JSON.parse(task.blocked_by);
310
+ if (!blockers.includes(completedTaskId)) continue;
311
+ const allDone = blockers.every((bid) => {
312
+ if (bid === completedTaskId) return true;
313
+ const blocker = db.prepare("SELECT status FROM cord_tasks WHERE task_id = ?").get(bid);
314
+ return blocker?.status === "completed";
315
+ });
316
+ if (allDone) {
317
+ db.prepare(
318
+ "UPDATE cord_tasks SET status = 'active' WHERE task_id = ?"
319
+ ).run(task.task_id);
320
+ unblocked.push(task.task_id);
321
+ }
322
+ }
323
+ return unblocked;
324
+ }
325
+ getSubtree(db, rootId) {
326
+ const result = [];
327
+ const queue = [rootId];
328
+ while (queue.length > 0) {
329
+ const current = queue.shift();
330
+ const task = db.prepare("SELECT * FROM cord_tasks WHERE task_id = ?").get(current);
331
+ if (task) {
332
+ result.push(task);
333
+ const children = db.prepare(
334
+ "SELECT task_id FROM cord_tasks WHERE parent_id = ? ORDER BY created_at ASC"
335
+ ).all(current);
336
+ for (const c of children) queue.push(c.task_id);
337
+ }
338
+ }
339
+ return result;
340
+ }
341
+ computeVisibleContext(task, allTaskMap, includeResults) {
342
+ const ctx = { prompt: task.prompt };
343
+ if (task.context_mode === "ask") {
344
+ try {
345
+ const parsed = JSON.parse(task.prompt);
346
+ ctx.question = parsed.question;
347
+ ctx.options = parsed.options || null;
348
+ } catch {
349
+ ctx.question = task.goal;
350
+ }
351
+ if (task.status === "completed" && task.result !== null) {
352
+ ctx.answer = task.result;
353
+ }
354
+ return ctx;
355
+ }
356
+ const blockerIds = JSON.parse(task.blocked_by);
357
+ const blockerResults = [];
358
+ for (const bid of blockerIds) {
359
+ const blocker = allTaskMap.get(bid);
360
+ if (blocker?.status === "completed" && blocker.result !== null) {
361
+ blockerResults.push({
362
+ task_id: bid,
363
+ goal: blocker.goal,
364
+ result: includeResults ? blocker.result : "[completed]"
365
+ });
366
+ }
367
+ }
368
+ if (blockerResults.length > 0) {
369
+ ctx.blocker_results = blockerResults;
370
+ }
371
+ if (task.context_mode === "fork" && task.parent_id) {
372
+ const siblingResults = [];
373
+ for (const [, t] of allTaskMap) {
374
+ if (t.parent_id === task.parent_id && t.task_id !== task.task_id && t.status === "completed" && t.result !== null) {
375
+ siblingResults.push({
376
+ task_id: t.task_id,
377
+ goal: t.goal,
378
+ result: includeResults ? t.result : "[completed]"
379
+ });
380
+ }
381
+ }
382
+ if (siblingResults.length > 0) {
383
+ ctx.sibling_results = siblingResults;
384
+ }
385
+ }
386
+ return ctx;
387
+ }
388
+ getProjectId() {
389
+ return this.deps.dbAdapter.projectId;
390
+ }
391
+ getRunId() {
392
+ return this.deps.frameManager.currentRunId;
393
+ }
394
+ }
395
+ export {
396
+ CordHandlers
397
+ };
@@ -18,6 +18,8 @@ import {
18
18
  import {
19
19
  ProviderHandlers
20
20
  } from "./provider-handlers.js";
21
+ import { TeamHandlers } from "./team-handlers.js";
22
+ import { CordHandlers } from "./cord-handlers.js";
21
23
  import {
22
24
  ContextHandlers as ContextHandlers2
23
25
  } from "./context-handlers.js";
@@ -27,12 +29,16 @@ import {
27
29
  } from "./linear-handlers.js";
28
30
  import { TraceHandlers as TraceHandlers2 } from "./trace-handlers.js";
29
31
  import { ProviderHandlers as ProviderHandlers2 } from "./provider-handlers.js";
32
+ import { TeamHandlers as TeamHandlers2 } from "./team-handlers.js";
33
+ import { CordHandlers as CordHandlers2 } from "./cord-handlers.js";
30
34
  class MCPHandlerFactory {
31
35
  contextHandlers;
32
36
  taskHandlers;
33
37
  linearHandlers;
34
38
  traceHandlers;
35
39
  providerHandlers;
40
+ teamHandlers;
41
+ cordHandlers;
36
42
  constructor(deps) {
37
43
  this.contextHandlers = new ContextHandlers2({
38
44
  frameManager: deps.frameManager
@@ -51,6 +57,16 @@ class MCPHandlerFactory {
51
57
  browserMCP: deps.browserMCP
52
58
  });
53
59
  this.providerHandlers = new ProviderHandlers2();
60
+ if (deps.dbAdapter) {
61
+ this.teamHandlers = new TeamHandlers2({
62
+ frameManager: deps.frameManager,
63
+ dbAdapter: deps.dbAdapter
64
+ });
65
+ this.cordHandlers = new CordHandlers2({
66
+ frameManager: deps.frameManager,
67
+ dbAdapter: deps.dbAdapter
68
+ });
69
+ }
54
70
  }
55
71
  /**
56
72
  * Get handler for a specific tool
@@ -130,6 +146,32 @@ class MCPHandlerFactory {
130
146
  return this.providerHandlers.handleBatchCheck.bind(
131
147
  this.providerHandlers
132
148
  );
149
+ // Team handlers
150
+ case "team_context_get":
151
+ if (!this.teamHandlers) throw new Error("Team tools require dbAdapter");
152
+ return this.teamHandlers.handleTeamContextGet.bind(this.teamHandlers);
153
+ case "team_context_share":
154
+ if (!this.teamHandlers) throw new Error("Team tools require dbAdapter");
155
+ return this.teamHandlers.handleTeamContextShare.bind(this.teamHandlers);
156
+ case "team_search":
157
+ if (!this.teamHandlers) throw new Error("Team tools require dbAdapter");
158
+ return this.teamHandlers.handleTeamSearch.bind(this.teamHandlers);
159
+ // Cord orchestration handlers
160
+ case "cord_spawn":
161
+ if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
162
+ return this.cordHandlers.handleCordSpawn.bind(this.cordHandlers);
163
+ case "cord_fork":
164
+ if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
165
+ return this.cordHandlers.handleCordFork.bind(this.cordHandlers);
166
+ case "cord_complete":
167
+ if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
168
+ return this.cordHandlers.handleCordComplete.bind(this.cordHandlers);
169
+ case "cord_ask":
170
+ if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
171
+ return this.cordHandlers.handleCordAsk.bind(this.cordHandlers);
172
+ case "cord_tree":
173
+ if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
174
+ return this.cordHandlers.handleCordTree.bind(this.cordHandlers);
133
175
  default:
134
176
  throw new Error(`Unknown tool: ${toolName}`);
135
177
  }
@@ -167,7 +209,17 @@ class MCPHandlerFactory {
167
209
  // Provider tools (conditionally active)
168
210
  "delegate_to_model",
169
211
  "batch_submit",
170
- "batch_check"
212
+ "batch_check",
213
+ // Team tools
214
+ "team_context_get",
215
+ "team_context_share",
216
+ "team_search",
217
+ // Cord orchestration tools
218
+ "cord_spawn",
219
+ "cord_fork",
220
+ "cord_complete",
221
+ "cord_ask",
222
+ "cord_tree"
171
223
  ];
172
224
  }
173
225
  /**
@@ -179,10 +231,12 @@ class MCPHandlerFactory {
179
231
  }
180
232
  export {
181
233
  ContextHandlers,
234
+ CordHandlers,
182
235
  DiscoveryHandlers,
183
236
  LinearHandlers,
184
237
  MCPHandlerFactory,
185
238
  ProviderHandlers,
186
239
  TaskHandlers,
240
+ TeamHandlers,
187
241
  TraceHandlers
188
242
  };
@@ -12,7 +12,13 @@ class TaskHandlers {
12
12
  */
13
13
  async handleCreateTask(args) {
14
14
  try {
15
- const { title, description, priority = "medium", tags = [], parent_id } = args;
15
+ const {
16
+ title,
17
+ description,
18
+ priority = "medium",
19
+ tags = [],
20
+ parent_id
21
+ } = args;
16
22
  if (!title) {
17
23
  throw new Error("Task title is required");
18
24
  }
@@ -40,7 +46,10 @@ class TaskHandlers {
40
46
  }
41
47
  };
42
48
  } catch (error) {
43
- logger.error("Error creating task", error instanceof Error ? error : new Error(String(error)));
49
+ logger.error(
50
+ "Error creating task",
51
+ error instanceof Error ? error : new Error(String(error))
52
+ );
44
53
  throw error;
45
54
  }
46
55
  }
@@ -57,12 +66,20 @@ class TaskHandlers {
57
66
  throw new Error("Status is required");
58
67
  }
59
68
  const validStatus = this.validateStatus(status);
60
- await this.deps.taskStore.updateTaskStatus(task_id, validStatus, progress);
69
+ await this.deps.taskStore.updateTaskStatus(
70
+ task_id,
71
+ validStatus,
72
+ progress
73
+ );
61
74
  const task = await this.deps.taskStore.getTask(task_id);
62
75
  if (!task) {
63
76
  throw new Error(`Task not found: ${task_id}`);
64
77
  }
65
- logger.info("Updated task status", { taskId: task_id, status: validStatus, progress });
78
+ logger.info("Updated task status", {
79
+ taskId: task_id,
80
+ status: validStatus,
81
+ progress
82
+ });
66
83
  return {
67
84
  content: [
68
85
  {
@@ -77,7 +94,10 @@ class TaskHandlers {
77
94
  }
78
95
  };
79
96
  } catch (error) {
80
- logger.error("Error updating task status", error instanceof Error ? error : new Error(String(error)));
97
+ logger.error(
98
+ "Error updating task status",
99
+ error instanceof Error ? error : new Error(String(error))
100
+ );
81
101
  throw error;
82
102
  }
83
103
  }
@@ -138,7 +158,10 @@ ${summaryText}`
138
158
  }
139
159
  };
140
160
  } catch (error) {
141
- logger.error("Error getting active tasks", error instanceof Error ? error : new Error(String(error)));
161
+ logger.error(
162
+ "Error getting active tasks",
163
+ error instanceof Error ? error : new Error(String(error))
164
+ );
142
165
  throw error;
143
166
  }
144
167
  }
@@ -172,7 +195,10 @@ ${Object.entries(metrics.by_status || {}).map(([status, count]) => `- ${status}:
172
195
  metadata: metrics
173
196
  };
174
197
  } catch (error) {
175
- logger.error("Error getting task metrics", error instanceof Error ? error : new Error(String(error)));
198
+ logger.error(
199
+ "Error getting task metrics",
200
+ error instanceof Error ? error : new Error(String(error))
201
+ );
176
202
  throw error;
177
203
  }
178
204
  }
@@ -191,7 +217,11 @@ ${Object.entries(metrics.by_status || {}).map(([status, count]) => `- ${status}:
191
217
  if (!task || !dependencyTask) {
192
218
  throw new Error("One or both tasks not found");
193
219
  }
194
- logger.info("Added task dependency", { taskId: task_id, dependsOn: depends_on, type: dependency_type });
220
+ logger.info("Added task dependency", {
221
+ taskId: task_id,
222
+ dependsOn: depends_on,
223
+ type: dependency_type
224
+ });
195
225
  return {
196
226
  content: [
197
227
  {
@@ -206,7 +236,10 @@ ${Object.entries(metrics.by_status || {}).map(([status, count]) => `- ${status}:
206
236
  }
207
237
  };
208
238
  } catch (error) {
209
- logger.error("Error adding task dependency", error instanceof Error ? error : new Error(String(error)));
239
+ logger.error(
240
+ "Error adding task dependency",
241
+ error instanceof Error ? error : new Error(String(error))
242
+ );
210
243
  throw error;
211
244
  }
212
245
  }
@@ -217,7 +250,9 @@ ${Object.entries(metrics.by_status || {}).map(([status, count]) => `- ${status}:
217
250
  const validPriorities = ["low", "medium", "high", "urgent"];
218
251
  const normalizedPriority = priority.toLowerCase();
219
252
  if (!validPriorities.includes(normalizedPriority)) {
220
- throw new Error(`Invalid priority: ${priority}. Must be one of: ${validPriorities.join(", ")}`);
253
+ throw new Error(
254
+ `Invalid priority: ${priority}. Must be one of: ${validPriorities.join(", ")}`
255
+ );
221
256
  }
222
257
  return normalizedPriority;
223
258
  }
@@ -225,10 +260,18 @@ ${Object.entries(metrics.by_status || {}).map(([status, count]) => `- ${status}:
225
260
  * Validate task status
226
261
  */
227
262
  validateStatus(status) {
228
- const validStatuses = ["pending", "in_progress", "blocked", "completed", "cancelled"];
263
+ const validStatuses = [
264
+ "pending",
265
+ "in_progress",
266
+ "blocked",
267
+ "completed",
268
+ "cancelled"
269
+ ];
229
270
  const normalizedStatus = status.toLowerCase().replace("_", "-");
230
271
  if (!validStatuses.includes(normalizedStatus)) {
231
- throw new Error(`Invalid status: ${status}. Must be one of: ${validStatuses.join(", ")}`);
272
+ throw new Error(
273
+ `Invalid status: ${status}. Must be one of: ${validStatuses.join(", ")}`
274
+ );
232
275
  }
233
276
  return normalizedStatus;
234
277
  }