@vheins/local-memory-mcp 0.8.42 → 0.8.44

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.
@@ -3,8 +3,8 @@ import { fileURLToPath } from "url";
3
3
  import path from "path";
4
4
  var __dirname = path.dirname(fileURLToPath(import.meta.url));
5
5
  var pkgVersion = "0.1.0";
6
- if ("0.8.42") {
7
- pkgVersion = "0.8.42";
6
+ if ("0.8.44") {
7
+ pkgVersion = "0.8.44";
8
8
  } else {
9
9
  let searchDir = __dirname;
10
10
  for (let i = 0; i < 5; i++) {
@@ -305,6 +305,28 @@ var MigrationManager = class {
305
305
  CREATE INDEX IF NOT EXISTS idx_task_comments_repo ON task_comments(repo);
306
306
  CREATE INDEX IF NOT EXISTS idx_task_comments_created_at ON task_comments(created_at DESC);
307
307
 
308
+ CREATE TABLE IF NOT EXISTS coding_standards (
309
+ id TEXT PRIMARY KEY,
310
+ title TEXT NOT NULL,
311
+ content TEXT NOT NULL,
312
+ context TEXT,
313
+ version TEXT,
314
+ language TEXT,
315
+ stack TEXT,
316
+ is_global INTEGER NOT NULL DEFAULT 0,
317
+ repo TEXT,
318
+ tags TEXT,
319
+ metadata TEXT,
320
+ created_at TEXT NOT NULL,
321
+ updated_at TEXT NOT NULL,
322
+ agent TEXT NOT NULL DEFAULT 'unknown',
323
+ model TEXT NOT NULL DEFAULT 'unknown'
324
+ );
325
+
326
+ CREATE INDEX IF NOT EXISTS idx_coding_standards_repo ON coding_standards(repo);
327
+ CREATE INDEX IF NOT EXISTS idx_coding_standards_is_global ON coding_standards(is_global);
328
+ CREATE INDEX IF NOT EXISTS idx_coding_standards_language ON coding_standards(language);
329
+
308
330
  CREATE TABLE IF NOT EXISTS memories_archive (
309
331
  id TEXT PRIMARY KEY,
310
332
  repo TEXT NOT NULL,
@@ -340,6 +362,45 @@ var MigrationManager = class {
340
362
 
341
363
  CREATE INDEX IF NOT EXISTS idx_action_log_repo ON action_log(repo);
342
364
  CREATE INDEX IF NOT EXISTS idx_action_log_created_at ON action_log(created_at);
365
+
366
+ CREATE TABLE IF NOT EXISTS handoffs (
367
+ id TEXT PRIMARY KEY,
368
+ repo TEXT NOT NULL,
369
+ from_agent TEXT NOT NULL,
370
+ to_agent TEXT,
371
+ task_id TEXT,
372
+ summary TEXT NOT NULL,
373
+ context TEXT NOT NULL DEFAULT '{}',
374
+ status TEXT NOT NULL DEFAULT 'pending',
375
+ created_at TEXT NOT NULL,
376
+ updated_at TEXT NOT NULL,
377
+ expires_at TEXT,
378
+ FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE SET NULL
379
+ );
380
+
381
+ CREATE INDEX IF NOT EXISTS idx_handoffs_repo ON handoffs(repo);
382
+ CREATE INDEX IF NOT EXISTS idx_handoffs_status ON handoffs(status);
383
+ CREATE INDEX IF NOT EXISTS idx_handoffs_from_agent ON handoffs(from_agent);
384
+ CREATE INDEX IF NOT EXISTS idx_handoffs_to_agent ON handoffs(to_agent);
385
+ CREATE INDEX IF NOT EXISTS idx_handoffs_task_id ON handoffs(task_id);
386
+ CREATE INDEX IF NOT EXISTS idx_handoffs_created_at ON handoffs(created_at);
387
+
388
+ CREATE TABLE IF NOT EXISTS claims (
389
+ id TEXT PRIMARY KEY,
390
+ repo TEXT NOT NULL,
391
+ task_id TEXT NOT NULL,
392
+ agent TEXT NOT NULL,
393
+ role TEXT NOT NULL DEFAULT 'unknown',
394
+ claimed_at TEXT NOT NULL,
395
+ released_at TEXT,
396
+ metadata TEXT NOT NULL DEFAULT '{}',
397
+ FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
398
+ );
399
+
400
+ CREATE INDEX IF NOT EXISTS idx_claims_repo ON claims(repo);
401
+ CREATE INDEX IF NOT EXISTS idx_claims_task_id ON claims(task_id);
402
+ CREATE INDEX IF NOT EXISTS idx_claims_agent ON claims(agent);
403
+ CREATE INDEX IF NOT EXISTS idx_claims_claimed_at ON claims(claimed_at);
343
404
  `);
344
405
  const columnsToAdd = [
345
406
  { name: "title", table: "memories", definition: "ALTER TABLE memories ADD COLUMN title TEXT" },
@@ -2021,6 +2082,272 @@ var SummaryEntity = class extends BaseEntity {
2021
2082
  }
2022
2083
  };
2023
2084
 
2085
+ // src/mcp/entities/standard.ts
2086
+ var StandardEntity = class extends BaseEntity {
2087
+ insert(entry) {
2088
+ this.run(
2089
+ `INSERT INTO coding_standards (
2090
+ id, title, content, context, version, language, stack,
2091
+ is_global, repo, tags, metadata, created_at, updated_at, agent, model
2092
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2093
+ [
2094
+ entry.id,
2095
+ entry.title,
2096
+ entry.content,
2097
+ entry.context,
2098
+ entry.version,
2099
+ entry.language ?? null,
2100
+ entry.stack.length > 0 ? JSON.stringify(entry.stack) : null,
2101
+ entry.is_global ? 1 : 0,
2102
+ entry.repo ?? null,
2103
+ entry.tags.length > 0 ? JSON.stringify(entry.tags) : null,
2104
+ Object.keys(entry.metadata).length > 0 ? JSON.stringify(entry.metadata) : null,
2105
+ entry.created_at,
2106
+ entry.updated_at,
2107
+ entry.agent,
2108
+ entry.model
2109
+ ]
2110
+ );
2111
+ }
2112
+ getById(id) {
2113
+ const row = this.get("SELECT * FROM coding_standards WHERE id = ?", [id]);
2114
+ return row ? this.rowToEntry(row) : null;
2115
+ }
2116
+ search(options) {
2117
+ const { query, context, language, stack, repo, is_global, limit = 20, offset = 0 } = options;
2118
+ const where = [];
2119
+ const params = [];
2120
+ if (query) {
2121
+ where.push("(title LIKE ? OR content LIKE ? OR context LIKE ?)");
2122
+ params.push(`%${query}%`, `%${query}%`, `%${query}%`);
2123
+ }
2124
+ if (context) {
2125
+ where.push("context = ?");
2126
+ params.push(context);
2127
+ }
2128
+ if (language) {
2129
+ where.push("language = ?");
2130
+ params.push(language);
2131
+ }
2132
+ if (stack) {
2133
+ where.push("stack LIKE ?");
2134
+ params.push(`%${stack}%`);
2135
+ }
2136
+ if (repo !== void 0) {
2137
+ where.push("(repo = ? OR is_global = 1)");
2138
+ params.push(repo);
2139
+ }
2140
+ if (is_global !== void 0) {
2141
+ where.push("is_global = ?");
2142
+ params.push(is_global ? 1 : 0);
2143
+ }
2144
+ const whereClause = where.length > 0 ? `WHERE ${where.join(" AND ")}` : "";
2145
+ const sql = `SELECT * FROM coding_standards ${whereClause} ORDER BY created_at DESC LIMIT ? OFFSET ?`;
2146
+ params.push(limit, offset);
2147
+ const rows = this.all(sql, params);
2148
+ return rows.map((r) => this.rowToEntry(r));
2149
+ }
2150
+ update(id, updates) {
2151
+ const fields = [];
2152
+ const values = [];
2153
+ Object.keys(updates).forEach((key) => {
2154
+ const k = key;
2155
+ const val = updates[k];
2156
+ if (val !== void 0) {
2157
+ if (k === "stack" || k === "tags") {
2158
+ fields.push(`${k} = ?`);
2159
+ values.push(Array.isArray(val) ? JSON.stringify(val) : val);
2160
+ } else if (k === "metadata") {
2161
+ fields.push(`${k} = ?`);
2162
+ values.push(typeof val === "object" ? JSON.stringify(val) : val);
2163
+ } else if (k === "is_global") {
2164
+ fields.push(`${k} = ?`);
2165
+ values.push(val ? 1 : 0);
2166
+ } else if (k !== "id" && k !== "created_at") {
2167
+ fields.push(`${k} = ?`);
2168
+ values.push(val);
2169
+ }
2170
+ }
2171
+ });
2172
+ if (fields.length === 0) return;
2173
+ fields.push("updated_at = ?");
2174
+ values.push((/* @__PURE__ */ new Date()).toISOString());
2175
+ values.push(id);
2176
+ this.run(`UPDATE coding_standards SET ${fields.join(", ")} WHERE id = ?`, values);
2177
+ }
2178
+ delete(id) {
2179
+ this.run("DELETE FROM coding_standards WHERE id = ?", [id]);
2180
+ }
2181
+ rowToEntry(row) {
2182
+ return {
2183
+ id: row.id,
2184
+ title: row.title,
2185
+ content: row.content,
2186
+ context: row.context,
2187
+ version: row.version,
2188
+ language: row.language ?? null,
2189
+ stack: this.safeJSONParse(row.stack, []),
2190
+ is_global: row.is_global === 1,
2191
+ repo: row.repo ?? null,
2192
+ tags: this.safeJSONParse(row.tags, []),
2193
+ metadata: this.safeJSONParse(row.metadata, {}),
2194
+ created_at: row.created_at,
2195
+ updated_at: row.updated_at,
2196
+ agent: row.agent,
2197
+ model: row.model
2198
+ };
2199
+ }
2200
+ };
2201
+
2202
+ // src/mcp/entities/handoff.ts
2203
+ import { randomUUID } from "crypto";
2204
+ var HandoffEntity = class extends BaseEntity {
2205
+ rowToHandoff(row) {
2206
+ return {
2207
+ id: row.id,
2208
+ repo: row.repo,
2209
+ from_agent: row.from_agent,
2210
+ to_agent: row.to_agent ?? null,
2211
+ task_id: row.task_id ?? null,
2212
+ summary: row.summary,
2213
+ context: this.safeJSONParse(row.context, {}),
2214
+ status: row.status,
2215
+ created_at: row.created_at,
2216
+ updated_at: row.updated_at,
2217
+ expires_at: row.expires_at ?? null
2218
+ };
2219
+ }
2220
+ rowToClaim(row) {
2221
+ return {
2222
+ id: row.id,
2223
+ repo: row.repo,
2224
+ task_id: row.task_id,
2225
+ agent: row.agent,
2226
+ role: row.role,
2227
+ claimed_at: row.claimed_at,
2228
+ released_at: row.released_at ?? null,
2229
+ metadata: this.safeJSONParse(row.metadata, {})
2230
+ };
2231
+ }
2232
+ createHandoff(params) {
2233
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2234
+ const id = randomUUID();
2235
+ this.run(
2236
+ `INSERT INTO handoffs (id, repo, from_agent, to_agent, task_id, summary, context, status, created_at, updated_at, expires_at)
2237
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2238
+ [
2239
+ id,
2240
+ params.repo,
2241
+ params.from_agent,
2242
+ params.to_agent ?? null,
2243
+ params.task_id ?? null,
2244
+ params.summary,
2245
+ JSON.stringify(params.context ?? {}),
2246
+ "pending",
2247
+ now,
2248
+ now,
2249
+ params.expires_at ?? null
2250
+ ]
2251
+ );
2252
+ return this.rowToHandoff(this.get("SELECT * FROM handoffs WHERE id = ?", [id]));
2253
+ }
2254
+ listHandoffs(params) {
2255
+ const conditions = ["repo = ?"];
2256
+ const values = [params.repo];
2257
+ if (params.status) {
2258
+ conditions.push("status = ?");
2259
+ values.push(params.status);
2260
+ }
2261
+ if (params.to_agent) {
2262
+ conditions.push("to_agent = ?");
2263
+ values.push(params.to_agent);
2264
+ }
2265
+ if (params.from_agent) {
2266
+ conditions.push("from_agent = ?");
2267
+ values.push(params.from_agent);
2268
+ }
2269
+ const limit = params.limit ?? 50;
2270
+ const offset = params.offset ?? 0;
2271
+ values.push(limit, offset);
2272
+ const rows = this.all(
2273
+ `SELECT * FROM handoffs WHERE ${conditions.join(" AND ")} ORDER BY created_at DESC LIMIT ? OFFSET ?`,
2274
+ values
2275
+ );
2276
+ return rows.map((r) => this.rowToHandoff(r));
2277
+ }
2278
+ getHandoffById(id) {
2279
+ const row = this.get("SELECT * FROM handoffs WHERE id = ?", [id]);
2280
+ return row ? this.rowToHandoff(row) : null;
2281
+ }
2282
+ updateHandoffStatus(id, status) {
2283
+ const result = this.run("UPDATE handoffs SET status = ?, updated_at = ? WHERE id = ?", [
2284
+ status,
2285
+ (/* @__PURE__ */ new Date()).toISOString(),
2286
+ id
2287
+ ]);
2288
+ return result.changes > 0;
2289
+ }
2290
+ claimTask(params) {
2291
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2292
+ const id = randomUUID();
2293
+ this.run(
2294
+ "UPDATE claims SET released_at = ? WHERE task_id = ? AND released_at IS NULL",
2295
+ [now, params.task_id]
2296
+ );
2297
+ this.run(
2298
+ `INSERT INTO claims (id, repo, task_id, agent, role, claimed_at, released_at, metadata)
2299
+ VALUES (?, ?, ?, ?, ?, ?, NULL, ?)`,
2300
+ [
2301
+ id,
2302
+ params.repo,
2303
+ params.task_id,
2304
+ params.agent,
2305
+ params.role ?? "unknown",
2306
+ now,
2307
+ JSON.stringify(params.metadata ?? {})
2308
+ ]
2309
+ );
2310
+ return this.rowToClaim(this.get("SELECT * FROM claims WHERE id = ?", [id]));
2311
+ }
2312
+ getClaim(task_id) {
2313
+ const row = this.get(
2314
+ "SELECT * FROM claims WHERE task_id = ? AND released_at IS NULL ORDER BY claimed_at DESC LIMIT 1",
2315
+ [task_id]
2316
+ );
2317
+ return row ? this.rowToClaim(row) : null;
2318
+ }
2319
+ releaseClaim(task_id, agent) {
2320
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2321
+ let sql = "UPDATE claims SET released_at = ? WHERE task_id = ? AND released_at IS NULL";
2322
+ const params = [now, task_id];
2323
+ if (agent) {
2324
+ sql += " AND agent = ?";
2325
+ params.push(agent);
2326
+ }
2327
+ const result = this.run(sql, params);
2328
+ return result.changes > 0;
2329
+ }
2330
+ listClaims(params) {
2331
+ const conditions = ["repo = ?"];
2332
+ const values = [params.repo];
2333
+ if (params.agent) {
2334
+ conditions.push("agent = ?");
2335
+ values.push(params.agent);
2336
+ }
2337
+ if (params.active_only) {
2338
+ conditions.push("released_at IS NULL");
2339
+ }
2340
+ const limit = params.limit ?? 50;
2341
+ const offset = params.offset ?? 0;
2342
+ values.push(limit, offset);
2343
+ const rows = this.all(
2344
+ `SELECT * FROM claims WHERE ${conditions.join(" AND ")} ORDER BY claimed_at DESC LIMIT ? OFFSET ?`,
2345
+ values
2346
+ );
2347
+ return rows.map((r) => this.rowToClaim(r));
2348
+ }
2349
+ };
2350
+
2024
2351
  // src/mcp/storage/write-lock.ts
2025
2352
  import lockfile from "proper-lockfile";
2026
2353
  import path2 from "path";
@@ -2104,6 +2431,8 @@ var SQLiteStore = class _SQLiteStore {
2104
2431
  actions;
2105
2432
  system;
2106
2433
  summaries;
2434
+ standards;
2435
+ handoffs;
2107
2436
  lock;
2108
2437
  dbPathInstance;
2109
2438
  constructor(dbPath) {
@@ -2132,6 +2461,8 @@ var SQLiteStore = class _SQLiteStore {
2132
2461
  this.actions = new ActionEntity(this.db);
2133
2462
  this.system = new SystemEntity(this.db);
2134
2463
  this.summaries = new SummaryEntity(this.db);
2464
+ this.standards = new StandardEntity(this.db);
2465
+ this.handoffs = new HandoffEntity(this.db);
2135
2466
  this.lock = new WriteLock(finalPath);
2136
2467
  }
2137
2468
  /**
@@ -2347,8 +2678,6 @@ var MemoryTypeSchema = z.enum([
2347
2678
  "decision",
2348
2679
  "mistake",
2349
2680
  "pattern",
2350
- "agent_handoff",
2351
- "agent_registered",
2352
2681
  "file_claim",
2353
2682
  "task_archive"
2354
2683
  ]);
@@ -2555,6 +2884,68 @@ var TaskGetSchema = z.object({
2555
2884
  }).refine((data) => data.id !== void 0 || data.task_code !== void 0, {
2556
2885
  message: "Either id or task_code must be provided"
2557
2886
  });
2887
+ var HandoffStatusSchema = z.enum(["pending", "accepted", "rejected", "expired"]);
2888
+ var HandoffCreateSchema = z.object({
2889
+ repo: z.string().min(1).transform(normalizeRepo),
2890
+ from_agent: z.string().min(1),
2891
+ to_agent: z.string().min(1).optional(),
2892
+ task_id: z.string().uuid().optional(),
2893
+ task_code: z.string().optional(),
2894
+ summary: z.string().min(1),
2895
+ context: z.record(z.string(), z.any()).optional(),
2896
+ expires_at: z.string().optional(),
2897
+ structured: z.boolean().default(false)
2898
+ }).refine((data) => !(data.task_id && data.task_code), {
2899
+ message: "Provide either task_id or task_code, not both"
2900
+ });
2901
+ var HandoffListSchema = z.object({
2902
+ repo: z.string().min(1).transform(normalizeRepo),
2903
+ status: HandoffStatusSchema.optional(),
2904
+ from_agent: z.string().min(1).optional(),
2905
+ to_agent: z.string().min(1).optional(),
2906
+ limit: z.number().min(1).max(100).default(20),
2907
+ offset: z.number().min(0).default(0),
2908
+ structured: z.boolean().default(false)
2909
+ });
2910
+ var TaskClaimSchema = z.object({
2911
+ repo: z.string().min(1).transform(normalizeRepo),
2912
+ task_id: z.string().uuid().optional(),
2913
+ task_code: z.string().optional(),
2914
+ agent: z.string().min(1),
2915
+ role: z.string().optional(),
2916
+ metadata: z.record(z.string(), z.any()).optional(),
2917
+ structured: z.boolean().default(false)
2918
+ }).refine((data) => data.task_id !== void 0 || data.task_code !== void 0, {
2919
+ message: "Either task_id or task_code must be provided"
2920
+ }).refine((data) => !(data.task_id && data.task_code), {
2921
+ message: "Provide either task_id or task_code, not both"
2922
+ });
2923
+ var StandardStoreSchema = z.object({
2924
+ name: z.string().min(3).max(255),
2925
+ content: z.string().min(10),
2926
+ context: z.string().optional(),
2927
+ version: z.string().optional(),
2928
+ language: z.string().optional(),
2929
+ stack: z.array(z.string()).optional(),
2930
+ repo: z.string().optional(),
2931
+ is_global: z.boolean().optional(),
2932
+ tags: z.array(z.string()).optional(),
2933
+ metadata: z.record(z.string(), z.any()).optional(),
2934
+ agent: z.string().optional(),
2935
+ model: z.string().optional(),
2936
+ structured: z.boolean().default(false)
2937
+ });
2938
+ var StandardSearchSchema = z.object({
2939
+ query: z.string().optional(),
2940
+ stack: z.array(z.string()).optional(),
2941
+ language: z.string().optional(),
2942
+ version: z.string().optional(),
2943
+ repo: z.string().optional(),
2944
+ is_global: z.boolean().optional(),
2945
+ limit: z.number().min(1).max(100).default(20),
2946
+ offset: z.number().min(0).default(0),
2947
+ structured: z.boolean().default(false)
2948
+ });
2558
2949
  var TOOL_DEFINITIONS = [
2559
2950
  {
2560
2951
  name: "memory-synthesize",
@@ -2649,14 +3040,14 @@ var TOOL_DEFINITIONS = [
2649
3040
  {
2650
3041
  name: "memory-detail",
2651
3042
  title: "Memory Detail",
2652
- description: "Fetch full details of a specific memory by ID. Use this when you have a memory ID (e.g. from search results) and need to read the full content.",
3043
+ description: "Fetch full details of a specific memory by ID or short code. Use after memory-recap or memory-search when a pointer row is relevant and full content is needed.",
2653
3044
  inputSchema: {
2654
3045
  type: "object",
2655
3046
  properties: {
2656
- id: { type: "string", format: "uuid", description: "Memory entry ID" },
3047
+ id: { type: "string", format: "uuid", description: "Memory entry ID. Optional if code is provided." },
3048
+ code: { type: "string", description: "Short memory code. Optional if id is provided." },
2657
3049
  structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
2658
- },
2659
- required: ["id"]
3050
+ }
2660
3051
  }
2661
3052
  },
2662
3053
  {
@@ -2698,8 +3089,6 @@ var TOOL_DEFINITIONS = [
2698
3089
  "decision",
2699
3090
  "mistake",
2700
3091
  "pattern",
2701
- "agent_handoff",
2702
- "agent_registered",
2703
3092
  "file_claim",
2704
3093
  "task_archive"
2705
3094
  ],
@@ -2828,8 +3217,6 @@ var TOOL_DEFINITIONS = [
2828
3217
  "decision",
2829
3218
  "mistake",
2830
3219
  "pattern",
2831
- "agent_handoff",
2832
- "agent_registered",
2833
3220
  "file_claim",
2834
3221
  "task_archive"
2835
3222
  ]
@@ -2892,8 +3279,6 @@ var TOOL_DEFINITIONS = [
2892
3279
  "decision",
2893
3280
  "mistake",
2894
3281
  "pattern",
2895
- "agent_handoff",
2896
- "agent_registered",
2897
3282
  "file_claim",
2898
3283
  "task_archive"
2899
3284
  ]
@@ -3024,7 +3409,7 @@ var TOOL_DEFINITIONS = [
3024
3409
  {
3025
3410
  name: "memory-recap",
3026
3411
  title: "Memory Recap",
3027
- description: "AGGREGATED OVERVIEW LAYER: Returns stats (counts by type) and a pointer table of top memories [id, title, type, importance]. NO content. Use for orientation only \u2014 retrieve full memory via memory-detail.",
3412
+ description: "AGGREGATED OVERVIEW LAYER: Returns stats (counts by type) and a pointer table of top memories [id, code, title, type, importance]. NO content. Use for orientation only \u2014 retrieve full memory via memory-detail.",
3028
3413
  annotations: {
3029
3414
  readOnlyHint: true,
3030
3415
  idempotentHint: true,
@@ -3067,12 +3452,12 @@ var TOOL_DEFINITIONS = [
3067
3452
  stats: {
3068
3453
  type: "object",
3069
3454
  properties: {
3070
- by_type: {
3455
+ byType: {
3071
3456
  type: "object",
3072
3457
  description: "Count of active memories per type (e.g. { decision: 3, code_fact: 7 })"
3073
3458
  }
3074
3459
  },
3075
- required: ["by_type"]
3460
+ required: ["byType"]
3076
3461
  },
3077
3462
  top: {
3078
3463
  type: "object",
@@ -3080,12 +3465,12 @@ var TOOL_DEFINITIONS = [
3080
3465
  columns: {
3081
3466
  type: "array",
3082
3467
  items: { type: "string" },
3083
- description: "Column names: [id, title, type, importance]"
3468
+ description: "Column names: [id, code, title, type, importance]"
3084
3469
  },
3085
3470
  rows: {
3086
3471
  type: "array",
3087
3472
  items: { type: "array" },
3088
- description: "Each row: [id, title, type, importance]. Fetch full content via memory-detail"
3473
+ description: "Each row: [id, code, title, type, importance]. Fetch full content via memory-detail"
3089
3474
  }
3090
3475
  },
3091
3476
  required: ["columns", "rows"]
@@ -3279,7 +3664,7 @@ var TOOL_DEFINITIONS = [
3279
3664
  {
3280
3665
  name: "task-list",
3281
3666
  title: "Task List",
3282
- description: "PRIMARY navigation and search tool for tasks. Returns a compact tabular list of tasks (id, task_code, title, status, priority, updated_at). Defaults to in_progress and pending tasks. Use 'query' to filter by code, title, or description. Use 'status' (comma-separated) for specific filters. AGENTS: call this once at start, pick ONE task, then call task-detail.",
3667
+ description: "PRIMARY navigation and search tool for tasks. Returns a compact tabular list of tasks (id, task_code, title, status, priority, updated_at, comments_count). Defaults to in_progress and pending tasks. Use 'query' to filter by code, title, or description. Use 'status' (comma-separated) for specific filters. AGENTS: call this once at start, pick ONE task, then call task-detail.",
3283
3668
  annotations: {
3284
3669
  readOnlyHint: true,
3285
3670
  idempotentHint: true,
@@ -3351,6 +3736,285 @@ var TOOL_DEFINITIONS = [
3351
3736
  },
3352
3737
  required: ["schema", "tasks", "count"]
3353
3738
  }
3739
+ },
3740
+ {
3741
+ name: "handoff-create",
3742
+ title: "Handoff Create",
3743
+ description: "Create a handoff record when work needs context transfer between agents. Optionally link it to a task by task_id or task_code, and put machine-readable details in context.",
3744
+ annotations: {
3745
+ readOnlyHint: false,
3746
+ idempotentHint: false,
3747
+ destructiveHint: false,
3748
+ openWorldHint: false
3749
+ },
3750
+ inputSchema: {
3751
+ type: "object",
3752
+ properties: {
3753
+ repo: { type: "string", description: "Repository name" },
3754
+ from_agent: { type: "string", description: "Agent creating the handoff" },
3755
+ to_agent: { type: "string", description: "Optional target agent" },
3756
+ task_id: { type: "string", format: "uuid", description: "Optional task id to associate" },
3757
+ task_code: { type: "string", description: "Optional task code to associate" },
3758
+ summary: { type: "string", minLength: 1, description: "Concise human-readable transfer summary" },
3759
+ context: {
3760
+ type: "object",
3761
+ description: "Structured handoff context, such as changed files, blockers, verification status, and next steps"
3762
+ },
3763
+ expires_at: { type: "string", description: "Optional expiration timestamp" },
3764
+ structured: { type: "boolean", default: false }
3765
+ },
3766
+ required: ["repo", "from_agent", "summary"]
3767
+ },
3768
+ outputSchema: {
3769
+ type: "object",
3770
+ properties: {
3771
+ id: { type: "string" },
3772
+ repo: { type: "string" },
3773
+ from_agent: { type: "string" },
3774
+ to_agent: { type: "string", nullable: true },
3775
+ task_id: { type: "string", nullable: true },
3776
+ summary: { type: "string" },
3777
+ context: { type: "object" },
3778
+ status: { type: "string", enum: ["pending", "accepted", "rejected", "expired"] },
3779
+ created_at: { type: "string" },
3780
+ updated_at: { type: "string" },
3781
+ expires_at: { type: "string", nullable: true }
3782
+ },
3783
+ required: ["id", "repo", "from_agent", "summary", "context", "status", "created_at", "updated_at"]
3784
+ }
3785
+ },
3786
+ {
3787
+ name: "handoff-list",
3788
+ title: "Handoff List",
3789
+ description: "Navigation layer for handoff queues. List repository handoffs with optional status and agent filters, then inspect selected rows before acting.",
3790
+ annotations: {
3791
+ readOnlyHint: true,
3792
+ idempotentHint: true,
3793
+ openWorldHint: false
3794
+ },
3795
+ inputSchema: {
3796
+ type: "object",
3797
+ properties: {
3798
+ repo: { type: "string", description: "Repository name" },
3799
+ status: { type: "string", enum: ["pending", "accepted", "rejected", "expired"] },
3800
+ from_agent: { type: "string" },
3801
+ to_agent: { type: "string" },
3802
+ limit: { type: "number", minimum: 1, maximum: 100, default: 20 },
3803
+ offset: { type: "number", minimum: 0, default: 0 },
3804
+ structured: { type: "boolean", default: false }
3805
+ },
3806
+ required: ["repo"]
3807
+ },
3808
+ outputSchema: {
3809
+ type: "object",
3810
+ properties: {
3811
+ schema: { type: "string", enum: ["handoff-list"] },
3812
+ handoffs: {
3813
+ type: "object",
3814
+ properties: {
3815
+ columns: {
3816
+ type: "array",
3817
+ items: { type: "string" },
3818
+ description: "Column names: [id, from_agent, to_agent, task_id, status, created_at, summary]"
3819
+ },
3820
+ rows: {
3821
+ type: "array",
3822
+ items: { type: "array" },
3823
+ description: "Each row: [id, from_agent, to_agent, task_id, status, created_at, summary]"
3824
+ }
3825
+ },
3826
+ required: ["columns", "rows"]
3827
+ },
3828
+ count: { type: "number" },
3829
+ offset: { type: "number" }
3830
+ },
3831
+ required: ["schema", "handoffs", "count", "offset"]
3832
+ }
3833
+ },
3834
+ {
3835
+ name: "task-claim",
3836
+ title: "Task Claim",
3837
+ description: "Claim task ownership for an agent using the dedicated claims table. Use this before taking work from task-list; provide either task_id or task_code.",
3838
+ annotations: {
3839
+ readOnlyHint: false,
3840
+ idempotentHint: false,
3841
+ destructiveHint: false,
3842
+ openWorldHint: false
3843
+ },
3844
+ inputSchema: {
3845
+ type: "object",
3846
+ properties: {
3847
+ repo: { type: "string", description: "Repository name" },
3848
+ task_id: { type: "string", format: "uuid", description: "Task id to claim. Optional if task_code is provided." },
3849
+ task_code: { type: "string", description: "Task code to claim. Optional if task_id is provided." },
3850
+ agent: { type: "string", description: "Claiming agent name" },
3851
+ role: { type: "string", description: "Claiming agent role" },
3852
+ metadata: { type: "object", description: "Optional claim metadata" },
3853
+ structured: { type: "boolean", default: false }
3854
+ },
3855
+ required: ["repo", "agent"]
3856
+ },
3857
+ outputSchema: {
3858
+ type: "object",
3859
+ properties: {
3860
+ id: { type: "string" },
3861
+ repo: { type: "string" },
3862
+ task_id: { type: "string" },
3863
+ task_code: { type: "string", nullable: true },
3864
+ agent: { type: "string" },
3865
+ role: { type: "string" },
3866
+ claimed_at: { type: "string" },
3867
+ released_at: { type: "string", nullable: true },
3868
+ metadata: { type: "object" }
3869
+ },
3870
+ required: ["id", "repo", "task_id", "agent", "role", "claimed_at", "metadata"]
3871
+ }
3872
+ },
3873
+ {
3874
+ name: "standard-store",
3875
+ title: "Standard Store",
3876
+ description: "Store one atomic coding standard. Use for durable implementation rules with explicit context, stack/language filters, and repo/global scope.",
3877
+ annotations: {
3878
+ readOnlyHint: false,
3879
+ idempotentHint: false,
3880
+ destructiveHint: false,
3881
+ openWorldHint: false
3882
+ },
3883
+ inputSchema: {
3884
+ type: "object",
3885
+ properties: {
3886
+ name: { type: "string", minLength: 3, maxLength: 255, description: "Human-readable standard name" },
3887
+ content: { type: "string", minLength: 10, description: "One atomic, actionable standard written as concise Markdown" },
3888
+ context: { type: "string", description: "Context or category (e.g., 'error-handling', 'security')" },
3889
+ version: { type: "string", description: "Version of the standard (e.g., '1.0.0')" },
3890
+ language: { type: "string", description: "Programming language (e.g., 'typescript', 'python')" },
3891
+ stack: {
3892
+ type: "array",
3893
+ items: { type: "string" },
3894
+ description: "Technology stack (e.g., ['react', 'nextjs'])"
3895
+ },
3896
+ repo: { type: "string", description: "Repository name for repo-specific standards. Omit only for global standards." },
3897
+ is_global: { type: "boolean", description: "Whether standard applies globally or repo-specific" },
3898
+ tags: {
3899
+ type: "array",
3900
+ items: { type: "string" },
3901
+ description: "Tags for categorization"
3902
+ },
3903
+ metadata: {
3904
+ type: "object",
3905
+ description: "Additional metadata"
3906
+ },
3907
+ agent: { type: "string", description: "Agent creating the standard" },
3908
+ model: { type: "string", description: "AI model used" },
3909
+ structured: { type: "boolean", default: false }
3910
+ },
3911
+ required: ["name", "content"]
3912
+ },
3913
+ outputSchema: {
3914
+ type: "object",
3915
+ properties: {
3916
+ success: { type: "boolean" },
3917
+ standard: {
3918
+ type: "object",
3919
+ properties: {
3920
+ id: { type: "string" },
3921
+ title: { type: "string" },
3922
+ content: { type: "string" },
3923
+ context: { type: "string" },
3924
+ version: { type: "string" },
3925
+ language: { type: "string", nullable: true },
3926
+ stack: { type: "array", items: { type: "string" } },
3927
+ is_global: { type: "boolean" },
3928
+ repo: { type: "string", nullable: true },
3929
+ tags: { type: "array", items: { type: "string" } },
3930
+ metadata: { type: "object" },
3931
+ created_at: { type: "string" },
3932
+ updated_at: { type: "string" },
3933
+ agent: { type: "string" },
3934
+ model: { type: "string" }
3935
+ },
3936
+ required: [
3937
+ "id",
3938
+ "title",
3939
+ "content",
3940
+ "context",
3941
+ "version",
3942
+ "stack",
3943
+ "is_global",
3944
+ "tags",
3945
+ "metadata",
3946
+ "created_at",
3947
+ "updated_at",
3948
+ "agent",
3949
+ "model"
3950
+ ]
3951
+ },
3952
+ message: { type: "string" }
3953
+ },
3954
+ required: ["success", "standard", "message"]
3955
+ }
3956
+ },
3957
+ {
3958
+ name: "standard-search",
3959
+ title: "Standard Search",
3960
+ description: "Navigation and lookup layer for coding standards. Query by text, stack, language, version, repo, and global scope before applying or creating standards.",
3961
+ annotations: {
3962
+ readOnlyHint: true,
3963
+ idempotentHint: true,
3964
+ openWorldHint: false
3965
+ },
3966
+ inputSchema: {
3967
+ type: "object",
3968
+ properties: {
3969
+ query: { type: "string", description: "Search query (optional, searches title/content)" },
3970
+ stack: {
3971
+ type: "array",
3972
+ items: { type: "string" },
3973
+ description: "Technology stack to filter by (e.g., ['react', 'nextjs'])"
3974
+ },
3975
+ language: { type: "string", description: "Programming language filter" },
3976
+ version: { type: "string", description: "Version filter" },
3977
+ repo: { type: "string", description: "Repository filter (optional)" },
3978
+ is_global: { type: "boolean", description: "Filter by global/repo-specific" },
3979
+ limit: { type: "number", minimum: 1, maximum: 100, default: 20 },
3980
+ offset: { type: "number", minimum: 0, default: 0 },
3981
+ structured: { type: "boolean", default: false }
3982
+ },
3983
+ required: []
3984
+ },
3985
+ outputSchema: {
3986
+ type: "object",
3987
+ properties: {
3988
+ success: { type: "boolean" },
3989
+ standards: {
3990
+ type: "array",
3991
+ items: {
3992
+ type: "object",
3993
+ properties: {
3994
+ id: { type: "string" },
3995
+ title: { type: "string" },
3996
+ content: { type: "string" },
3997
+ context: { type: "string" },
3998
+ version: { type: "string" },
3999
+ language: { type: "string", nullable: true },
4000
+ stack: { type: "array", items: { type: "string" } },
4001
+ is_global: { type: "boolean" },
4002
+ repo: { type: "string", nullable: true },
4003
+ tags: { type: "array", items: { type: "string" } },
4004
+ metadata: { type: "object" },
4005
+ created_at: { type: "string" },
4006
+ updated_at: { type: "string" },
4007
+ agent: { type: "string" },
4008
+ model: { type: "string" }
4009
+ }
4010
+ },
4011
+ description: "Matching coding standards"
4012
+ },
4013
+ count: { type: "number", description: "Number of results returned" },
4014
+ message: { type: "string" }
4015
+ },
4016
+ required: ["success", "standards", "count", "message"]
4017
+ }
3354
4018
  }
3355
4019
  ];
3356
4020
 
@@ -3946,6 +4610,11 @@ export {
3946
4610
  TaskDeleteSchema,
3947
4611
  MemoryDetailSchema,
3948
4612
  TaskGetSchema,
4613
+ HandoffCreateSchema,
4614
+ HandoffListSchema,
4615
+ TaskClaimSchema,
4616
+ StandardStoreSchema,
4617
+ StandardSearchSchema,
3949
4618
  TOOL_DEFINITIONS,
3950
4619
  encodeCursor,
3951
4620
  decodeCursor,