@vheins/local-memory-mcp 0.16.2 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -81,8 +81,8 @@ function loadServerInstructions() {
81
81
  // src/mcp/capabilities.ts
82
82
  var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
83
83
  var pkgVersion = "0.1.0";
84
- if ("0.16.2") {
85
- pkgVersion = "0.16.2";
84
+ if ("0.17.0") {
85
+ pkgVersion = "0.17.0";
86
86
  } else {
87
87
  let searchDir = __dirname2;
88
88
  for (let i = 0; i < 5; i++) {
@@ -294,6 +294,7 @@ var MigrationManager = class {
294
294
  CREATE TABLE IF NOT EXISTS memories (
295
295
  id TEXT PRIMARY KEY,
296
296
  repo TEXT NOT NULL,
297
+ owner TEXT NOT NULL DEFAULT '',
297
298
  type TEXT NOT NULL,
298
299
  title TEXT,
299
300
  content TEXT NOT NULL,
@@ -322,9 +323,11 @@ var MigrationManager = class {
322
323
  CREATE INDEX IF NOT EXISTS idx_memories_title ON memories(title);
323
324
 
324
325
  CREATE TABLE IF NOT EXISTS memory_summary (
325
- repo TEXT PRIMARY KEY,
326
+ repo TEXT NOT NULL,
327
+ owner TEXT NOT NULL DEFAULT '',
326
328
  summary TEXT NOT NULL,
327
- updated_at TEXT NOT NULL
329
+ updated_at TEXT NOT NULL,
330
+ PRIMARY KEY (owner, repo)
328
331
  );
329
332
 
330
333
  CREATE TABLE IF NOT EXISTS memory_vectors (
@@ -337,6 +340,7 @@ var MigrationManager = class {
337
340
  CREATE TABLE IF NOT EXISTS tasks (
338
341
  id TEXT PRIMARY KEY,
339
342
  repo TEXT NOT NULL,
343
+ owner TEXT NOT NULL DEFAULT '',
340
344
  task_code TEXT NOT NULL,
341
345
  phase TEXT,
342
346
  title TEXT NOT NULL,
@@ -373,6 +377,7 @@ var MigrationManager = class {
373
377
  id TEXT PRIMARY KEY,
374
378
  task_id TEXT NOT NULL,
375
379
  repo TEXT NOT NULL,
380
+ owner TEXT NOT NULL DEFAULT '',
376
381
  comment TEXT NOT NULL,
377
382
  agent TEXT NOT NULL DEFAULT 'unknown',
378
383
  role TEXT NOT NULL DEFAULT 'unknown',
@@ -398,6 +403,7 @@ var MigrationManager = class {
398
403
  stack TEXT,
399
404
  is_global INTEGER NOT NULL DEFAULT 0,
400
405
  repo TEXT,
406
+ owner TEXT NOT NULL DEFAULT '',
401
407
  tags TEXT,
402
408
  metadata TEXT,
403
409
  created_at TEXT NOT NULL,
@@ -424,6 +430,7 @@ var MigrationManager = class {
424
430
  CREATE TABLE IF NOT EXISTS memories_archive (
425
431
  id TEXT PRIMARY KEY,
426
432
  repo TEXT NOT NULL,
433
+ owner TEXT NOT NULL DEFAULT '',
427
434
  type TEXT NOT NULL,
428
435
  content TEXT NOT NULL,
429
436
  importance INTEGER NOT NULL,
@@ -450,6 +457,7 @@ var MigrationManager = class {
450
457
  memory_id TEXT,
451
458
  task_id TEXT,
452
459
  repo TEXT NOT NULL,
460
+ owner TEXT NOT NULL DEFAULT '',
453
461
  result_count INTEGER NOT NULL DEFAULT 0,
454
462
  created_at TEXT NOT NULL
455
463
  );
@@ -460,6 +468,7 @@ var MigrationManager = class {
460
468
  CREATE TABLE IF NOT EXISTS handoffs (
461
469
  id TEXT PRIMARY KEY,
462
470
  repo TEXT NOT NULL,
471
+ owner TEXT NOT NULL DEFAULT '',
463
472
  from_agent TEXT NOT NULL,
464
473
  to_agent TEXT,
465
474
  task_id TEXT,
@@ -482,6 +491,7 @@ var MigrationManager = class {
482
491
  CREATE TABLE IF NOT EXISTS claims (
483
492
  id TEXT PRIMARY KEY,
484
493
  repo TEXT NOT NULL,
494
+ owner TEXT NOT NULL DEFAULT '',
485
495
  task_id TEXT NOT NULL,
486
496
  agent TEXT NOT NULL,
487
497
  role TEXT NOT NULL DEFAULT 'unknown',
@@ -590,6 +600,51 @@ var MigrationManager = class {
590
600
  name: "suggested_skills",
591
601
  table: "tasks",
592
602
  definition: "ALTER TABLE tasks ADD COLUMN suggested_skills TEXT"
603
+ },
604
+ {
605
+ name: "owner",
606
+ table: "memories",
607
+ definition: "ALTER TABLE memories ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
608
+ },
609
+ {
610
+ name: "owner",
611
+ table: "tasks",
612
+ definition: "ALTER TABLE tasks ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
613
+ },
614
+ {
615
+ name: "owner",
616
+ table: "task_comments",
617
+ definition: "ALTER TABLE task_comments ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
618
+ },
619
+ {
620
+ name: "owner",
621
+ table: "coding_standards",
622
+ definition: "ALTER TABLE coding_standards ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
623
+ },
624
+ {
625
+ name: "owner",
626
+ table: "memories_archive",
627
+ definition: "ALTER TABLE memories_archive ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
628
+ },
629
+ {
630
+ name: "owner",
631
+ table: "action_log",
632
+ definition: "ALTER TABLE action_log ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
633
+ },
634
+ {
635
+ name: "owner",
636
+ table: "handoffs",
637
+ definition: "ALTER TABLE handoffs ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
638
+ },
639
+ {
640
+ name: "owner",
641
+ table: "claims",
642
+ definition: "ALTER TABLE claims ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
643
+ },
644
+ {
645
+ name: "owner",
646
+ table: "memory_summary",
647
+ definition: "ALTER TABLE memory_summary ADD COLUMN owner TEXT NOT NULL DEFAULT ''"
593
648
  }
594
649
  ];
595
650
  for (const col of columnsToAdd) {
@@ -627,6 +682,7 @@ var MigrationManager = class {
627
682
  CREATE TABLE memories__migrated (
628
683
  id TEXT PRIMARY KEY,
629
684
  repo TEXT NOT NULL,
685
+ owner TEXT NOT NULL DEFAULT '',
630
686
  type TEXT NOT NULL,
631
687
  title TEXT,
632
688
  content TEXT NOT NULL,
@@ -651,12 +707,12 @@ var MigrationManager = class {
651
707
  );
652
708
 
653
709
  INSERT INTO memories__migrated (
654
- id, repo, type, title, content, importance, folder, language,
710
+ id, repo, owner, type, title, content, importance, folder, language,
655
711
  created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
656
712
  supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
657
713
  )
658
714
  SELECT
659
- id, repo, type, title, content, importance, folder, language,
715
+ id, repo, owner, type, title, content, importance, folder, language,
660
716
  created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
661
717
  supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
662
718
  FROM memories;
@@ -678,6 +734,7 @@ var MigrationManager = class {
678
734
  CREATE TABLE tasks__migrated (
679
735
  id TEXT PRIMARY KEY,
680
736
  repo TEXT NOT NULL,
737
+ owner TEXT NOT NULL DEFAULT '',
681
738
  task_code TEXT NOT NULL,
682
739
  phase TEXT,
683
740
  title TEXT NOT NULL,
@@ -704,12 +761,12 @@ var MigrationManager = class {
704
761
  );
705
762
 
706
763
  INSERT INTO tasks__migrated (
707
- id, repo, task_code, phase, title, description, status, priority,
764
+ id, repo, owner, task_code, phase, title, description, status, priority,
708
765
  agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at,
709
766
  commit_id, changed_files
710
767
  )
711
768
  SELECT
712
- id, repo, task_code, phase, title, description, status, priority,
769
+ id, repo, owner, task_code, phase, title, description, status, priority,
713
770
  agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at,
714
771
  commit_id, changed_files
715
772
  FROM tasks;
@@ -983,6 +1040,15 @@ var STOPWORDS = /* @__PURE__ */ new Set([
983
1040
  function normalize(text) {
984
1041
  return text.toLowerCase().replace(/[^a-z0-9\s_\-.]/g, " ").replace(/\s+/g, " ").trim();
985
1042
  }
1043
+ function parseRepoInput(repo, owner) {
1044
+ if (!repo) return { owner: "", repo: "" };
1045
+ if (owner) return { owner: owner.trim(), repo: repo.trim() };
1046
+ const parts = repo.split("/");
1047
+ if (parts.length > 1) {
1048
+ return { owner: parts[0].trim(), repo: parts.slice(1).join("/").trim() };
1049
+ }
1050
+ return { owner: "", repo: parts[0].trim() };
1051
+ }
986
1052
  function normalizeRepo(repo) {
987
1053
  if (!repo) return "";
988
1054
  const parts = repo.split("/");
@@ -1038,6 +1104,7 @@ var BaseEntity = class {
1038
1104
  role: r.role || "unknown",
1039
1105
  model: r.model || "unknown",
1040
1106
  scope: {
1107
+ owner: r.owner,
1041
1108
  repo: r.repo,
1042
1109
  folder: r.folder || void 0,
1043
1110
  language: r.language || void 0
@@ -1060,6 +1127,7 @@ var BaseEntity = class {
1060
1127
  const r = row;
1061
1128
  return {
1062
1129
  id: r.id,
1130
+ owner: r.owner,
1063
1131
  repo: r.repo,
1064
1132
  task_code: r.task_code,
1065
1133
  phase: r.phase || "",
@@ -1146,14 +1214,15 @@ var MemoryEntity = class extends BaseEntity {
1146
1214
  insert(entry) {
1147
1215
  this.run(
1148
1216
  `INSERT INTO memories (
1149
- id, code, repo, type, title, content, importance, folder, language,
1217
+ id, code, repo, owner, type, title, content, importance, folder, language,
1150
1218
  created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
1151
1219
  supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
1152
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1220
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1153
1221
  [
1154
1222
  entry.id,
1155
1223
  entry.code || null,
1156
1224
  entry.scope.repo,
1225
+ entry.scope.owner,
1157
1226
  entry.type,
1158
1227
  entry.title || null,
1159
1228
  entry.content,
@@ -1184,6 +1253,10 @@ var MemoryEntity = class extends BaseEntity {
1184
1253
  if (val !== void 0) {
1185
1254
  if (k === "scope") {
1186
1255
  const scope = updates.scope;
1256
+ if (scope?.owner !== void 0) {
1257
+ fields.push("owner = ?");
1258
+ values.push(scope.owner);
1259
+ }
1187
1260
  if (scope?.repo) {
1188
1261
  fields.push("repo = ?");
1189
1262
  values.push(scope.repo);
@@ -1251,10 +1324,17 @@ var MemoryEntity = class extends BaseEntity {
1251
1324
  const rows = this.all(sql, params);
1252
1325
  return rows.map((row) => this.rowToMemoryEntry(row));
1253
1326
  }
1254
- getStats(repo) {
1327
+ getStats(owner, repo) {
1255
1328
  let sql = "SELECT type, COUNT(*) as count FROM memories";
1256
1329
  const params = [];
1257
- if (repo) {
1330
+ if (owner) {
1331
+ sql += " WHERE owner = ?";
1332
+ params.push(owner);
1333
+ if (repo) {
1334
+ sql += " AND repo = ?";
1335
+ params.push(repo);
1336
+ }
1337
+ } else if (repo) {
1258
1338
  sql += " WHERE repo = ?";
1259
1339
  params.push(repo);
1260
1340
  }
@@ -1268,10 +1348,10 @@ var MemoryEntity = class extends BaseEntity {
1268
1348
  });
1269
1349
  return { total, byType };
1270
1350
  }
1271
- searchByRepo(repo, query = "", type, limit = 5) {
1351
+ searchByRepo(owner, repo, query = "", type, limit = 5) {
1272
1352
  const now = (/* @__PURE__ */ new Date()).toISOString();
1273
- let sql = "SELECT * FROM memories WHERE repo = ? AND (content LIKE ? OR title LIKE ? OR tags LIKE ?) AND status = 'active' AND (expires_at IS NULL OR expires_at > ?)";
1274
- const params = [repo, `%${query}%`, `%${query}%`, `%${query}%`, now];
1353
+ let sql = "SELECT * FROM memories WHERE owner = ? AND repo = ? AND (content LIKE ? OR title LIKE ? OR tags LIKE ?) AND status = 'active' AND (expires_at IS NULL OR expires_at > ?)";
1354
+ const params = [owner, repo, `%${query}%`, `%${query}%`, `%${query}%`, now];
1275
1355
  if (type) {
1276
1356
  sql += " AND type = ?";
1277
1357
  params.push(type);
@@ -1287,13 +1367,14 @@ var MemoryEntity = class extends BaseEntity {
1287
1367
  for (const entry of entries) {
1288
1368
  this.run(
1289
1369
  `INSERT INTO memories (
1290
- id, repo, type, title, content, importance, folder, language,
1370
+ id, repo, owner, type, title, content, importance, folder, language,
1291
1371
  created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
1292
1372
  supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
1293
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1373
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1294
1374
  [
1295
1375
  entry.id,
1296
1376
  entry.scope.repo,
1377
+ entry.scope.owner,
1297
1378
  entry.type,
1298
1379
  entry.title || null,
1299
1380
  entry.content,
@@ -1328,6 +1409,10 @@ var MemoryEntity = class extends BaseEntity {
1328
1409
  if (value !== void 0) {
1329
1410
  if (key === "scope") {
1330
1411
  const scope = updates.scope;
1412
+ if (scope?.owner !== void 0) {
1413
+ fields.push("owner = ?");
1414
+ values.push(scope.owner);
1415
+ }
1331
1416
  if (scope?.repo) {
1332
1417
  fields.push("repo = ?");
1333
1418
  values.push(scope.repo);
@@ -1369,9 +1454,9 @@ var MemoryEntity = class extends BaseEntity {
1369
1454
  return count;
1370
1455
  });
1371
1456
  }
1372
- getRecentMemories(repo, limit, offset = 0, includeArchived = false, excludeTypes = [], sortOrder = "DESC") {
1373
- let query = "SELECT * FROM memories WHERE repo = ?";
1374
- const params = [repo];
1457
+ getRecentMemories(owner, repo, limit, offset = 0, includeArchived = false, excludeTypes = [], sortOrder = "DESC") {
1458
+ let query = "SELECT * FROM memories WHERE owner = ? AND repo = ?";
1459
+ const params = [owner, repo];
1375
1460
  if (!includeArchived) {
1376
1461
  query += " AND status = 'active'";
1377
1462
  }
@@ -1384,9 +1469,9 @@ var MemoryEntity = class extends BaseEntity {
1384
1469
  const rows = this.all(query, params);
1385
1470
  return rows.map((row) => this.rowToMemoryEntry(row));
1386
1471
  }
1387
- getTotalCount(repo, includeArchived = false, excludeTypes = []) {
1388
- let sql = "SELECT COUNT(*) as count FROM memories WHERE repo = ?";
1389
- const params = [repo];
1472
+ getTotalCount(owner, repo, includeArchived = false, excludeTypes = []) {
1473
+ let sql = "SELECT COUNT(*) as count FROM memories WHERE owner = ? AND repo = ?";
1474
+ const params = [owner, repo];
1390
1475
  if (!includeArchived) sql += " AND status = 'active'";
1391
1476
  if (excludeTypes.length > 0) {
1392
1477
  sql += ` AND type NOT IN (${excludeTypes.map(() => "?").join(",")})`;
@@ -1414,32 +1499,33 @@ var MemoryEntity = class extends BaseEntity {
1414
1499
  id
1415
1500
  ]);
1416
1501
  }
1417
- getSummary(repo) {
1502
+ getSummary(owner, repo) {
1418
1503
  const row = this.get(
1419
- "SELECT summary, updated_at FROM memory_summary WHERE repo = ?",
1420
- [repo]
1504
+ "SELECT summary, updated_at FROM memory_summary WHERE owner = ? AND repo = ?",
1505
+ [owner, repo]
1421
1506
  );
1422
1507
  return row;
1423
1508
  }
1424
- getAllMemoriesWithStats(repo) {
1509
+ getAllMemoriesWithStats(owner, repo) {
1425
1510
  const rows = this.all(
1426
- `SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate FROM memories WHERE repo = ? ORDER BY created_at DESC`,
1427
- [repo]
1511
+ `SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate FROM memories WHERE owner = ? AND repo = ? ORDER BY created_at DESC`,
1512
+ [owner, repo]
1428
1513
  );
1429
1514
  return rows.map((row) => ({
1430
1515
  ...this.rowToMemoryEntry(row),
1431
1516
  recall_rate: row.recall_rate || 0
1432
1517
  }));
1433
1518
  }
1434
- upsertSummary(repo, summary) {
1519
+ upsertSummary(owner, repo, summary) {
1435
1520
  this.run(
1436
- `INSERT INTO memory_summary (repo, summary, updated_at) VALUES (?, ?, ?)
1437
- ON CONFLICT(repo) DO UPDATE SET summary = excluded.summary, updated_at = excluded.updated_at`,
1438
- [repo, summary, (/* @__PURE__ */ new Date()).toISOString()]
1521
+ `INSERT INTO memory_summary (owner, repo, summary, updated_at) VALUES (?, ?, ?, ?)
1522
+ ON CONFLICT(owner, repo) DO UPDATE SET summary = excluded.summary, updated_at = excluded.updated_at`,
1523
+ [owner, repo, summary, (/* @__PURE__ */ new Date()).toISOString()]
1439
1524
  );
1440
1525
  }
1441
1526
  listMemoriesForDashboard(options) {
1442
1527
  const {
1528
+ owner,
1443
1529
  repo,
1444
1530
  type,
1445
1531
  tag,
@@ -1454,6 +1540,10 @@ var MemoryEntity = class extends BaseEntity {
1454
1540
  } = options;
1455
1541
  const where = ["1=1"];
1456
1542
  const params = [];
1543
+ if (owner) {
1544
+ where.push("owner = ?");
1545
+ params.push(owner);
1546
+ }
1457
1547
  if (repo) {
1458
1548
  where.push("repo = ?");
1459
1549
  params.push(repo);
@@ -1497,12 +1587,15 @@ var MemoryEntity = class extends BaseEntity {
1497
1587
 
1498
1588
  // src/mcp/entities/memory.vector.ts
1499
1589
  var MemoryVectorEntity = class extends BaseEntity {
1500
- getVectorCandidates(repo, limit = 100) {
1590
+ getVectorCandidates(owner, repo, limit = 100) {
1501
1591
  let sql = `SELECT mv.memory_id, mv.vector FROM memory_vectors mv JOIN memories m ON mv.memory_id = m.id`;
1502
1592
  const params = [];
1503
1593
  if (repo) {
1504
- sql += " WHERE m.repo = ?";
1505
- params.push(repo);
1594
+ sql += " WHERE m.owner = ? AND m.repo = ?";
1595
+ params.push(owner, repo);
1596
+ } else if (owner) {
1597
+ sql += " WHERE m.owner = ?";
1598
+ params.push(owner);
1506
1599
  }
1507
1600
  sql += " LIMIT ?";
1508
1601
  params.push(limit);
@@ -1515,11 +1608,11 @@ var MemoryVectorEntity = class extends BaseEntity {
1515
1608
  [memoryId, JSON.stringify(vector), (/* @__PURE__ */ new Date()).toISOString()]
1516
1609
  );
1517
1610
  }
1518
- searchBySimilarity(query, repo, limit = 10, includeArchived = false, currentTags = []) {
1611
+ searchBySimilarity(query, owner, repo, limit = 10, includeArchived = false, currentTags = []) {
1519
1612
  const queryVector = this.computeVector(query);
1520
1613
  const now = /* @__PURE__ */ new Date();
1521
- const where = ["(repo = ? OR is_global = 1)"];
1522
- const params = [repo];
1614
+ const where = ["(owner = ? AND repo = ? OR is_global = 1)"];
1615
+ const params = [owner, repo];
1523
1616
  if (currentTags.length > 0) {
1524
1617
  const tagConditions = currentTags.map(() => "tags LIKE ?").join(" OR ");
1525
1618
  where.push(`(${tagConditions})`);
@@ -1527,8 +1620,8 @@ var MemoryVectorEntity = class extends BaseEntity {
1527
1620
  }
1528
1621
  let sql = `SELECT * FROM memories WHERE (${where.join(" AND ")}) AND (expires_at IS NULL OR expires_at > ?)`;
1529
1622
  if (!includeArchived) sql += " AND status = 'active'";
1530
- sql += ` ORDER BY CASE WHEN repo = ? THEN 0 ELSE 1 END, importance DESC, created_at DESC LIMIT 100`;
1531
- const candidates = this.all(sql, [...params, now.toISOString(), repo]);
1623
+ sql += ` ORDER BY CASE WHEN owner = ? AND repo = ? THEN 0 ELSE 1 END, importance DESC, created_at DESC LIMIT 100`;
1624
+ const candidates = this.all(sql, [...params, now.toISOString(), owner, repo]);
1532
1625
  if (candidates.length < 5) {
1533
1626
  const recentSql = `SELECT * FROM memories WHERE (${where.join(" OR ")}) AND status = 'active' AND (expires_at IS NULL OR expires_at > ?) ORDER BY created_at DESC LIMIT 10`;
1534
1627
  const recent = this.all(recentSql, [...params, now.toISOString()]);
@@ -1556,8 +1649,8 @@ var MemoryVectorEntity = class extends BaseEntity {
1556
1649
  return { ...memory, similarity: score };
1557
1650
  }).filter((r) => r.similarity > 0).sort((a, b) => b.similarity - a.similarity).slice(0, limit);
1558
1651
  }
1559
- async checkConflicts(content, repo, _type, _vectors, threshold = 0.55) {
1560
- const results = await this.searchBySimilarity(content, repo, 1, false);
1652
+ async checkConflicts(content, owner, repo, _type, _vectors, threshold = 0.55) {
1653
+ const results = await this.searchBySimilarity(content, owner, repo, 1, false);
1561
1654
  if (results.length > 0 && results[0].similarity >= threshold) {
1562
1655
  return results[0];
1563
1656
  }
@@ -1620,13 +1713,14 @@ var TaskEntity = class extends BaseEntity {
1620
1713
  insertTask(task) {
1621
1714
  this.run(
1622
1715
  `INSERT INTO tasks (
1623
- id, repo, task_code, phase, title, description, status, priority,
1716
+ id, repo, owner, task_code, phase, title, description, status, priority,
1624
1717
  agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, suggested_skills, metadata, parent_id, depends_on, est_tokens, in_progress_at,
1625
1718
  commit_id, changed_files
1626
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1719
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1627
1720
  [
1628
1721
  task.id,
1629
1722
  task.repo,
1723
+ task.owner || "",
1630
1724
  task.task_code,
1631
1725
  task.phase || null,
1632
1726
  task.title,
@@ -1657,6 +1751,7 @@ var TaskEntity = class extends BaseEntity {
1657
1751
  const values = [];
1658
1752
  const anyUpdates = updates;
1659
1753
  const VALID_COLUMNS2 = /* @__PURE__ */ new Set([
1754
+ "owner",
1660
1755
  "repo",
1661
1756
  "task_code",
1662
1757
  "phase",
@@ -1747,15 +1842,15 @@ var TaskEntity = class extends BaseEntity {
1747
1842
  return task;
1748
1843
  });
1749
1844
  }
1750
- getTaskByCode(repo, taskCode) {
1845
+ getTaskByCode(owner, repo, taskCode) {
1751
1846
  const row = this.get(
1752
1847
  `SELECT t.*, d.task_code as depends_on_code, p.task_code as parent_code,
1753
1848
  ${this.coordinationSelect("t")}
1754
1849
  FROM tasks t
1755
1850
  LEFT JOIN tasks d ON t.depends_on = d.id
1756
1851
  LEFT JOIN tasks p ON t.parent_id = p.id
1757
- WHERE t.repo = ? AND t.task_code = ?`,
1758
- [repo, taskCode]
1852
+ WHERE t.owner = ? AND t.repo = ? AND t.task_code = ?`,
1853
+ [owner, repo, taskCode]
1759
1854
  );
1760
1855
  return row ? {
1761
1856
  ...this.rowToTask(row),
@@ -1765,7 +1860,7 @@ var TaskEntity = class extends BaseEntity {
1765
1860
  )
1766
1861
  } : null;
1767
1862
  }
1768
- getTasksByRepo(repo, status, limit, offset, search) {
1863
+ getTasksByRepo(owner, repo, status, limit, offset, search) {
1769
1864
  let query = `
1770
1865
  SELECT t.*, d.task_code as depends_on_code, p.task_code as parent_code,
1771
1866
  ${this.coordinationSelect("t")},
@@ -1773,9 +1868,9 @@ var TaskEntity = class extends BaseEntity {
1773
1868
  FROM tasks t
1774
1869
  LEFT JOIN tasks d ON t.depends_on = d.id
1775
1870
  LEFT JOIN tasks p ON t.parent_id = p.id
1776
- WHERE t.repo = ?
1871
+ WHERE ${owner ? "t.owner = ? AND " : ""}t.repo = ?
1777
1872
  `;
1778
- const params = [repo];
1873
+ const params = owner ? [owner, repo] : [repo];
1779
1874
  if (status) {
1780
1875
  query += " AND t.status = ?";
1781
1876
  params.push(status);
@@ -1807,9 +1902,10 @@ var TaskEntity = class extends BaseEntity {
1807
1902
  const rows = this.all(query, params);
1808
1903
  return rows.map((r) => this.rowToTask(r));
1809
1904
  }
1810
- countTasks(repo, status, search) {
1811
- let query = "SELECT COUNT(*) as count FROM tasks WHERE repo = ?";
1812
- const params = [repo];
1905
+ countTasks(owner, repo, status, search) {
1906
+ const ownerClause = owner ? "owner = ? AND " : "";
1907
+ let query = `SELECT COUNT(*) as count FROM tasks WHERE ${ownerClause}repo = ?`;
1908
+ const params = owner ? [owner, repo] : [repo];
1813
1909
  if (status) {
1814
1910
  query += " AND status = ?";
1815
1911
  params.push(status);
@@ -1831,7 +1927,6 @@ var TaskEntity = class extends BaseEntity {
1831
1927
  LEFT JOIN tasks d ON t.depends_on = d.id
1832
1928
  LEFT JOIN tasks p ON t.parent_id = p.id
1833
1929
  ORDER BY
1834
- ...
1835
1930
  CASE WHEN t.status = 'completed' THEN 1 ELSE 0 END ASC,
1836
1931
  CASE WHEN t.status = 'completed' THEN t.updated_at ELSE NULL END DESC,
1837
1932
  CASE WHEN t.status = 'in_progress' THEN 0
@@ -1847,8 +1942,9 @@ var TaskEntity = class extends BaseEntity {
1847
1942
  const rows = this.all(query, [limit, offset]);
1848
1943
  return rows.map((r) => this.rowToTask(r));
1849
1944
  }
1850
- getTasksByMultipleStatuses(repo, statuses, limit, offset, search) {
1851
- if (!statuses.length) return this.getTasksByRepo(repo, void 0, limit, offset, search);
1945
+ getTasksByMultipleStatuses(owner, repo, statuses, limit, offset, search) {
1946
+ if (!statuses.length) return this.getTasksByRepo(owner, repo, void 0, limit, offset, search);
1947
+ const ownerClause = owner ? "t.owner = ? AND " : "";
1852
1948
  let query = `
1853
1949
  SELECT t.*, d.task_code as depends_on_code, p.task_code as parent_code,
1854
1950
  ${this.coordinationSelect("t")},
@@ -1856,9 +1952,9 @@ var TaskEntity = class extends BaseEntity {
1856
1952
  FROM tasks t
1857
1953
  LEFT JOIN tasks d ON t.depends_on = d.id
1858
1954
  LEFT JOIN tasks p ON t.parent_id = p.id
1859
- WHERE t.repo = ? AND t.status IN (${statuses.map(() => "?").join(",")})
1955
+ WHERE ${ownerClause}t.repo = ? AND t.status IN (${statuses.map(() => "?").join(",")})
1860
1956
  `;
1861
- const params = [repo, ...statuses];
1957
+ const params = owner ? [owner, repo, ...statuses] : [repo, ...statuses];
1862
1958
  if (search) {
1863
1959
  query += " AND (t.title LIKE ? OR t.description LIKE ? OR t.task_code LIKE ?)";
1864
1960
  const searchPattern = `%${search}%`;
@@ -1886,10 +1982,11 @@ var TaskEntity = class extends BaseEntity {
1886
1982
  const rows = this.all(query, params);
1887
1983
  return rows.map((r) => this.rowToTask(r));
1888
1984
  }
1889
- countTasksByMultipleStatuses(repo, statuses, search) {
1890
- if (!statuses.length) return this.countTasks(repo, void 0, search);
1891
- let query = `SELECT COUNT(*) as count FROM tasks WHERE repo = ? AND status IN (${statuses.map(() => "?").join(",")})`;
1892
- const params = [repo, ...statuses];
1985
+ countTasksByMultipleStatuses(owner, repo, statuses, search) {
1986
+ if (!statuses.length) return this.countTasks(owner, repo, void 0, search);
1987
+ const ownerClause = owner ? "owner = ? AND " : "";
1988
+ let query = `SELECT COUNT(*) as count FROM tasks WHERE ${ownerClause}repo = ? AND status IN (${statuses.map(() => "?").join(",")})`;
1989
+ const params = owner ? [owner, repo, ...statuses] : [repo, ...statuses];
1893
1990
  if (search) {
1894
1991
  query += " AND (title LIKE ? OR description LIKE ? OR task_code LIKE ?)";
1895
1992
  const searchPattern = `%${search}%`;
@@ -1898,9 +1995,9 @@ var TaskEntity = class extends BaseEntity {
1898
1995
  const row = this.get(query, params);
1899
1996
  return row?.count ?? 0;
1900
1997
  }
1901
- isTaskCodeDuplicate(repo, task_code, excludeId) {
1902
- let query = "SELECT COUNT(*) as count FROM tasks WHERE repo = ? AND task_code = ?";
1903
- const params = [repo, task_code];
1998
+ isTaskCodeDuplicate(owner, repo, task_code, excludeId) {
1999
+ let query = "SELECT COUNT(*) as count FROM tasks WHERE owner = ? AND repo = ? AND task_code = ?";
2000
+ const params = [owner, repo, task_code];
1904
2001
  if (excludeId) {
1905
2002
  query += " AND id != ?";
1906
2003
  params.push(excludeId);
@@ -1920,12 +2017,12 @@ var TaskEntity = class extends BaseEntity {
1920
2017
  [id]
1921
2018
  );
1922
2019
  }
1923
- getExistingTaskCodes(repo, codes) {
2020
+ getExistingTaskCodes(owner, repo, codes) {
1924
2021
  if (codes.length === 0) return /* @__PURE__ */ new Set();
1925
2022
  const placeholders = codes.map(() => "?").join(",");
1926
2023
  const rows = this.all(
1927
- `SELECT task_code FROM tasks WHERE repo = ? AND task_code IN (${placeholders})`,
1928
- [repo, ...codes]
2024
+ `SELECT task_code FROM tasks WHERE owner = ? AND repo = ? AND task_code IN (${placeholders})`,
2025
+ [owner, repo, ...codes]
1929
2026
  );
1930
2027
  return new Set(rows.map((r) => r.task_code));
1931
2028
  }
@@ -1935,13 +2032,14 @@ var TaskEntity = class extends BaseEntity {
1935
2032
  for (const task of tasks) {
1936
2033
  this.run(
1937
2034
  `INSERT INTO tasks (
1938
- id, repo, task_code, phase, title, description, status, priority,
2035
+ id, repo, owner, task_code, phase, title, description, status, priority,
1939
2036
  agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, suggested_skills, metadata, parent_id, depends_on, est_tokens, in_progress_at,
1940
2037
  commit_id, changed_files
1941
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2038
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1942
2039
  [
1943
2040
  task.id,
1944
2041
  task.repo,
2042
+ task.owner || "",
1945
2043
  task.task_code,
1946
2044
  task.phase || null,
1947
2045
  task.title,
@@ -1978,12 +2076,13 @@ var TaskCommentEntity = class extends BaseEntity {
1978
2076
  insertTaskComment(comment) {
1979
2077
  this.run(
1980
2078
  `INSERT INTO task_comments (
1981
- id, task_id, repo, comment, agent, role, model, previous_status, next_status, created_at
1982
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2079
+ id, task_id, repo, owner, comment, agent, role, model, previous_status, next_status, created_at
2080
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1983
2081
  [
1984
2082
  comment.id,
1985
2083
  comment.task_id,
1986
2084
  comment.repo,
2085
+ comment.owner,
1987
2086
  comment.comment,
1988
2087
  comment.agent || "unknown",
1989
2088
  comment.role || "unknown",
@@ -1999,6 +2098,7 @@ var TaskCommentEntity = class extends BaseEntity {
1999
2098
  const values = [];
2000
2099
  const anyUpdates = updates;
2001
2100
  const VALID_COLUMNS2 = /* @__PURE__ */ new Set([
2101
+ "owner",
2002
2102
  "repo",
2003
2103
  "comment",
2004
2104
  "agent",
@@ -2028,19 +2128,20 @@ var TaskCommentEntity = class extends BaseEntity {
2028
2128
  taskId
2029
2129
  ]);
2030
2130
  }
2031
- getAllTaskCommentsByRepo(repo) {
2032
- return this.all(`SELECT * FROM task_comments WHERE repo = ? ORDER BY created_at DESC, id DESC`, [
2033
- repo
2034
- ]);
2131
+ getAllTaskCommentsByRepo(owner, repo) {
2132
+ return this.all(
2133
+ `SELECT * FROM task_comments WHERE owner = ? AND repo = ? ORDER BY created_at DESC, id DESC`,
2134
+ [owner, repo]
2135
+ );
2035
2136
  }
2036
2137
  };
2037
2138
 
2038
2139
  // src/mcp/entities/task-stats.ts
2039
2140
  var TaskStatsEntity = class extends BaseEntity {
2040
- getTaskStats(repo) {
2141
+ getTaskStats(owner, repo) {
2041
2142
  const rows = this.all(
2042
- "SELECT status, COUNT(*) as count FROM tasks WHERE repo = ? GROUP BY status",
2043
- [repo]
2143
+ "SELECT status, COUNT(*) as count FROM tasks WHERE owner = ? AND repo = ? GROUP BY status",
2144
+ [owner, repo]
2044
2145
  );
2045
2146
  const stats = { total: 0, backlog: 0, todo: 0, inProgress: 0, completed: 0, blocked: 0, canceled: 0 };
2046
2147
  rows.forEach((r) => {
@@ -2055,14 +2156,14 @@ var TaskStatsEntity = class extends BaseEntity {
2055
2156
  });
2056
2157
  return stats;
2057
2158
  }
2058
- getTaskTimeStats(repo, period) {
2159
+ getTaskTimeStats(owner, repo, period) {
2059
2160
  let dateFilter = "";
2060
2161
  if (period === "daily") dateFilter = "AND date(COALESCE(finished_at, updated_at)) = date('now')";
2061
2162
  else if (period === "weekly") dateFilter = "AND date(COALESCE(finished_at, updated_at)) >= date('now', '-7 days')";
2062
2163
  else if (period === "monthly")
2063
2164
  dateFilter = "AND date(COALESCE(finished_at, updated_at)) >= date('now', '-30 days')";
2064
- const repoWhere = repo ? "repo = ?" : "1=1";
2065
- const repoParams = repo ? [repo] : [];
2165
+ const repoWhere = repo ? "owner = ? AND repo = ?" : "1=1";
2166
+ const repoParams = repo ? [owner, repo] : [];
2066
2167
  const stats = this.get(
2067
2168
  `SELECT
2068
2169
  COUNT(*) as completed_count,
@@ -2096,7 +2197,7 @@ var TaskStatsEntity = class extends BaseEntity {
2096
2197
  added: added?.count || 0
2097
2198
  };
2098
2199
  }
2099
- getTaskComparisonSeries(repo, period) {
2200
+ getTaskComparisonSeries(owner, repo, period) {
2100
2201
  let labelFormat;
2101
2202
  let dateFilter;
2102
2203
  if (period === "daily") {
@@ -2117,8 +2218,8 @@ var TaskStatsEntity = class extends BaseEntity {
2117
2218
  "COALESCE(finished_at, created_at)",
2118
2219
  "COALESCE(finished_at, updated_at)"
2119
2220
  );
2120
- const createdRepoFilter = repo ? "repo = ? AND " : "";
2121
- const completedRepoFilter = repo ? "repo = ? AND " : "";
2221
+ const createdRepoFilter = repo ? "owner = ? AND repo = ? AND " : "";
2222
+ const completedRepoFilter = repo ? "owner = ? AND repo = ? AND " : "";
2122
2223
  const query = `
2123
2224
  SELECT label, SUM(created) as created, SUM(completed) as completed
2124
2225
  FROM (
@@ -2135,16 +2236,16 @@ var TaskStatsEntity = class extends BaseEntity {
2135
2236
  LIMIT 100
2136
2237
  `;
2137
2238
  const params = [labelFormat];
2138
- if (repo) params.push(repo);
2239
+ if (repo) params.push(owner, repo);
2139
2240
  params.push(labelFormat);
2140
- if (repo) params.push(repo);
2241
+ if (repo) params.push(owner, repo);
2141
2242
  return this.all(query, params);
2142
2243
  }
2143
2244
  };
2144
2245
 
2145
2246
  // src/mcp/entities/action.ts
2146
2247
  var ActionEntity = class extends BaseEntity {
2147
- logAction(action, repo, optionsOrQuery, response, memoryId, taskId, resultCount = 0) {
2248
+ logAction(action, owner, repo, optionsOrQuery, response, memoryId, taskId, resultCount = 0) {
2148
2249
  let query = typeof optionsOrQuery === "string" ? optionsOrQuery : void 0;
2149
2250
  let finalResponse = response;
2150
2251
  let finalMemoryId = memoryId;
@@ -2159,9 +2260,10 @@ var ActionEntity = class extends BaseEntity {
2159
2260
  finalResultCount = optionsOrQuery.resultCount !== void 0 ? optionsOrQuery.resultCount : finalResultCount;
2160
2261
  }
2161
2262
  this.run(
2162
- `INSERT INTO action_log (repo, action, query, response, memory_id, task_id, result_count, created_at)
2163
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
2263
+ `INSERT INTO action_log (owner, repo, action, query, response, memory_id, task_id, result_count, created_at)
2264
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2164
2265
  [
2266
+ owner,
2165
2267
  repo || "",
2166
2268
  action || "unknown",
2167
2269
  query || null,
@@ -2185,37 +2287,45 @@ var ActionEntity = class extends BaseEntity {
2185
2287
  [id]
2186
2288
  );
2187
2289
  }
2188
- getRecentActions(repo, limit = 10, offset = 0) {
2290
+ getRecentActions(owner, repo, limit = 10, offset = 0) {
2189
2291
  let query = `
2190
2292
  SELECT a.*, m.title as memory_title, m.type as memory_type
2191
2293
  FROM action_log a LEFT JOIN memories m ON a.memory_id = m.id
2192
2294
  `;
2193
2295
  const params = [];
2296
+ const where = [];
2194
2297
  if (repo) {
2195
- query += " WHERE a.repo = ?";
2298
+ where.push("a.repo = ?");
2196
2299
  params.push(repo);
2197
2300
  }
2301
+ if (owner) {
2302
+ where.push("a.owner = ?");
2303
+ params.push(owner);
2304
+ }
2305
+ if (where.length > 0) {
2306
+ query += " WHERE " + where.join(" AND ");
2307
+ }
2198
2308
  query += " ORDER BY a.created_at DESC, a.id DESC LIMIT ? OFFSET ?";
2199
2309
  params.push(limit, offset);
2200
2310
  return this.all(query, params);
2201
2311
  }
2202
- getActionStatsByDate(repo) {
2312
+ getActionStatsByDate(owner, repo) {
2203
2313
  return this.all(
2204
2314
  `SELECT date(created_at) as date, count(*) as count
2205
2315
  FROM action_log
2206
- WHERE repo = ? AND created_at > date('now', '-30 days')
2316
+ WHERE owner = ? AND repo = ? AND created_at > date('now', '-30 days')
2207
2317
  GROUP BY date(created_at)
2208
2318
  ORDER BY date ASC`,
2209
- [repo]
2319
+ [owner, repo]
2210
2320
  );
2211
2321
  }
2212
- getActionDistribution(repo) {
2322
+ getActionDistribution(owner, repo) {
2213
2323
  return this.all(
2214
2324
  `SELECT action, count(*) as count
2215
2325
  FROM action_log
2216
- WHERE repo = ?
2326
+ WHERE owner = ? AND repo = ?
2217
2327
  GROUP BY action`,
2218
- [repo]
2328
+ [owner, repo]
2219
2329
  );
2220
2330
  }
2221
2331
  getActionById(id) {
@@ -2251,39 +2361,55 @@ var SystemEntity = class extends BaseEntity {
2251
2361
  });
2252
2362
  return taskStats;
2253
2363
  }
2254
- listRepos() {
2255
- const rows = this.all("SELECT DISTINCT repo FROM memories UNION SELECT DISTINCT repo FROM tasks");
2364
+ listRepos(owner) {
2365
+ let sql;
2366
+ if (owner) {
2367
+ sql = "SELECT DISTINCT repo FROM memories WHERE owner = ? UNION SELECT DISTINCT repo FROM tasks WHERE owner = ?";
2368
+ } else {
2369
+ sql = "SELECT DISTINCT repo FROM memories UNION SELECT DISTINCT repo FROM tasks";
2370
+ }
2371
+ const params = owner ? [owner, owner] : [];
2372
+ const rows = this.all(sql, params);
2256
2373
  return rows.map((r) => r.repo);
2257
2374
  }
2258
- listRepoNavigation() {
2259
- const repos = this.listRepos();
2375
+ listRepoNavigation(owner) {
2376
+ const repos = this.listRepos(owner);
2377
+ const ownerFilter = owner ? " AND owner = ?" : "";
2378
+ const ownerParams = owner ? [owner] : [];
2260
2379
  const activeClaimRows = this.all(
2261
- "SELECT repo, COUNT(*) as count FROM claims WHERE released_at IS NULL GROUP BY repo"
2380
+ `SELECT repo, COUNT(*) as count FROM claims WHERE released_at IS NULL${ownerFilter} GROUP BY repo`,
2381
+ ownerParams
2262
2382
  );
2263
2383
  const pendingHandoffRows = this.all(
2264
- "SELECT repo, COUNT(*) as count FROM handoffs WHERE status = 'pending' GROUP BY repo"
2384
+ `SELECT repo, COUNT(*) as count FROM handoffs WHERE status = 'pending'${ownerFilter} GROUP BY repo`,
2385
+ ownerParams
2265
2386
  );
2266
2387
  const unassignedHandoffRows = this.all(
2267
- "SELECT repo, COUNT(*) as count FROM handoffs WHERE status = 'pending' AND to_agent IS NULL GROUP BY repo"
2388
+ `SELECT repo, COUNT(*) as count FROM handoffs WHERE status = 'pending' AND to_agent IS NULL${ownerFilter} GROUP BY repo`,
2389
+ ownerParams
2268
2390
  );
2269
2391
  const staleClaimRows = this.all(
2270
- "SELECT repo, COUNT(*) as count FROM claims WHERE released_at IS NULL AND claimed_at <= datetime('now', '-1 day') GROUP BY repo"
2392
+ `SELECT repo, COUNT(*) as count FROM claims WHERE released_at IS NULL AND claimed_at <= datetime('now', '-1 day')${ownerFilter} GROUP BY repo`,
2393
+ ownerParams
2271
2394
  );
2272
2395
  const activeClaimsByRepo = Object.fromEntries(activeClaimRows.map((row) => [row.repo, row.count]));
2273
2396
  const pendingHandoffsByRepo = Object.fromEntries(pendingHandoffRows.map((row) => [row.repo, row.count]));
2274
2397
  const unassignedHandoffsByRepo = Object.fromEntries(unassignedHandoffRows.map((row) => [row.repo, row.count]));
2275
2398
  const staleClaimsByRepo = Object.fromEntries(staleClaimRows.map((row) => [row.repo, row.count]));
2399
+ const repoOwnerFilter = owner ? " AND owner = ?" : "";
2400
+ const repoOwnerParams = owner ? [owner] : [];
2276
2401
  return repos.map((repo) => {
2277
- const memoryCountRow = this.get("SELECT COUNT(*) as count FROM memories WHERE repo = ?", [
2278
- repo
2279
- ]);
2402
+ const memoryCountRow = this.get(
2403
+ `SELECT COUNT(*) as count FROM memories WHERE repo = ?${repoOwnerFilter}`,
2404
+ owner ? [repo, owner] : [repo]
2405
+ );
2280
2406
  const lastActivityRow = this.get(
2281
- `SELECT MAX(created_at) as last FROM (SELECT created_at FROM memories WHERE repo = ? UNION ALL SELECT created_at FROM tasks WHERE repo = ? UNION ALL SELECT created_at FROM action_log WHERE repo = ?)`,
2282
- [repo, repo, repo]
2407
+ `SELECT MAX(created_at) as last FROM (SELECT created_at FROM memories WHERE repo = ?${repoOwnerFilter} UNION ALL SELECT created_at FROM tasks WHERE repo = ?${repoOwnerFilter} UNION ALL SELECT created_at FROM action_log WHERE repo = ?${repoOwnerFilter})`,
2408
+ owner ? [repo, owner, repo, owner, repo, owner] : [repo, repo, repo]
2283
2409
  );
2284
2410
  const taskStatusRows = this.all(
2285
- "SELECT status, COUNT(*) as count FROM tasks WHERE repo = ? GROUP BY status",
2286
- [repo]
2411
+ `SELECT status, COUNT(*) as count FROM tasks WHERE repo = ?${repoOwnerFilter} GROUP BY status`,
2412
+ owner ? [repo, owner] : [repo]
2287
2413
  );
2288
2414
  const taskStatusMap = {};
2289
2415
  taskStatusRows.forEach((r) => {
@@ -2306,35 +2432,39 @@ var SystemEntity = class extends BaseEntity {
2306
2432
  };
2307
2433
  });
2308
2434
  }
2309
- getDashboardStats(repo) {
2310
- const totalCountRow = this.get("SELECT COUNT(*) as count FROM memories WHERE repo = ?", [repo]);
2311
- const avgImportanceRow = this.get("SELECT AVG(importance) as avg FROM memories WHERE repo = ?", [
2312
- repo
2313
- ]);
2435
+ getDashboardStats(owner, repo) {
2436
+ const totalCountRow = this.get(
2437
+ "SELECT COUNT(*) as count FROM memories WHERE owner = ? AND repo = ?",
2438
+ [owner, repo]
2439
+ );
2440
+ const avgImportanceRow = this.get(
2441
+ "SELECT AVG(importance) as avg FROM memories WHERE owner = ? AND repo = ?",
2442
+ [owner, repo]
2443
+ );
2314
2444
  const totalHitCountRow = this.get(
2315
- "SELECT SUM(hit_count) as count FROM memories WHERE repo = ?",
2316
- [repo]
2445
+ "SELECT SUM(hit_count) as count FROM memories WHERE owner = ? AND repo = ?",
2446
+ [owner, repo]
2317
2447
  );
2318
2448
  const expiringSoonRow = this.get(
2319
- "SELECT COUNT(*) as count FROM memories WHERE repo = ? AND expires_at IS NOT NULL AND expires_at > ? AND expires_at <= ?",
2320
- [repo, (/* @__PURE__ */ new Date()).toISOString(), new Date(Date.now() + 7 * 86400 * 1e3).toISOString()]
2449
+ "SELECT COUNT(*) as count FROM memories WHERE owner = ? AND repo = ? AND expires_at IS NOT NULL AND expires_at > ? AND expires_at <= ?",
2450
+ [owner, repo, (/* @__PURE__ */ new Date()).toISOString(), new Date(Date.now() + 7 * 86400 * 1e3).toISOString()]
2321
2451
  );
2322
2452
  const typeStats = this.all(
2323
- "SELECT type, COUNT(*) as count FROM memories WHERE repo = ? GROUP BY type",
2324
- [repo]
2453
+ "SELECT type, COUNT(*) as count FROM memories WHERE owner = ? AND repo = ? GROUP BY type",
2454
+ [owner, repo]
2325
2455
  );
2326
2456
  const byType = {};
2327
2457
  typeStats.forEach((t) => {
2328
2458
  byType[t.type] = t.count;
2329
2459
  });
2330
2460
  const taskRows = this.all(
2331
- "SELECT status, COUNT(*) as count FROM tasks WHERE repo = ? GROUP BY status",
2332
- [repo]
2461
+ "SELECT status, COUNT(*) as count FROM tasks WHERE owner = ? AND repo = ? GROUP BY status",
2462
+ [owner, repo]
2333
2463
  );
2334
2464
  const taskStats = this.buildTaskStats(taskRows);
2335
2465
  const topMemoriesRows = this.all(
2336
- "SELECT * FROM memories WHERE repo = ? ORDER BY importance DESC, created_at DESC LIMIT 5",
2337
- [repo]
2466
+ "SELECT * FROM memories WHERE owner = ? AND repo = ? ORDER BY importance DESC, created_at DESC LIMIT 5",
2467
+ [owner, repo]
2338
2468
  );
2339
2469
  const topMemories = topMemoriesRows.map((r) => this.rowToMemoryEntry(r));
2340
2470
  return {
@@ -2422,12 +2552,18 @@ var SystemEntity = class extends BaseEntity {
2422
2552
  totalRepos
2423
2553
  };
2424
2554
  }
2425
- getRepoDetails(repo) {
2426
- const memoryCountRow = this.get("SELECT COUNT(*) as count FROM memories WHERE repo = ?", [repo]);
2427
- const taskCountRow = this.get("SELECT COUNT(*) as count FROM tasks WHERE repo = ?", [repo]);
2555
+ getRepoDetails(owner, repo) {
2556
+ const memoryCountRow = this.get(
2557
+ "SELECT COUNT(*) as count FROM memories WHERE owner = ? AND repo = ?",
2558
+ [owner, repo]
2559
+ );
2560
+ const taskCountRow = this.get(
2561
+ "SELECT COUNT(*) as count FROM tasks WHERE owner = ? AND repo = ?",
2562
+ [owner, repo]
2563
+ );
2428
2564
  const languagesRows = this.all(
2429
- "SELECT DISTINCT language FROM memories WHERE repo = ? AND language IS NOT NULL",
2430
- [repo]
2565
+ "SELECT DISTINCT language FROM memories WHERE owner = ? AND repo = ? AND language IS NOT NULL",
2566
+ [owner, repo]
2431
2567
  );
2432
2568
  const languages = languagesRows.map((r) => r.language);
2433
2569
  return {
@@ -2441,19 +2577,33 @@ var SystemEntity = class extends BaseEntity {
2441
2577
 
2442
2578
  // src/mcp/entities/summary.ts
2443
2579
  var SummaryEntity = class extends BaseEntity {
2444
- getSummary(repo) {
2580
+ getSummary(owner, repo) {
2445
2581
  const row = this.get(
2446
- "SELECT summary, updated_at FROM memory_summary WHERE repo = ?",
2447
- [repo]
2582
+ "SELECT summary, updated_at FROM memory_summary WHERE owner = ? AND repo = ?",
2583
+ [owner, repo]
2448
2584
  );
2449
2585
  return row || null;
2450
2586
  }
2451
- upsertSummary(repo, summary) {
2452
- this.run(
2453
- `INSERT INTO memory_summary (repo, summary, updated_at) VALUES (?, ?, ?)
2454
- ON CONFLICT(repo) DO UPDATE SET summary = excluded.summary, updated_at = excluded.updated_at`,
2455
- [repo, summary, (/* @__PURE__ */ new Date()).toISOString()]
2456
- );
2587
+ upsertSummary(owner, repo, summary) {
2588
+ const existing = this.get("SELECT summary FROM memory_summary WHERE owner = ? AND repo = ?", [
2589
+ owner,
2590
+ repo
2591
+ ]);
2592
+ if (existing) {
2593
+ this.run("UPDATE memory_summary SET summary = ?, updated_at = ? WHERE owner = ? AND repo = ?", [
2594
+ summary,
2595
+ (/* @__PURE__ */ new Date()).toISOString(),
2596
+ owner,
2597
+ repo
2598
+ ]);
2599
+ } else {
2600
+ this.run("INSERT INTO memory_summary (owner, repo, summary, updated_at) VALUES (?, ?, ?, ?)", [
2601
+ owner,
2602
+ repo,
2603
+ summary,
2604
+ (/* @__PURE__ */ new Date()).toISOString()
2605
+ ]);
2606
+ }
2457
2607
  }
2458
2608
  };
2459
2609
 
@@ -2463,8 +2613,8 @@ var StandardEntity = class extends BaseEntity {
2463
2613
  this.run(
2464
2614
  `INSERT INTO coding_standards (
2465
2615
  id, code, title, content, parent_id, context, version, language, stack,
2466
- is_global, repo, tags, metadata, created_at, updated_at, hit_count, last_used_at, agent, model
2467
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2616
+ is_global, owner, repo, tags, metadata, created_at, updated_at, hit_count, last_used_at, agent, model
2617
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2468
2618
  [
2469
2619
  entry.id,
2470
2620
  entry.code ?? null,
@@ -2476,6 +2626,7 @@ var StandardEntity = class extends BaseEntity {
2476
2626
  entry.language ?? null,
2477
2627
  entry.stack.length > 0 ? JSON.stringify(entry.stack) : null,
2478
2628
  entry.is_global ? 1 : 0,
2629
+ entry.owner ?? "",
2479
2630
  entry.repo ?? null,
2480
2631
  entry.tags.length > 0 ? JSON.stringify(entry.tags) : null,
2481
2632
  Object.keys(entry.metadata).length > 0 ? JSON.stringify(entry.metadata) : null,
@@ -2495,8 +2646,8 @@ var StandardEntity = class extends BaseEntity {
2495
2646
  this.run(
2496
2647
  `INSERT INTO coding_standards (
2497
2648
  id, code, title, content, parent_id, context, version, language, stack,
2498
- is_global, repo, tags, metadata, created_at, updated_at, hit_count, last_used_at, agent, model
2499
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2649
+ is_global, owner, repo, tags, metadata, created_at, updated_at, hit_count, last_used_at, agent, model
2650
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2500
2651
  [
2501
2652
  entry.id,
2502
2653
  entry.code ?? null,
@@ -2508,6 +2659,7 @@ var StandardEntity = class extends BaseEntity {
2508
2659
  entry.language ?? null,
2509
2660
  entry.stack.length > 0 ? JSON.stringify(entry.stack) : null,
2510
2661
  entry.is_global ? 1 : 0,
2662
+ entry.owner ?? "",
2511
2663
  entry.repo ?? null,
2512
2664
  entry.tags.length > 0 ? JSON.stringify(entry.tags) : null,
2513
2665
  Object.keys(entry.metadata).length > 0 ? JSON.stringify(entry.metadata) : null,
@@ -2533,7 +2685,7 @@ var StandardEntity = class extends BaseEntity {
2533
2685
  return row ? this.rowToEntry(row) : null;
2534
2686
  }
2535
2687
  search(options) {
2536
- const { query, context, version, language, stack, tag, repo, is_global, limit = 20, offset = 0 } = options;
2688
+ const { query, context, version, language, stack, tag, owner, repo, is_global, limit = 20, offset = 0 } = options;
2537
2689
  const where = [];
2538
2690
  const params = [];
2539
2691
  if (query) {
@@ -2561,8 +2713,13 @@ var StandardEntity = class extends BaseEntity {
2561
2713
  params.push(`%${tag}%`);
2562
2714
  }
2563
2715
  if (repo !== void 0) {
2564
- where.push("(repo = ? OR is_global = 1)");
2565
- params.push(repo);
2716
+ if (owner !== void 0) {
2717
+ where.push("((owner = ? AND repo = ?) OR is_global = 1)");
2718
+ params.push(owner, repo);
2719
+ } else {
2720
+ where.push("(repo = ? OR is_global = 1)");
2721
+ params.push(repo);
2722
+ }
2566
2723
  }
2567
2724
  if (is_global !== void 0) {
2568
2725
  where.push("is_global = ?");
@@ -2611,11 +2768,12 @@ var StandardEntity = class extends BaseEntity {
2611
2768
  *
2612
2769
  * @param content Raw content of the new standard to check.
2613
2770
  * @param incomingVersion Version of the new standard (e.g. "2.0.0").
2771
+ * @param owner Owner filter; pass undefined for global standards.
2614
2772
  * @param repo Repo filter; pass undefined for global standards.
2615
2773
  * @param threshold Cosine-similarity cutoff (default 0.82 — stricter than memory).
2616
2774
  */
2617
- checkConflicts(content, incomingVersion, repo, incomingLanguage, incomingStack, threshold = 0.82) {
2618
- const candidates = this.search({ repo, limit: 80, offset: 0 });
2775
+ checkConflicts(content, incomingVersion, owner, repo, incomingLanguage, incomingStack, threshold = 0.82) {
2776
+ const candidates = this.search({ repo, owner, limit: 80, offset: 0 });
2619
2777
  if (candidates.length === 0) return null;
2620
2778
  const queryVector = this.computeVector(content);
2621
2779
  for (const standard of candidates) {
@@ -2716,6 +2874,7 @@ var StandardEntity = class extends BaseEntity {
2716
2874
  language: row.language ?? null,
2717
2875
  stack: this.safeJSONParse(row.stack, []),
2718
2876
  is_global: row.is_global === 1,
2877
+ owner: row.owner,
2719
2878
  repo: row.repo ?? null,
2720
2879
  tags: this.safeJSONParse(row.tags, []),
2721
2880
  metadata: this.safeJSONParse(row.metadata, {}),
@@ -2735,6 +2894,7 @@ var HandoffEntity = class extends BaseEntity {
2735
2894
  rowToHandoff(row) {
2736
2895
  return {
2737
2896
  id: row.id,
2897
+ owner: row.owner,
2738
2898
  repo: row.repo,
2739
2899
  from_agent: row.from_agent,
2740
2900
  to_agent: row.to_agent ?? null,
@@ -2751,6 +2911,7 @@ var HandoffEntity = class extends BaseEntity {
2751
2911
  rowToClaim(row) {
2752
2912
  return {
2753
2913
  id: row.id,
2914
+ owner: row.owner,
2754
2915
  repo: row.repo,
2755
2916
  task_id: row.task_id,
2756
2917
  task_code: "task_code" in row ? row.task_code ?? null : null,
@@ -2765,10 +2926,11 @@ var HandoffEntity = class extends BaseEntity {
2765
2926
  const now = (/* @__PURE__ */ new Date()).toISOString();
2766
2927
  const id = randomUUID();
2767
2928
  this.run(
2768
- `INSERT INTO handoffs (id, repo, from_agent, to_agent, task_id, summary, context, status, created_at, updated_at, expires_at)
2769
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2929
+ `INSERT INTO handoffs (id, owner, repo, from_agent, to_agent, task_id, summary, context, status, created_at, updated_at, expires_at)
2930
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2770
2931
  [
2771
2932
  id,
2933
+ params.owner,
2772
2934
  params.repo,
2773
2935
  params.from_agent,
2774
2936
  params.to_agent ?? null,
@@ -2784,8 +2946,8 @@ var HandoffEntity = class extends BaseEntity {
2784
2946
  return this.getHandoffById(id);
2785
2947
  }
2786
2948
  listHandoffs(params) {
2787
- const conditions = ["repo = ?"];
2788
- const values = [params.repo];
2949
+ const conditions = ["owner = ?", "repo = ?"];
2950
+ const values = [params.owner, params.repo];
2789
2951
  if (params.status) {
2790
2952
  conditions.push("status = ?");
2791
2953
  values.push(params.status);
@@ -2806,7 +2968,7 @@ var HandoffEntity = class extends BaseEntity {
2806
2968
  FROM handoffs h
2807
2969
  LEFT JOIN tasks t ON h.task_id = t.id
2808
2970
  WHERE ${conditions.map(
2809
- (condition) => condition.replace(/\brepo\b/g, "h.repo").replace(/\bstatus\b/g, "h.status").replace(/\bto_agent\b/g, "h.to_agent").replace(/\bfrom_agent\b/g, "h.from_agent")
2971
+ (condition) => condition.replace(/\bowner\b/g, "h.owner").replace(/\brepo\b/g, "h.repo").replace(/\bstatus\b/g, "h.status").replace(/\bto_agent\b/g, "h.to_agent").replace(/\bfrom_agent\b/g, "h.from_agent")
2810
2972
  ).join(" AND ")}
2811
2973
  ORDER BY h.created_at DESC LIMIT ? OFFSET ?`,
2812
2974
  values
@@ -2844,10 +3006,11 @@ var HandoffEntity = class extends BaseEntity {
2844
3006
  const id = randomUUID();
2845
3007
  this.run("UPDATE claims SET released_at = ? WHERE task_id = ? AND released_at IS NULL", [now, params.task_id]);
2846
3008
  this.run(
2847
- `INSERT INTO claims (id, repo, task_id, agent, role, claimed_at, released_at, metadata)
2848
- VALUES (?, ?, ?, ?, ?, ?, NULL, ?)`,
3009
+ `INSERT INTO claims (id, owner, repo, task_id, agent, role, claimed_at, released_at, metadata)
3010
+ VALUES (?, ?, ?, ?, ?, ?, ?, NULL, ?)`,
2849
3011
  [
2850
3012
  id,
3013
+ params.owner,
2851
3014
  params.repo,
2852
3015
  params.task_id,
2853
3016
  params.agent,
@@ -2896,8 +3059,8 @@ var HandoffEntity = class extends BaseEntity {
2896
3059
  return result.changes;
2897
3060
  }
2898
3061
  listClaims(params) {
2899
- const conditions = ["repo = ?"];
2900
- const values = [params.repo];
3062
+ const conditions = params.owner ? ["owner = ?", "repo = ?"] : ["repo = ?"];
3063
+ const values = params.owner ? [params.owner, params.repo] : [params.repo];
2901
3064
  if (params.agent) {
2902
3065
  conditions.push("agent = ?");
2903
3066
  values.push(params.agent);
@@ -2913,7 +3076,7 @@ var HandoffEntity = class extends BaseEntity {
2913
3076
  FROM claims c
2914
3077
  LEFT JOIN tasks t ON c.task_id = t.id
2915
3078
  WHERE ${conditions.map(
2916
- (condition) => condition.replace(/\brepo\b/g, "c.repo").replace(/\bagent\b/g, "c.agent").replace(/released_at/g, "c.released_at")
3079
+ (condition) => condition.replace(/\bowner\b/g, "c.owner").replace(/\brepo\b/g, "c.repo").replace(/\bagent\b/g, "c.agent").replace(/released_at/g, "c.released_at")
2917
3080
  ).join(" AND ")}
2918
3081
  ORDER BY c.claimed_at DESC LIMIT ? OFFSET ?`,
2919
3082
  values
@@ -3207,7 +3370,7 @@ var RealVectorStore = class {
3207
3370
  const extractor = await this.getExtractor();
3208
3371
  const output = await extractor(query, { pooling: "mean", normalize: true });
3209
3372
  const queryVector = Array.from(output.data);
3210
- const rows = kind === "standard" ? this.db.standards.getVectorCandidates(repo, 100).map((row) => ({ id: row.standard_id, vector: row.vector })) : this.db.memoryVectors.getVectorCandidates(repo, 100).map((row) => ({ id: row.memory_id, vector: row.vector }));
3373
+ const rows = kind === "standard" ? this.db.standards.getVectorCandidates(repo, 100).map((row) => ({ id: row.standard_id, vector: row.vector })) : this.db.memoryVectors.getVectorCandidates("", repo, 100).map((row) => ({ id: row.memory_id, vector: row.vector }));
3211
3374
  const results = rows.map((row) => {
3212
3375
  const memoryVector = JSON.parse(row.vector);
3213
3376
  return {
@@ -3328,6 +3491,7 @@ function inferRepoFromSession(session) {
3328
3491
  // src/mcp/tools/schemas.ts
3329
3492
  import { z } from "zod";
3330
3493
  var MemoryScopeSchema = z.object({
3494
+ owner: z.string().min(1),
3331
3495
  repo: z.string().min(1).transform(normalizeRepo),
3332
3496
  branch: z.string().optional(),
3333
3497
  folder: z.string().optional(),
@@ -3417,6 +3581,7 @@ var MemoryUpdateSchema = z.object({
3417
3581
  var MemorySearchSchema = z.object({
3418
3582
  query: z.string().min(3),
3419
3583
  prompt: z.string().optional(),
3584
+ owner: z.string().min(1),
3420
3585
  repo: z.string().min(1).transform(normalizeRepo),
3421
3586
  types: z.array(MemoryTypeSchema).optional(),
3422
3587
  minImportance: z.number().min(1).max(5).optional(),
@@ -3439,12 +3604,14 @@ var MemoryAcknowledgeSchema = z.object({
3439
3604
  message: "Either memory_id or code must be provided"
3440
3605
  });
3441
3606
  var MemoryRecapSchema = z.object({
3607
+ owner: z.string().min(1),
3442
3608
  repo: z.string().min(1).transform(normalizeRepo),
3443
3609
  limit: z.number().min(1).max(50).default(20),
3444
3610
  offset: z.number().min(0).default(0),
3445
3611
  structured: z.boolean().default(false)
3446
3612
  });
3447
3613
  var MemoryDeleteSchema = z.object({
3614
+ owner: z.string().optional().default(""),
3448
3615
  repo: z.string().min(1).transform(normalizeRepo).optional(),
3449
3616
  id: z.string().uuid().optional(),
3450
3617
  ids: z.array(z.string().uuid()).min(1).optional(),
@@ -3458,11 +3625,13 @@ var MemoryDeleteSchema = z.object({
3458
3625
  }
3459
3626
  );
3460
3627
  var MemorySummarizeSchema = z.object({
3628
+ owner: z.string().min(1),
3461
3629
  repo: z.string().min(1).transform(normalizeRepo),
3462
3630
  signals: z.array(z.string().max(200)).min(1),
3463
3631
  structured: z.boolean().default(false)
3464
3632
  });
3465
3633
  var MemorySynthesizeSchema = z.object({
3634
+ owner: z.string().min(1),
3466
3635
  repo: z.string().min(1).transform(normalizeRepo).optional(),
3467
3636
  objective: z.string().min(5),
3468
3637
  current_file_path: z.string().optional(),
@@ -3479,20 +3648,44 @@ var TaskMetadataSchema = z.record(z.string(), z.any()).optional().superRefine((m
3479
3648
  if (!metadata) return;
3480
3649
  if (metadata.required_skills !== void 0) {
3481
3650
  if (!Array.isArray(metadata.required_skills)) {
3482
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "metadata.required_skills must be an array of strings", path: ["metadata", "required_skills"] });
3651
+ ctx.addIssue({
3652
+ code: z.ZodIssueCode.custom,
3653
+ message: "metadata.required_skills must be an array of strings",
3654
+ path: ["metadata", "required_skills"]
3655
+ });
3483
3656
  } else if (metadata.required_skills.length === 0) {
3484
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "metadata.required_skills must not be empty when present", path: ["metadata", "required_skills"] });
3657
+ ctx.addIssue({
3658
+ code: z.ZodIssueCode.custom,
3659
+ message: "metadata.required_skills must not be empty when present",
3660
+ path: ["metadata", "required_skills"]
3661
+ });
3485
3662
  } else if (!metadata.required_skills.every((s) => typeof s === "string" && s.length > 0)) {
3486
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "metadata.required_skills must be an array of non-empty strings", path: ["metadata", "required_skills"] });
3663
+ ctx.addIssue({
3664
+ code: z.ZodIssueCode.custom,
3665
+ message: "metadata.required_skills must be an array of non-empty strings",
3666
+ path: ["metadata", "required_skills"]
3667
+ });
3487
3668
  }
3488
3669
  }
3489
3670
  if (metadata.fsm_gates !== void 0) {
3490
3671
  if (!Array.isArray(metadata.fsm_gates)) {
3491
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "metadata.fsm_gates must be an array of strings", path: ["metadata", "fsm_gates"] });
3672
+ ctx.addIssue({
3673
+ code: z.ZodIssueCode.custom,
3674
+ message: "metadata.fsm_gates must be an array of strings",
3675
+ path: ["metadata", "fsm_gates"]
3676
+ });
3492
3677
  } else if (metadata.fsm_gates.length === 0) {
3493
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "metadata.fsm_gates must not be empty when present", path: ["metadata", "fsm_gates"] });
3678
+ ctx.addIssue({
3679
+ code: z.ZodIssueCode.custom,
3680
+ message: "metadata.fsm_gates must not be empty when present",
3681
+ path: ["metadata", "fsm_gates"]
3682
+ });
3494
3683
  } else if (!metadata.fsm_gates.every((s) => typeof s === "string" && s.length > 0)) {
3495
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: "metadata.fsm_gates must be an array of non-empty strings", path: ["metadata", "fsm_gates"] });
3684
+ ctx.addIssue({
3685
+ code: z.ZodIssueCode.custom,
3686
+ message: "metadata.fsm_gates must be an array of non-empty strings",
3687
+ path: ["metadata", "fsm_gates"]
3688
+ });
3496
3689
  }
3497
3690
  }
3498
3691
  });
@@ -3514,6 +3707,7 @@ var SingleTaskCreateSchema = z.object({
3514
3707
  est_tokens: z.number().int().min(0).optional()
3515
3708
  });
3516
3709
  var TaskCreateSchema = z.object({
3710
+ owner: z.string().min(1),
3517
3711
  repo: z.string().min(1).transform(normalizeRepo),
3518
3712
  // Allow single task fields at top level (backward compatibility & single use)
3519
3713
  task_code: z.string().min(1).optional(),
@@ -3542,10 +3736,12 @@ var TaskCreateSchema = z.object({
3542
3736
  { message: "Either 'tasks' array or single task fields (phase, title, description) must be provided" }
3543
3737
  );
3544
3738
  var TaskCreateInteractiveSchema = SingleTaskCreateSchema.partial().extend({
3739
+ owner: z.string().optional().default(""),
3545
3740
  repo: z.string().min(1).transform(normalizeRepo).optional(),
3546
3741
  structured: z.boolean().default(false)
3547
3742
  });
3548
3743
  var TaskUpdateSchema = z.object({
3744
+ owner: z.string().optional().default(""),
3549
3745
  repo: z.string().min(1).transform(normalizeRepo),
3550
3746
  id: z.string().uuid().optional(),
3551
3747
  ids: z.array(z.string().uuid()).min(1).optional(),
@@ -3576,6 +3772,7 @@ var TaskUpdateSchema = z.object({
3576
3772
  message: "At least one field besides repo and id/ids must be provided for update"
3577
3773
  });
3578
3774
  var TaskListSchema = z.object({
3775
+ owner: z.string().min(1),
3579
3776
  repo: z.string().min(1).transform(normalizeRepo),
3580
3777
  status: z.string().optional(),
3581
3778
  phase: z.string().optional(),
@@ -3585,6 +3782,7 @@ var TaskListSchema = z.object({
3585
3782
  structured: z.boolean().default(false)
3586
3783
  });
3587
3784
  var TaskSearchSchema = z.object({
3785
+ owner: z.string().min(1),
3588
3786
  repo: z.string().min(1).transform(normalizeRepo),
3589
3787
  query: z.string().min(1),
3590
3788
  status: z.string().optional(),
@@ -3595,6 +3793,7 @@ var TaskSearchSchema = z.object({
3595
3793
  structured: z.boolean().default(false)
3596
3794
  });
3597
3795
  var TaskDeleteSchema = z.object({
3796
+ owner: z.string().optional().default(""),
3598
3797
  repo: z.string().min(1).transform(normalizeRepo),
3599
3798
  id: z.string().uuid().optional(),
3600
3799
  ids: z.array(z.string().uuid()).min(1).optional(),
@@ -3618,6 +3817,7 @@ var StandardDetailSchema = z.object({
3618
3817
  message: "Either id or code must be provided"
3619
3818
  });
3620
3819
  var StandardDeleteSchema = z.object({
3820
+ owner: z.string().optional().default(""),
3621
3821
  repo: z.string().min(1).transform(normalizeRepo).optional(),
3622
3822
  id: z.string().uuid().optional(),
3623
3823
  ids: z.array(z.string().uuid()).min(1).optional(),
@@ -3631,6 +3831,7 @@ var StandardDeleteSchema = z.object({
3631
3831
  }
3632
3832
  );
3633
3833
  var TaskGetSchema = z.object({
3834
+ owner: z.string().optional().default(""),
3634
3835
  repo: z.string().min(1).transform(normalizeRepo),
3635
3836
  id: z.string().uuid().optional(),
3636
3837
  task_code: z.string().optional(),
@@ -3640,6 +3841,7 @@ var TaskGetSchema = z.object({
3640
3841
  });
3641
3842
  var HandoffStatusSchema = z.enum(["pending", "accepted", "rejected", "expired"]);
3642
3843
  var HandoffCreateSchema = z.object({
3844
+ owner: z.string().min(1),
3643
3845
  repo: z.string().min(1).transform(normalizeRepo),
3644
3846
  from_agent: z.string().min(1),
3645
3847
  to_agent: z.string().min(1).optional(),
@@ -3663,6 +3865,7 @@ var HandoffUpdateSchema = z.object({
3663
3865
  structured: z.boolean().default(false)
3664
3866
  });
3665
3867
  var HandoffListSchema = z.object({
3868
+ owner: z.string().min(1),
3666
3869
  repo: z.string().min(1).transform(normalizeRepo),
3667
3870
  status: HandoffStatusSchema.optional(),
3668
3871
  from_agent: z.string().min(1).optional(),
@@ -3672,6 +3875,7 @@ var HandoffListSchema = z.object({
3672
3875
  structured: z.boolean().default(false)
3673
3876
  });
3674
3877
  var TaskClaimSchema = z.object({
3878
+ owner: z.string().min(1),
3675
3879
  repo: z.string().min(1).transform(normalizeRepo),
3676
3880
  task_id: z.string().uuid().optional(),
3677
3881
  task_code: z.string().optional(),
@@ -3685,6 +3889,7 @@ var TaskClaimSchema = z.object({
3685
3889
  message: "Provide either task_id or task_code, not both"
3686
3890
  });
3687
3891
  var ClaimListSchema = z.object({
3892
+ owner: z.string().min(1),
3688
3893
  repo: z.string().min(1).transform(normalizeRepo),
3689
3894
  agent: z.string().min(1).optional(),
3690
3895
  active_only: z.boolean().default(true),
@@ -3693,6 +3898,7 @@ var ClaimListSchema = z.object({
3693
3898
  structured: z.boolean().default(false)
3694
3899
  });
3695
3900
  var ClaimReleaseSchema = z.object({
3901
+ owner: z.string().optional().default(""),
3696
3902
  repo: z.string().min(1).transform(normalizeRepo),
3697
3903
  task_id: z.string().uuid().optional(),
3698
3904
  task_code: z.string().optional(),
@@ -3711,6 +3917,7 @@ var StandardStoreSchema = z.object({
3711
3917
  version: z.string().optional(),
3712
3918
  language: z.string().optional(),
3713
3919
  stack: z.array(z.string()).optional(),
3920
+ owner: z.string().optional().default(""),
3714
3921
  repo: z.string().transform(normalizeRepo).optional(),
3715
3922
  is_global: z.boolean().optional(),
3716
3923
  tags: z.array(z.string().min(1)).min(1).optional(),
@@ -3738,6 +3945,7 @@ var StandardUpdateSchema = z.object({
3738
3945
  version: z.string().optional(),
3739
3946
  language: z.string().optional(),
3740
3947
  stack: z.array(z.string().min(1)).min(1).optional(),
3948
+ owner: z.string().optional().default(""),
3741
3949
  repo: z.string().transform(normalizeRepo).optional(),
3742
3950
  is_global: z.boolean().optional(),
3743
3951
  tags: z.array(z.string().min(1)).min(1).optional(),
@@ -3760,6 +3968,7 @@ var StandardSearchSchema = z.object({
3760
3968
  language: z.string().optional(),
3761
3969
  context: z.string().optional(),
3762
3970
  version: z.string().optional(),
3971
+ owner: z.string().optional().default(""),
3763
3972
  repo: z.string().transform(normalizeRepo).optional(),
3764
3973
  is_global: z.boolean().optional(),
3765
3974
  limit: z.number().min(1).max(100).default(20),
@@ -5518,7 +5727,7 @@ function readResource(uri, db, session) {
5518
5727
  if (repoBase) {
5519
5728
  const { name, path: repoPath, query } = repoBase;
5520
5729
  if (repoPath === "summary") {
5521
- const summary = db.summaries.getSummary(name);
5730
+ const summary = db.summaries.getSummary("", name);
5522
5731
  const text = summary?.summary || `No summary available for repository: ${name}`;
5523
5732
  return {
5524
5733
  contents: [
@@ -5570,12 +5779,13 @@ function readResource(uri, db, session) {
5570
5779
  if (repoPath === "tasks") {
5571
5780
  const status = query.get("status");
5572
5781
  const priority = query.get("priority");
5782
+ const owner = parseRepoInput(name).owner;
5573
5783
  let tasks;
5574
5784
  if (status && status !== "all") {
5575
5785
  const statuses = status.split(",").map((s) => s.trim());
5576
- tasks = db.tasks.getTasksByMultipleStatuses(name, statuses);
5786
+ tasks = db.tasks.getTasksByMultipleStatuses(owner, name, statuses);
5577
5787
  } else {
5578
- tasks = db.tasks.getTasksByMultipleStatuses(name, ["backlog", "pending", "in_progress", "blocked"]);
5788
+ tasks = db.tasks.getTasksByMultipleStatuses(owner, name, ["backlog", "pending", "in_progress", "blocked"]);
5579
5789
  }
5580
5790
  if (priority) {
5581
5791
  const p = Number(priority);
@@ -5601,7 +5811,7 @@ function readResource(uri, db, session) {
5601
5811
  };
5602
5812
  }
5603
5813
  if (repoPath === "actions") {
5604
- const actions = db.actions.getRecentActions(name, 100);
5814
+ const actions = db.actions.getRecentActions("", name, 100);
5605
5815
  const payload = JSON.stringify(actions, null, 2);
5606
5816
  return {
5607
5817
  contents: [
@@ -5770,6 +5980,9 @@ async function completePromptArgument(name, argName, value, contextArguments, da
5770
5980
  return [];
5771
5981
  }
5772
5982
 
5983
+ // src/mcp/tools/handoff.manage.ts
5984
+ import { randomUUID as randomUUID2 } from "crypto";
5985
+
5773
5986
  // src/mcp/utils/mcp-response.ts
5774
5987
  import { z as z2 } from "zod";
5775
5988
  var McpAnnotationsSchema = z2.object({
@@ -5902,16 +6115,17 @@ function buildClaimListSummary(repo, count, agent, activeOnly) {
5902
6115
  }
5903
6116
  async function handleHandoffCreate(args, storage) {
5904
6117
  const validated = HandoffCreateSchema.parse(args);
5905
- const { repo, from_agent, to_agent, task_id, task_code, summary, context, expires_at, structured } = validated;
6118
+ const { owner, repo, from_agent, to_agent, task_id, task_code, summary, context, expires_at, structured } = validated;
5906
6119
  let resolvedTaskId = task_id ?? null;
5907
6120
  if (!resolvedTaskId && task_code) {
5908
- const task = storage.tasks.getTaskByCode(repo, task_code);
6121
+ const task = storage.tasks.getTaskByCode(owner, repo, task_code);
5909
6122
  if (!task) {
5910
6123
  throw new Error(`Task not found: ${task_code} in repo ${repo}`);
5911
6124
  }
5912
6125
  resolvedTaskId = task.id;
5913
6126
  }
5914
6127
  const handoff = storage.handoffs.createHandoff({
6128
+ owner,
5915
6129
  repo,
5916
6130
  from_agent,
5917
6131
  to_agent,
@@ -5936,8 +6150,9 @@ async function handleHandoffCreate(args, storage) {
5936
6150
  }
5937
6151
  async function handleHandoffList(args, storage) {
5938
6152
  const validated = HandoffListSchema.parse(args);
5939
- const { repo, status, from_agent, to_agent, limit, offset, structured } = validated;
6153
+ const { owner, repo, status, from_agent, to_agent, limit, offset, structured } = validated;
5940
6154
  const handoffs = storage.handoffs.listHandoffs({
6155
+ owner,
5941
6156
  repo,
5942
6157
  status,
5943
6158
  from_agent,
@@ -6012,17 +6227,18 @@ async function handleHandoffUpdate(args, storage) {
6012
6227
  }
6013
6228
  async function handleTaskClaim(args, storage) {
6014
6229
  const validated = TaskClaimSchema.parse(args);
6015
- const { repo, task_id, task_code, agent, role, metadata, structured } = validated;
6230
+ const { owner, repo, task_id, task_code, agent, role, metadata, structured } = validated;
6016
6231
  let taskId = task_id;
6017
6232
  let resolvedTaskCode;
6233
+ let task = null;
6018
6234
  if (taskId) {
6019
- const task = storage.tasks.getTaskById(taskId);
6235
+ task = storage.tasks.getTaskById(taskId);
6020
6236
  if (!task || task.repo !== repo) {
6021
6237
  throw new Error(`Task not found: ${taskId} in repo ${repo}`);
6022
6238
  }
6023
6239
  resolvedTaskCode = task.task_code;
6024
6240
  } else if (task_code) {
6025
- const task = storage.tasks.getTaskByCode(repo, task_code);
6241
+ task = storage.tasks.getTaskByCode(owner, repo, task_code);
6026
6242
  if (!task) {
6027
6243
  throw new Error(`Task not found: ${task_code} in repo ${repo}`);
6028
6244
  }
@@ -6032,12 +6248,30 @@ async function handleTaskClaim(args, storage) {
6032
6248
  throw new Error("Either task_id or task_code must be provided");
6033
6249
  }
6034
6250
  const claim = storage.handoffs.claimTask({
6251
+ owner,
6035
6252
  repo,
6036
6253
  task_id: taskId,
6037
6254
  agent,
6038
6255
  role,
6039
6256
  metadata
6040
6257
  });
6258
+ if (task && task.status !== "completed") {
6259
+ const now = (/* @__PURE__ */ new Date()).toISOString();
6260
+ storage.tasks.updateTask(task.id, { status: "in_progress", in_progress_at: now });
6261
+ storage.taskComments.insertTaskComment({
6262
+ id: randomUUID2(),
6263
+ task_id: task.id,
6264
+ owner: repo,
6265
+ repo,
6266
+ comment: `Claimed by ${agent} \u2014 auto-promoted to in_progress`,
6267
+ agent,
6268
+ role: role || "unknown",
6269
+ model: "system",
6270
+ previous_status: task.status,
6271
+ next_status: "in_progress",
6272
+ created_at: now
6273
+ });
6274
+ }
6041
6275
  const responseData = {
6042
6276
  ...claim,
6043
6277
  task_code: resolvedTaskCode
@@ -6061,8 +6295,9 @@ async function handleTaskClaim(args, storage) {
6061
6295
  }
6062
6296
  async function handleClaimList(args, storage) {
6063
6297
  const validated = ClaimListSchema.parse(args);
6064
- const { repo, agent, active_only, limit, offset, structured } = validated;
6298
+ const { owner, repo, agent, active_only, limit, offset, structured } = validated;
6065
6299
  const claims = storage.handoffs.listClaims({
6300
+ owner,
6066
6301
  repo,
6067
6302
  agent,
6068
6303
  active_only,
@@ -6097,7 +6332,7 @@ async function handleClaimList(args, storage) {
6097
6332
  }
6098
6333
  async function handleClaimRelease(args, storage) {
6099
6334
  const validated = ClaimReleaseSchema.parse(args);
6100
- const { repo, task_id, task_code, agent, structured } = validated;
6335
+ const { owner, repo, task_id, task_code, agent, structured } = validated;
6101
6336
  let resolvedTaskId = task_id;
6102
6337
  let resolvedTaskCode = task_code ?? null;
6103
6338
  if (resolvedTaskId) {
@@ -6107,7 +6342,7 @@ async function handleClaimRelease(args, storage) {
6107
6342
  }
6108
6343
  resolvedTaskCode = task.task_code;
6109
6344
  } else if (task_code) {
6110
- const task = storage.tasks.getTaskByCode(repo, task_code);
6345
+ const task = storage.tasks.getTaskByCode(owner, repo, task_code);
6111
6346
  if (!task) {
6112
6347
  throw new Error(`Task not found: ${task_code} in repo ${repo}`);
6113
6348
  }