@askexenow/exe-os 0.8.40 → 0.8.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/bin/backfill-conversations.js +805 -642
  2. package/dist/bin/backfill-responses.js +804 -641
  3. package/dist/bin/backfill-vectors.js +791 -634
  4. package/dist/bin/cleanup-stale-review-tasks.js +788 -631
  5. package/dist/bin/cli.js +1376 -659
  6. package/dist/bin/exe-agent.js +20 -1
  7. package/dist/bin/exe-assign.js +1503 -1343
  8. package/dist/bin/exe-boot.js +2549 -1784
  9. package/dist/bin/exe-call.js +39 -1
  10. package/dist/bin/exe-cloud.js +12 -2
  11. package/dist/bin/exe-dispatch.js +39 -2
  12. package/dist/bin/exe-doctor.js +791 -634
  13. package/dist/bin/exe-export-behaviors.js +792 -637
  14. package/dist/bin/exe-forget.js +145 -0
  15. package/dist/bin/exe-gateway.js +2501 -1846
  16. package/dist/bin/exe-heartbeat.js +147 -1
  17. package/dist/bin/exe-kill.js +795 -640
  18. package/dist/bin/exe-launch-agent.js +2168 -2008
  19. package/dist/bin/exe-link.js +44 -12
  20. package/dist/bin/exe-new-employee.js +6 -2
  21. package/dist/bin/exe-pending-messages.js +146 -1
  22. package/dist/bin/exe-pending-notifications.js +788 -631
  23. package/dist/bin/exe-pending-reviews.js +176 -1
  24. package/dist/bin/exe-rename.js +23 -0
  25. package/dist/bin/exe-review.js +490 -327
  26. package/dist/bin/exe-search.js +157 -4
  27. package/dist/bin/exe-session-cleanup.js +2487 -403
  28. package/dist/bin/exe-settings.js +2 -1
  29. package/dist/bin/exe-status.js +474 -317
  30. package/dist/bin/exe-team.js +474 -317
  31. package/dist/bin/git-sweep.js +2691 -151
  32. package/dist/bin/graph-backfill.js +794 -637
  33. package/dist/bin/graph-export.js +798 -641
  34. package/dist/bin/scan-tasks.js +2951 -44
  35. package/dist/bin/setup.js +50 -26
  36. package/dist/bin/shard-migrate.js +792 -637
  37. package/dist/bin/wiki-sync.js +794 -637
  38. package/dist/gateway/index.js +2542 -1887
  39. package/dist/hooks/bug-report-worker.js +2118 -576
  40. package/dist/hooks/commit-complete.js +2690 -150
  41. package/dist/hooks/error-recall.js +157 -4
  42. package/dist/hooks/ingest-worker.js +1455 -803
  43. package/dist/hooks/instructions-loaded.js +151 -0
  44. package/dist/hooks/notification.js +153 -2
  45. package/dist/hooks/post-compact.js +164 -0
  46. package/dist/hooks/pre-compact.js +3073 -101
  47. package/dist/hooks/pre-tool-use.js +151 -0
  48. package/dist/hooks/prompt-ingest-worker.js +1670 -1509
  49. package/dist/hooks/prompt-submit.js +2650 -1074
  50. package/dist/hooks/response-ingest-worker.js +154 -6
  51. package/dist/hooks/session-end.js +153 -2
  52. package/dist/hooks/session-start.js +157 -4
  53. package/dist/hooks/stop.js +151 -0
  54. package/dist/hooks/subagent-stop.js +155 -2
  55. package/dist/hooks/summary-worker.js +190 -21
  56. package/dist/index.js +326 -102
  57. package/dist/lib/cloud-sync.js +31 -10
  58. package/dist/lib/config.js +2 -0
  59. package/dist/lib/consolidation.js +69 -2
  60. package/dist/lib/database.js +19 -0
  61. package/dist/lib/device-registry.js +19 -0
  62. package/dist/lib/embedder.js +3 -1
  63. package/dist/lib/employee-templates.js +20 -1
  64. package/dist/lib/exe-daemon.js +285 -18
  65. package/dist/lib/hybrid-search.js +157 -4
  66. package/dist/lib/messaging.js +39 -2
  67. package/dist/lib/schedules.js +792 -637
  68. package/dist/lib/store.js +796 -636
  69. package/dist/lib/tasks.js +1485 -918
  70. package/dist/lib/tmux-routing.js +194 -10
  71. package/dist/mcp/server.js +1643 -924
  72. package/dist/mcp/tools/create-task.js +2283 -829
  73. package/dist/mcp/tools/list-tasks.js +2788 -159
  74. package/dist/mcp/tools/send-message.js +39 -2
  75. package/dist/mcp/tools/update-task.js +79 -0
  76. package/dist/runtime/index.js +280 -68
  77. package/dist/tui/App.js +1485 -645
  78. package/package.json +3 -2
@@ -319,6 +319,13 @@ async function ensureSchema() {
319
319
  });
320
320
  } catch {
321
321
  }
322
+ try {
323
+ await client.execute({
324
+ sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
325
+ args: []
326
+ });
327
+ } catch {
328
+ }
322
329
  try {
323
330
  await client.execute({
324
331
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -765,6 +772,18 @@ async function ensureSchema() {
765
772
  CREATE INDEX IF NOT EXISTS idx_session_kills_agent
766
773
  ON session_kills(agent_id);
767
774
  `);
775
+ await client.execute(`
776
+ CREATE TABLE IF NOT EXISTS global_procedures (
777
+ id TEXT PRIMARY KEY,
778
+ title TEXT NOT NULL,
779
+ content TEXT NOT NULL,
780
+ priority TEXT NOT NULL DEFAULT 'p0',
781
+ domain TEXT,
782
+ active INTEGER NOT NULL DEFAULT 1,
783
+ created_at TEXT NOT NULL,
784
+ updated_at TEXT NOT NULL
785
+ )
786
+ `);
768
787
  await client.executeMultiple(`
769
788
  CREATE TABLE IF NOT EXISTS conversations (
770
789
  id TEXT PRIMARY KEY,
@@ -919,6 +938,7 @@ var config_exports = {};
919
938
  __export(config_exports, {
920
939
  CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
921
940
  CONFIG_PATH: () => CONFIG_PATH,
941
+ COO_AGENT_NAME: () => COO_AGENT_NAME,
922
942
  CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
923
943
  DB_PATH: () => DB_PATH,
924
944
  EXE_AI_DIR: () => EXE_AI_DIR,
@@ -1074,7 +1094,7 @@ async function loadConfigFrom(configPath) {
1074
1094
  return { ...DEFAULT_CONFIG };
1075
1095
  }
1076
1096
  }
1077
- var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
1097
+ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, COO_AGENT_NAME, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
1078
1098
  var init_config = __esm({
1079
1099
  "src/lib/config.ts"() {
1080
1100
  "use strict";
@@ -1082,6 +1102,7 @@ var init_config = __esm({
1082
1102
  DB_PATH = path3.join(EXE_AI_DIR, "memories.db");
1083
1103
  MODELS_DIR = path3.join(EXE_AI_DIR, "models");
1084
1104
  CONFIG_PATH = path3.join(EXE_AI_DIR, "config.json");
1105
+ COO_AGENT_NAME = "exe";
1085
1106
  LEGACY_LANCE_PATH = path3.join(EXE_AI_DIR, "local.lance");
1086
1107
  CURRENT_CONFIG_VERSION = 1;
1087
1108
  DEFAULT_CONFIG = {
@@ -1401,10 +1422,75 @@ var init_shard_manager = __esm({
1401
1422
  }
1402
1423
  });
1403
1424
 
1425
+ // src/lib/global-procedures.ts
1426
+ var global_procedures_exports = {};
1427
+ __export(global_procedures_exports, {
1428
+ deactivateGlobalProcedure: () => deactivateGlobalProcedure,
1429
+ getGlobalProceduresBlock: () => getGlobalProceduresBlock,
1430
+ loadGlobalProcedures: () => loadGlobalProcedures,
1431
+ storeGlobalProcedure: () => storeGlobalProcedure
1432
+ });
1433
+ import { randomUUID } from "crypto";
1434
+ async function loadGlobalProcedures() {
1435
+ const client = getClient();
1436
+ const result = await client.execute({
1437
+ sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
1438
+ args: []
1439
+ });
1440
+ const procedures = result.rows;
1441
+ if (procedures.length > 0) {
1442
+ _cache = procedures.map((p) => `### ${p.title}
1443
+ ${p.content}`).join("\n\n");
1444
+ } else {
1445
+ _cache = "";
1446
+ }
1447
+ _cacheLoaded = true;
1448
+ return procedures;
1449
+ }
1450
+ function getGlobalProceduresBlock() {
1451
+ if (!_cacheLoaded) return "";
1452
+ if (!_cache) return "";
1453
+ return `## Organization-Wide Procedures (MANDATORY \u2014 supersedes all other rules)
1454
+
1455
+ ${_cache}
1456
+ `;
1457
+ }
1458
+ async function storeGlobalProcedure(input) {
1459
+ const id = randomUUID();
1460
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1461
+ const client = getClient();
1462
+ await client.execute({
1463
+ sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
1464
+ VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
1465
+ args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
1466
+ });
1467
+ await loadGlobalProcedures();
1468
+ return id;
1469
+ }
1470
+ async function deactivateGlobalProcedure(id) {
1471
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1472
+ const client = getClient();
1473
+ const result = await client.execute({
1474
+ sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
1475
+ args: [now, id]
1476
+ });
1477
+ await loadGlobalProcedures();
1478
+ return result.rowsAffected > 0;
1479
+ }
1480
+ var _cache, _cacheLoaded;
1481
+ var init_global_procedures = __esm({
1482
+ "src/lib/global-procedures.ts"() {
1483
+ "use strict";
1484
+ init_database();
1485
+ _cache = "";
1486
+ _cacheLoaded = false;
1487
+ }
1488
+ });
1489
+
1404
1490
  // src/lib/exe-daemon-client.ts
1405
1491
  import net from "net";
1406
1492
  import { spawn } from "child_process";
1407
- import { randomUUID } from "crypto";
1493
+ import { randomUUID as randomUUID2 } from "crypto";
1408
1494
  import { existsSync as existsSync4, unlinkSync, readFileSync as readFileSync2, openSync, closeSync, statSync } from "fs";
1409
1495
  import path5 from "path";
1410
1496
  import { fileURLToPath } from "url";
@@ -1596,7 +1682,7 @@ function sendRequest(texts, priority) {
1596
1682
  resolve({ error: "Not connected" });
1597
1683
  return;
1598
1684
  }
1599
- const id = randomUUID();
1685
+ const id = randomUUID2();
1600
1686
  const timer = setTimeout(() => {
1601
1687
  _pending.delete(id);
1602
1688
  resolve({ error: "Request timeout" });
@@ -1614,7 +1700,7 @@ function sendRequest(texts, priority) {
1614
1700
  async function pingDaemon() {
1615
1701
  if (!_socket || !_connected) return null;
1616
1702
  return new Promise((resolve) => {
1617
- const id = randomUUID();
1703
+ const id = randomUUID2();
1618
1704
  const timer = setTimeout(() => {
1619
1705
  _pending.delete(id);
1620
1706
  resolve(null);
@@ -1837,7 +1923,7 @@ var init_employees = __esm({
1837
1923
 
1838
1924
  // src/lib/license.ts
1839
1925
  import { readFileSync as readFileSync4, writeFileSync, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
1840
- import { randomUUID as randomUUID2 } from "crypto";
1926
+ import { randomUUID as randomUUID3 } from "crypto";
1841
1927
  import path7 from "path";
1842
1928
  import { jwtVerify, importSPKI } from "jose";
1843
1929
  async function fetchRetry(url, init) {
@@ -1864,7 +1950,7 @@ function loadDeviceId() {
1864
1950
  }
1865
1951
  } catch {
1866
1952
  }
1867
- const id = randomUUID2();
1953
+ const id = randomUUID3();
1868
1954
  mkdirSync2(EXE_AI_DIR, { recursive: true });
1869
1955
  writeFileSync(DEVICE_ID_PATH, id, "utf8");
1870
1956
  return id;
@@ -2234,6 +2320,57 @@ async function getMasterKey() {
2234
2320
 
2235
2321
  // src/lib/store.ts
2236
2322
  init_config();
2323
+
2324
+ // src/lib/state-bus.ts
2325
+ var StateBus = class {
2326
+ handlers = /* @__PURE__ */ new Map();
2327
+ globalHandlers = /* @__PURE__ */ new Set();
2328
+ /** Emit an event to all subscribers */
2329
+ emit(event) {
2330
+ const typeHandlers = this.handlers.get(event.type);
2331
+ if (typeHandlers) {
2332
+ for (const handler of typeHandlers) {
2333
+ try {
2334
+ handler(event);
2335
+ } catch {
2336
+ }
2337
+ }
2338
+ }
2339
+ for (const handler of this.globalHandlers) {
2340
+ try {
2341
+ handler(event);
2342
+ } catch {
2343
+ }
2344
+ }
2345
+ }
2346
+ /** Subscribe to a specific event type */
2347
+ on(type, handler) {
2348
+ if (!this.handlers.has(type)) {
2349
+ this.handlers.set(type, /* @__PURE__ */ new Set());
2350
+ }
2351
+ this.handlers.get(type).add(handler);
2352
+ }
2353
+ /** Subscribe to ALL events */
2354
+ onAny(handler) {
2355
+ this.globalHandlers.add(handler);
2356
+ }
2357
+ /** Unsubscribe from a specific event type */
2358
+ off(type, handler) {
2359
+ this.handlers.get(type)?.delete(handler);
2360
+ }
2361
+ /** Unsubscribe from ALL events */
2362
+ offAny(handler) {
2363
+ this.globalHandlers.delete(handler);
2364
+ }
2365
+ /** Remove all listeners */
2366
+ clear() {
2367
+ this.handlers.clear();
2368
+ this.globalHandlers.clear();
2369
+ }
2370
+ };
2371
+ var orgBus = new StateBus();
2372
+
2373
+ // src/lib/store.ts
2237
2374
  var INIT_MAX_RETRIES = 3;
2238
2375
  var INIT_RETRY_DELAY_MS = 1e3;
2239
2376
  function isBusyError2(err) {
@@ -2304,6 +2441,11 @@ async function initStore(options) {
2304
2441
  "version-query"
2305
2442
  );
2306
2443
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
2444
+ try {
2445
+ const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
2446
+ await loadGlobalProcedures2();
2447
+ } catch {
2448
+ }
2307
2449
  }
2308
2450
  function classifyTier(record) {
2309
2451
  if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
@@ -2345,6 +2487,12 @@ async function writeMemory(record) {
2345
2487
  supersedes_id: record.supersedes_id ?? null
2346
2488
  };
2347
2489
  _pendingRecords.push(dbRow);
2490
+ orgBus.emit({
2491
+ type: "memory_stored",
2492
+ agentId: record.agent_id,
2493
+ project: record.project_name,
2494
+ timestamp: record.timestamp
2495
+ });
2348
2496
  const MAX_PENDING = 1e3;
2349
2497
  if (_pendingRecords.length > MAX_PENDING) {
2350
2498
  const dropped = _pendingRecords.length - MAX_PENDING;
@@ -513,6 +513,13 @@ async function ensureSchema() {
513
513
  });
514
514
  } catch {
515
515
  }
516
+ try {
517
+ await client.execute({
518
+ sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
519
+ args: []
520
+ });
521
+ } catch {
522
+ }
516
523
  try {
517
524
  await client.execute({
518
525
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -959,6 +966,18 @@ async function ensureSchema() {
959
966
  CREATE INDEX IF NOT EXISTS idx_session_kills_agent
960
967
  ON session_kills(agent_id);
961
968
  `);
969
+ await client.execute(`
970
+ CREATE TABLE IF NOT EXISTS global_procedures (
971
+ id TEXT PRIMARY KEY,
972
+ title TEXT NOT NULL,
973
+ content TEXT NOT NULL,
974
+ priority TEXT NOT NULL DEFAULT 'p0',
975
+ domain TEXT,
976
+ active INTEGER NOT NULL DEFAULT 1,
977
+ created_at TEXT NOT NULL,
978
+ updated_at TEXT NOT NULL
979
+ )
980
+ `);
962
981
  await client.executeMultiple(`
963
982
  CREATE TABLE IF NOT EXISTS conversations (
964
983
  id TEXT PRIMARY KEY,
@@ -1166,6 +1185,61 @@ var init_keychain = __esm({
1166
1185
  }
1167
1186
  });
1168
1187
 
1188
+ // src/lib/state-bus.ts
1189
+ var StateBus, orgBus;
1190
+ var init_state_bus = __esm({
1191
+ "src/lib/state-bus.ts"() {
1192
+ "use strict";
1193
+ StateBus = class {
1194
+ handlers = /* @__PURE__ */ new Map();
1195
+ globalHandlers = /* @__PURE__ */ new Set();
1196
+ /** Emit an event to all subscribers */
1197
+ emit(event) {
1198
+ const typeHandlers = this.handlers.get(event.type);
1199
+ if (typeHandlers) {
1200
+ for (const handler of typeHandlers) {
1201
+ try {
1202
+ handler(event);
1203
+ } catch {
1204
+ }
1205
+ }
1206
+ }
1207
+ for (const handler of this.globalHandlers) {
1208
+ try {
1209
+ handler(event);
1210
+ } catch {
1211
+ }
1212
+ }
1213
+ }
1214
+ /** Subscribe to a specific event type */
1215
+ on(type, handler) {
1216
+ if (!this.handlers.has(type)) {
1217
+ this.handlers.set(type, /* @__PURE__ */ new Set());
1218
+ }
1219
+ this.handlers.get(type).add(handler);
1220
+ }
1221
+ /** Subscribe to ALL events */
1222
+ onAny(handler) {
1223
+ this.globalHandlers.add(handler);
1224
+ }
1225
+ /** Unsubscribe from a specific event type */
1226
+ off(type, handler) {
1227
+ this.handlers.get(type)?.delete(handler);
1228
+ }
1229
+ /** Unsubscribe from ALL events */
1230
+ offAny(handler) {
1231
+ this.globalHandlers.delete(handler);
1232
+ }
1233
+ /** Remove all listeners */
1234
+ clear() {
1235
+ this.handlers.clear();
1236
+ this.globalHandlers.clear();
1237
+ }
1238
+ };
1239
+ orgBus = new StateBus();
1240
+ }
1241
+ });
1242
+
1169
1243
  // src/lib/shard-manager.ts
1170
1244
  var shard_manager_exports = {};
1171
1245
  __export(shard_manager_exports, {
@@ -1407,6 +1481,71 @@ var init_shard_manager = __esm({
1407
1481
  }
1408
1482
  });
1409
1483
 
1484
+ // src/lib/global-procedures.ts
1485
+ var global_procedures_exports = {};
1486
+ __export(global_procedures_exports, {
1487
+ deactivateGlobalProcedure: () => deactivateGlobalProcedure,
1488
+ getGlobalProceduresBlock: () => getGlobalProceduresBlock,
1489
+ loadGlobalProcedures: () => loadGlobalProcedures,
1490
+ storeGlobalProcedure: () => storeGlobalProcedure
1491
+ });
1492
+ import { randomUUID } from "crypto";
1493
+ async function loadGlobalProcedures() {
1494
+ const client = getClient();
1495
+ const result = await client.execute({
1496
+ sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
1497
+ args: []
1498
+ });
1499
+ const procedures = result.rows;
1500
+ if (procedures.length > 0) {
1501
+ _cache = procedures.map((p) => `### ${p.title}
1502
+ ${p.content}`).join("\n\n");
1503
+ } else {
1504
+ _cache = "";
1505
+ }
1506
+ _cacheLoaded = true;
1507
+ return procedures;
1508
+ }
1509
+ function getGlobalProceduresBlock() {
1510
+ if (!_cacheLoaded) return "";
1511
+ if (!_cache) return "";
1512
+ return `## Organization-Wide Procedures (MANDATORY \u2014 supersedes all other rules)
1513
+
1514
+ ${_cache}
1515
+ `;
1516
+ }
1517
+ async function storeGlobalProcedure(input2) {
1518
+ const id = randomUUID();
1519
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1520
+ const client = getClient();
1521
+ await client.execute({
1522
+ sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
1523
+ VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
1524
+ args: [id, input2.title, input2.content, input2.priority ?? "p0", input2.domain ?? null, now, now]
1525
+ });
1526
+ await loadGlobalProcedures();
1527
+ return id;
1528
+ }
1529
+ async function deactivateGlobalProcedure(id) {
1530
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1531
+ const client = getClient();
1532
+ const result = await client.execute({
1533
+ sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
1534
+ args: [now, id]
1535
+ });
1536
+ await loadGlobalProcedures();
1537
+ return result.rowsAffected > 0;
1538
+ }
1539
+ var _cache, _cacheLoaded;
1540
+ var init_global_procedures = __esm({
1541
+ "src/lib/global-procedures.ts"() {
1542
+ "use strict";
1543
+ init_database();
1544
+ _cache = "";
1545
+ _cacheLoaded = false;
1546
+ }
1547
+ });
1548
+
1410
1549
  // src/lib/store.ts
1411
1550
  var store_exports = {};
1412
1551
  __export(store_exports, {
@@ -1486,6 +1625,11 @@ async function initStore(options) {
1486
1625
  "version-query"
1487
1626
  );
1488
1627
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
1628
+ try {
1629
+ const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
1630
+ await loadGlobalProcedures2();
1631
+ } catch {
1632
+ }
1489
1633
  }
1490
1634
  function classifyTier(record) {
1491
1635
  if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
@@ -1527,6 +1671,12 @@ async function writeMemory(record) {
1527
1671
  supersedes_id: record.supersedes_id ?? null
1528
1672
  };
1529
1673
  _pendingRecords.push(dbRow);
1674
+ orgBus.emit({
1675
+ type: "memory_stored",
1676
+ agentId: record.agent_id,
1677
+ project: record.project_name,
1678
+ timestamp: record.timestamp
1679
+ });
1530
1680
  const MAX_PENDING = 1e3;
1531
1681
  if (_pendingRecords.length > MAX_PENDING) {
1532
1682
  const dropped = _pendingRecords.length - MAX_PENDING;
@@ -1872,6 +2022,7 @@ var init_store = __esm({
1872
2022
  init_database();
1873
2023
  init_keychain();
1874
2024
  init_config();
2025
+ init_state_bus();
1875
2026
  INIT_MAX_RETRIES = 3;
1876
2027
  INIT_RETRY_DELAY_MS = 1e3;
1877
2028
  _pendingRecords = [];
@@ -2241,7 +2392,7 @@ process.stdin.on("end", async () => {
2241
2392
  await initStore2();
2242
2393
  const { writeMemory: writeMemory2, flushBatch: flushBatch2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2243
2394
  const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
2244
- const { randomUUID } = await import("crypto");
2395
+ const { randomUUID: randomUUID2 } = await import("crypto");
2245
2396
  const client = getClient2();
2246
2397
  const orphanResult = await client.execute({
2247
2398
  sql: "SELECT title, status FROM tasks WHERE assigned_to = ? AND status IN ('open', 'in_progress')",
@@ -2250,7 +2401,7 @@ process.stdin.on("end", async () => {
2250
2401
  const orphanInfo = orphanResult.rows.length > 0 ? `
2251
2402
  Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title)}" (${String(r.status)})`).join(", ")}` : "";
2252
2403
  await writeMemory2({
2253
- id: randomUUID(),
2404
+ id: randomUUID2(),
2254
2405
  agent_id: agent.agentId,
2255
2406
  agent_role: agent.agentRole,
2256
2407
  session_id: data.session_id,
@@ -13,6 +13,7 @@ var config_exports = {};
13
13
  __export(config_exports, {
14
14
  CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
15
15
  CONFIG_PATH: () => CONFIG_PATH,
16
+ COO_AGENT_NAME: () => COO_AGENT_NAME,
16
17
  CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
17
18
  DB_PATH: () => DB_PATH,
18
19
  EXE_AI_DIR: () => EXE_AI_DIR,
@@ -168,7 +169,7 @@ async function loadConfigFrom(configPath) {
168
169
  return { ...DEFAULT_CONFIG };
169
170
  }
170
171
  }
171
- var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
172
+ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, COO_AGENT_NAME, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
172
173
  var init_config = __esm({
173
174
  "src/lib/config.ts"() {
174
175
  "use strict";
@@ -176,6 +177,7 @@ var init_config = __esm({
176
177
  DB_PATH = path.join(EXE_AI_DIR, "memories.db");
177
178
  MODELS_DIR = path.join(EXE_AI_DIR, "models");
178
179
  CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
180
+ COO_AGENT_NAME = "exe";
179
181
  LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
180
182
  CURRENT_CONFIG_VERSION = 1;
181
183
  DEFAULT_CONFIG = {
@@ -556,6 +558,13 @@ async function ensureSchema() {
556
558
  });
557
559
  } catch {
558
560
  }
561
+ try {
562
+ await client.execute({
563
+ sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
564
+ args: []
565
+ });
566
+ } catch {
567
+ }
559
568
  try {
560
569
  await client.execute({
561
570
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -1002,6 +1011,18 @@ async function ensureSchema() {
1002
1011
  CREATE INDEX IF NOT EXISTS idx_session_kills_agent
1003
1012
  ON session_kills(agent_id);
1004
1013
  `);
1014
+ await client.execute(`
1015
+ CREATE TABLE IF NOT EXISTS global_procedures (
1016
+ id TEXT PRIMARY KEY,
1017
+ title TEXT NOT NULL,
1018
+ content TEXT NOT NULL,
1019
+ priority TEXT NOT NULL DEFAULT 'p0',
1020
+ domain TEXT,
1021
+ active INTEGER NOT NULL DEFAULT 1,
1022
+ created_at TEXT NOT NULL,
1023
+ updated_at TEXT NOT NULL
1024
+ )
1025
+ `);
1005
1026
  await client.executeMultiple(`
1006
1027
  CREATE TABLE IF NOT EXISTS conversations (
1007
1028
  id TEXT PRIMARY KEY,
@@ -1209,6 +1230,61 @@ var init_keychain = __esm({
1209
1230
  }
1210
1231
  });
1211
1232
 
1233
+ // src/lib/state-bus.ts
1234
+ var StateBus, orgBus;
1235
+ var init_state_bus = __esm({
1236
+ "src/lib/state-bus.ts"() {
1237
+ "use strict";
1238
+ StateBus = class {
1239
+ handlers = /* @__PURE__ */ new Map();
1240
+ globalHandlers = /* @__PURE__ */ new Set();
1241
+ /** Emit an event to all subscribers */
1242
+ emit(event) {
1243
+ const typeHandlers = this.handlers.get(event.type);
1244
+ if (typeHandlers) {
1245
+ for (const handler of typeHandlers) {
1246
+ try {
1247
+ handler(event);
1248
+ } catch {
1249
+ }
1250
+ }
1251
+ }
1252
+ for (const handler of this.globalHandlers) {
1253
+ try {
1254
+ handler(event);
1255
+ } catch {
1256
+ }
1257
+ }
1258
+ }
1259
+ /** Subscribe to a specific event type */
1260
+ on(type, handler) {
1261
+ if (!this.handlers.has(type)) {
1262
+ this.handlers.set(type, /* @__PURE__ */ new Set());
1263
+ }
1264
+ this.handlers.get(type).add(handler);
1265
+ }
1266
+ /** Subscribe to ALL events */
1267
+ onAny(handler) {
1268
+ this.globalHandlers.add(handler);
1269
+ }
1270
+ /** Unsubscribe from a specific event type */
1271
+ off(type, handler) {
1272
+ this.handlers.get(type)?.delete(handler);
1273
+ }
1274
+ /** Unsubscribe from ALL events */
1275
+ offAny(handler) {
1276
+ this.globalHandlers.delete(handler);
1277
+ }
1278
+ /** Remove all listeners */
1279
+ clear() {
1280
+ this.handlers.clear();
1281
+ this.globalHandlers.clear();
1282
+ }
1283
+ };
1284
+ orgBus = new StateBus();
1285
+ }
1286
+ });
1287
+
1212
1288
  // src/lib/shard-manager.ts
1213
1289
  var shard_manager_exports = {};
1214
1290
  __export(shard_manager_exports, {
@@ -1450,6 +1526,71 @@ var init_shard_manager = __esm({
1450
1526
  }
1451
1527
  });
1452
1528
 
1529
+ // src/lib/global-procedures.ts
1530
+ var global_procedures_exports = {};
1531
+ __export(global_procedures_exports, {
1532
+ deactivateGlobalProcedure: () => deactivateGlobalProcedure,
1533
+ getGlobalProceduresBlock: () => getGlobalProceduresBlock,
1534
+ loadGlobalProcedures: () => loadGlobalProcedures,
1535
+ storeGlobalProcedure: () => storeGlobalProcedure
1536
+ });
1537
+ import { randomUUID } from "crypto";
1538
+ async function loadGlobalProcedures() {
1539
+ const client = getClient();
1540
+ const result = await client.execute({
1541
+ sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
1542
+ args: []
1543
+ });
1544
+ const procedures = result.rows;
1545
+ if (procedures.length > 0) {
1546
+ _cache = procedures.map((p) => `### ${p.title}
1547
+ ${p.content}`).join("\n\n");
1548
+ } else {
1549
+ _cache = "";
1550
+ }
1551
+ _cacheLoaded = true;
1552
+ return procedures;
1553
+ }
1554
+ function getGlobalProceduresBlock() {
1555
+ if (!_cacheLoaded) return "";
1556
+ if (!_cache) return "";
1557
+ return `## Organization-Wide Procedures (MANDATORY \u2014 supersedes all other rules)
1558
+
1559
+ ${_cache}
1560
+ `;
1561
+ }
1562
+ async function storeGlobalProcedure(input2) {
1563
+ const id = randomUUID();
1564
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1565
+ const client = getClient();
1566
+ await client.execute({
1567
+ sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
1568
+ VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
1569
+ args: [id, input2.title, input2.content, input2.priority ?? "p0", input2.domain ?? null, now, now]
1570
+ });
1571
+ await loadGlobalProcedures();
1572
+ return id;
1573
+ }
1574
+ async function deactivateGlobalProcedure(id) {
1575
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1576
+ const client = getClient();
1577
+ const result = await client.execute({
1578
+ sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
1579
+ args: [now, id]
1580
+ });
1581
+ await loadGlobalProcedures();
1582
+ return result.rowsAffected > 0;
1583
+ }
1584
+ var _cache, _cacheLoaded;
1585
+ var init_global_procedures = __esm({
1586
+ "src/lib/global-procedures.ts"() {
1587
+ "use strict";
1588
+ init_database();
1589
+ _cache = "";
1590
+ _cacheLoaded = false;
1591
+ }
1592
+ });
1593
+
1453
1594
  // src/lib/store.ts
1454
1595
  var store_exports = {};
1455
1596
  __export(store_exports, {
@@ -1529,6 +1670,11 @@ async function initStore(options) {
1529
1670
  "version-query"
1530
1671
  );
1531
1672
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
1673
+ try {
1674
+ const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
1675
+ await loadGlobalProcedures2();
1676
+ } catch {
1677
+ }
1532
1678
  }
1533
1679
  function classifyTier(record) {
1534
1680
  if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
@@ -1570,6 +1716,12 @@ async function writeMemory(record) {
1570
1716
  supersedes_id: record.supersedes_id ?? null
1571
1717
  };
1572
1718
  _pendingRecords.push(dbRow);
1719
+ orgBus.emit({
1720
+ type: "memory_stored",
1721
+ agentId: record.agent_id,
1722
+ project: record.project_name,
1723
+ timestamp: record.timestamp
1724
+ });
1573
1725
  const MAX_PENDING = 1e3;
1574
1726
  if (_pendingRecords.length > MAX_PENDING) {
1575
1727
  const dropped = _pendingRecords.length - MAX_PENDING;
@@ -1915,6 +2067,7 @@ var init_store = __esm({
1915
2067
  init_database();
1916
2068
  init_keychain();
1917
2069
  init_config();
2070
+ init_state_bus();
1918
2071
  INIT_MAX_RETRIES = 3;
1919
2072
  INIT_RETRY_DELAY_MS = 1e3;
1920
2073
  _pendingRecords = [];
@@ -2018,7 +2171,7 @@ var init_self_query_router = __esm({
2018
2171
  // src/lib/exe-daemon-client.ts
2019
2172
  import net from "net";
2020
2173
  import { spawn } from "child_process";
2021
- import { randomUUID } from "crypto";
2174
+ import { randomUUID as randomUUID2 } from "crypto";
2022
2175
  import { existsSync as existsSync4, unlinkSync, readFileSync as readFileSync2, openSync, closeSync, statSync } from "fs";
2023
2176
  import path4 from "path";
2024
2177
  import { fileURLToPath } from "url";
@@ -2210,7 +2363,7 @@ function sendRequest(texts, priority) {
2210
2363
  resolve({ error: "Not connected" });
2211
2364
  return;
2212
2365
  }
2213
- const id = randomUUID();
2366
+ const id = randomUUID2();
2214
2367
  const timer = setTimeout(() => {
2215
2368
  _pending.delete(id);
2216
2369
  resolve({ error: "Request timeout" });
@@ -2228,7 +2381,7 @@ function sendRequest(texts, priority) {
2228
2381
  async function pingDaemon() {
2229
2382
  if (!_socket || !_connected) return null;
2230
2383
  return new Promise((resolve) => {
2231
- const id = randomUUID();
2384
+ const id = randomUUID2();
2232
2385
  const timer = setTimeout(() => {
2233
2386
  _pending.delete(id);
2234
2387
  resolve(null);