@askexenow/exe-os 0.8.41 → 0.8.43

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 (76) 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 +1345 -660
  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 +2518 -1798
  9. package/dist/bin/exe-call.js +39 -1
  10. package/dist/bin/exe-cloud.js +15 -1
  11. package/dist/bin/exe-dispatch.js +39 -2
  12. package/dist/bin/exe-doctor.js +790 -633
  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 +2500 -1877
  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 +28 -2
  20. package/dist/bin/exe-new-employee.js +25 -3
  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 +147 -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 +154 -3
  27. package/dist/bin/exe-session-cleanup.js +2466 -413
  28. package/dist/bin/exe-status.js +474 -317
  29. package/dist/bin/exe-team.js +474 -317
  30. package/dist/bin/git-sweep.js +2690 -150
  31. package/dist/bin/graph-backfill.js +794 -637
  32. package/dist/bin/graph-export.js +798 -641
  33. package/dist/bin/scan-tasks.js +2951 -44
  34. package/dist/bin/setup.js +62 -26
  35. package/dist/bin/shard-migrate.js +792 -637
  36. package/dist/bin/wiki-sync.js +794 -637
  37. package/dist/gateway/index.js +2504 -1895
  38. package/dist/hooks/bug-report-worker.js +2118 -576
  39. package/dist/hooks/commit-complete.js +2689 -149
  40. package/dist/hooks/error-recall.js +154 -3
  41. package/dist/hooks/ingest-worker.js +1439 -815
  42. package/dist/hooks/instructions-loaded.js +151 -0
  43. package/dist/hooks/notification.js +153 -2
  44. package/dist/hooks/post-compact.js +164 -0
  45. package/dist/hooks/pre-compact.js +3073 -101
  46. package/dist/hooks/pre-tool-use.js +151 -0
  47. package/dist/hooks/prompt-ingest-worker.js +1714 -1537
  48. package/dist/hooks/prompt-submit.js +2658 -1113
  49. package/dist/hooks/response-ingest-worker.js +170 -6
  50. package/dist/hooks/session-end.js +153 -2
  51. package/dist/hooks/session-start.js +154 -3
  52. package/dist/hooks/stop.js +151 -0
  53. package/dist/hooks/subagent-stop.js +151 -0
  54. package/dist/hooks/summary-worker.js +179 -7
  55. package/dist/index.js +278 -100
  56. package/dist/lib/cloud-sync.js +28 -2
  57. package/dist/lib/consolidation.js +69 -2
  58. package/dist/lib/database.js +19 -0
  59. package/dist/lib/device-registry.js +19 -0
  60. package/dist/lib/employee-templates.js +20 -1
  61. package/dist/lib/exe-daemon.js +236 -16
  62. package/dist/lib/hybrid-search.js +154 -3
  63. package/dist/lib/license.js +15 -1
  64. package/dist/lib/messaging.js +39 -2
  65. package/dist/lib/schedules.js +792 -637
  66. package/dist/lib/store.js +796 -636
  67. package/dist/lib/tasks.js +1614 -1091
  68. package/dist/lib/tmux-routing.js +149 -9
  69. package/dist/mcp/server.js +1825 -1138
  70. package/dist/mcp/tools/create-task.js +2280 -828
  71. package/dist/mcp/tools/list-tasks.js +2788 -159
  72. package/dist/mcp/tools/send-message.js +39 -2
  73. package/dist/mcp/tools/update-task.js +64 -0
  74. package/dist/runtime/index.js +235 -67
  75. package/dist/tui/App.js +1452 -644
  76. 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,
@@ -1403,10 +1422,75 @@ var init_shard_manager = __esm({
1403
1422
  }
1404
1423
  });
1405
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
+
1406
1490
  // src/lib/exe-daemon-client.ts
1407
1491
  import net from "net";
1408
1492
  import { spawn } from "child_process";
1409
- import { randomUUID } from "crypto";
1493
+ import { randomUUID as randomUUID2 } from "crypto";
1410
1494
  import { existsSync as existsSync4, unlinkSync, readFileSync as readFileSync2, openSync, closeSync, statSync } from "fs";
1411
1495
  import path5 from "path";
1412
1496
  import { fileURLToPath } from "url";
@@ -1598,7 +1682,7 @@ function sendRequest(texts, priority) {
1598
1682
  resolve({ error: "Not connected" });
1599
1683
  return;
1600
1684
  }
1601
- const id = randomUUID();
1685
+ const id = randomUUID2();
1602
1686
  const timer = setTimeout(() => {
1603
1687
  _pending.delete(id);
1604
1688
  resolve({ error: "Request timeout" });
@@ -1616,7 +1700,7 @@ function sendRequest(texts, priority) {
1616
1700
  async function pingDaemon() {
1617
1701
  if (!_socket || !_connected) return null;
1618
1702
  return new Promise((resolve) => {
1619
- const id = randomUUID();
1703
+ const id = randomUUID2();
1620
1704
  const timer = setTimeout(() => {
1621
1705
  _pending.delete(id);
1622
1706
  resolve(null);
@@ -1839,7 +1923,7 @@ var init_employees = __esm({
1839
1923
 
1840
1924
  // src/lib/license.ts
1841
1925
  import { readFileSync as readFileSync4, writeFileSync, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
1842
- import { randomUUID as randomUUID2 } from "crypto";
1926
+ import { randomUUID as randomUUID3 } from "crypto";
1843
1927
  import path7 from "path";
1844
1928
  import { jwtVerify, importSPKI } from "jose";
1845
1929
  async function fetchRetry(url, init) {
@@ -1866,7 +1950,7 @@ function loadDeviceId() {
1866
1950
  }
1867
1951
  } catch {
1868
1952
  }
1869
- const id = randomUUID2();
1953
+ const id = randomUUID3();
1870
1954
  mkdirSync2(EXE_AI_DIR, { recursive: true });
1871
1955
  writeFileSync(DEVICE_ID_PATH, id, "utf8");
1872
1956
  return id;
@@ -1879,6 +1963,10 @@ function loadLicense() {
1879
1963
  return null;
1880
1964
  }
1881
1965
  }
1966
+ function saveLicense(apiKey) {
1967
+ mkdirSync2(EXE_AI_DIR, { recursive: true });
1968
+ writeFileSync(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
1969
+ }
1882
1970
  async function verifyLicenseJwt(token) {
1883
1971
  try {
1884
1972
  const key = await importSPKI(LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG);
@@ -1968,7 +2056,21 @@ function getCacheAgeMs() {
1968
2056
  }
1969
2057
  }
1970
2058
  async function checkLicense() {
1971
- const key = loadLicense();
2059
+ let key = loadLicense();
2060
+ if (!key) {
2061
+ try {
2062
+ const configPath = path7.join(EXE_AI_DIR, "config.json");
2063
+ if (existsSync6(configPath)) {
2064
+ const raw = JSON.parse(readFileSync4(configPath, "utf8"));
2065
+ const cloud = raw.cloud;
2066
+ if (cloud?.apiKey) {
2067
+ key = cloud.apiKey;
2068
+ saveLicense(key);
2069
+ }
2070
+ }
2071
+ } catch {
2072
+ }
2073
+ }
1972
2074
  if (!key) return FREE_LICENSE;
1973
2075
  const cached = await getCachedLicense();
1974
2076
  if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
@@ -2236,6 +2338,57 @@ async function getMasterKey() {
2236
2338
 
2237
2339
  // src/lib/store.ts
2238
2340
  init_config();
2341
+
2342
+ // src/lib/state-bus.ts
2343
+ var StateBus = class {
2344
+ handlers = /* @__PURE__ */ new Map();
2345
+ globalHandlers = /* @__PURE__ */ new Set();
2346
+ /** Emit an event to all subscribers */
2347
+ emit(event) {
2348
+ const typeHandlers = this.handlers.get(event.type);
2349
+ if (typeHandlers) {
2350
+ for (const handler of typeHandlers) {
2351
+ try {
2352
+ handler(event);
2353
+ } catch {
2354
+ }
2355
+ }
2356
+ }
2357
+ for (const handler of this.globalHandlers) {
2358
+ try {
2359
+ handler(event);
2360
+ } catch {
2361
+ }
2362
+ }
2363
+ }
2364
+ /** Subscribe to a specific event type */
2365
+ on(type, handler) {
2366
+ if (!this.handlers.has(type)) {
2367
+ this.handlers.set(type, /* @__PURE__ */ new Set());
2368
+ }
2369
+ this.handlers.get(type).add(handler);
2370
+ }
2371
+ /** Subscribe to ALL events */
2372
+ onAny(handler) {
2373
+ this.globalHandlers.add(handler);
2374
+ }
2375
+ /** Unsubscribe from a specific event type */
2376
+ off(type, handler) {
2377
+ this.handlers.get(type)?.delete(handler);
2378
+ }
2379
+ /** Unsubscribe from ALL events */
2380
+ offAny(handler) {
2381
+ this.globalHandlers.delete(handler);
2382
+ }
2383
+ /** Remove all listeners */
2384
+ clear() {
2385
+ this.handlers.clear();
2386
+ this.globalHandlers.clear();
2387
+ }
2388
+ };
2389
+ var orgBus = new StateBus();
2390
+
2391
+ // src/lib/store.ts
2239
2392
  var INIT_MAX_RETRIES = 3;
2240
2393
  var INIT_RETRY_DELAY_MS = 1e3;
2241
2394
  function isBusyError2(err) {
@@ -2306,6 +2459,11 @@ async function initStore(options) {
2306
2459
  "version-query"
2307
2460
  );
2308
2461
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
2462
+ try {
2463
+ const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
2464
+ await loadGlobalProcedures2();
2465
+ } catch {
2466
+ }
2309
2467
  }
2310
2468
  function classifyTier(record) {
2311
2469
  if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
@@ -2347,6 +2505,12 @@ async function writeMemory(record) {
2347
2505
  supersedes_id: record.supersedes_id ?? null
2348
2506
  };
2349
2507
  _pendingRecords.push(dbRow);
2508
+ orgBus.emit({
2509
+ type: "memory_stored",
2510
+ agentId: record.agent_id,
2511
+ project: record.project_name,
2512
+ timestamp: record.timestamp
2513
+ });
2350
2514
  const MAX_PENDING = 1e3;
2351
2515
  if (_pendingRecords.length > MAX_PENDING) {
2352
2516
  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,
@@ -558,6 +558,13 @@ async function ensureSchema() {
558
558
  });
559
559
  } catch {
560
560
  }
561
+ try {
562
+ await client.execute({
563
+ sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
564
+ args: []
565
+ });
566
+ } catch {
567
+ }
561
568
  try {
562
569
  await client.execute({
563
570
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -1004,6 +1011,18 @@ async function ensureSchema() {
1004
1011
  CREATE INDEX IF NOT EXISTS idx_session_kills_agent
1005
1012
  ON session_kills(agent_id);
1006
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
+ `);
1007
1026
  await client.executeMultiple(`
1008
1027
  CREATE TABLE IF NOT EXISTS conversations (
1009
1028
  id TEXT PRIMARY KEY,
@@ -1211,6 +1230,61 @@ var init_keychain = __esm({
1211
1230
  }
1212
1231
  });
1213
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
+
1214
1288
  // src/lib/shard-manager.ts
1215
1289
  var shard_manager_exports = {};
1216
1290
  __export(shard_manager_exports, {
@@ -1452,6 +1526,71 @@ var init_shard_manager = __esm({
1452
1526
  }
1453
1527
  });
1454
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
+
1455
1594
  // src/lib/store.ts
1456
1595
  var store_exports = {};
1457
1596
  __export(store_exports, {
@@ -1531,6 +1670,11 @@ async function initStore(options) {
1531
1670
  "version-query"
1532
1671
  );
1533
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
+ }
1534
1678
  }
1535
1679
  function classifyTier(record) {
1536
1680
  if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
@@ -1572,6 +1716,12 @@ async function writeMemory(record) {
1572
1716
  supersedes_id: record.supersedes_id ?? null
1573
1717
  };
1574
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
+ });
1575
1725
  const MAX_PENDING = 1e3;
1576
1726
  if (_pendingRecords.length > MAX_PENDING) {
1577
1727
  const dropped = _pendingRecords.length - MAX_PENDING;
@@ -1917,6 +2067,7 @@ var init_store = __esm({
1917
2067
  init_database();
1918
2068
  init_keychain();
1919
2069
  init_config();
2070
+ init_state_bus();
1920
2071
  INIT_MAX_RETRIES = 3;
1921
2072
  INIT_RETRY_DELAY_MS = 1e3;
1922
2073
  _pendingRecords = [];
@@ -2020,7 +2171,7 @@ var init_self_query_router = __esm({
2020
2171
  // src/lib/exe-daemon-client.ts
2021
2172
  import net from "net";
2022
2173
  import { spawn } from "child_process";
2023
- import { randomUUID } from "crypto";
2174
+ import { randomUUID as randomUUID2 } from "crypto";
2024
2175
  import { existsSync as existsSync4, unlinkSync, readFileSync as readFileSync2, openSync, closeSync, statSync } from "fs";
2025
2176
  import path4 from "path";
2026
2177
  import { fileURLToPath } from "url";
@@ -2212,7 +2363,7 @@ function sendRequest(texts, priority) {
2212
2363
  resolve({ error: "Not connected" });
2213
2364
  return;
2214
2365
  }
2215
- const id = randomUUID();
2366
+ const id = randomUUID2();
2216
2367
  const timer = setTimeout(() => {
2217
2368
  _pending.delete(id);
2218
2369
  resolve({ error: "Request timeout" });
@@ -2230,7 +2381,7 @@ function sendRequest(texts, priority) {
2230
2381
  async function pingDaemon() {
2231
2382
  if (!_socket || !_connected) return null;
2232
2383
  return new Promise((resolve) => {
2233
- const id = randomUUID();
2384
+ const id = randomUUID2();
2234
2385
  const timer = setTimeout(() => {
2235
2386
  _pending.delete(id);
2236
2387
  resolve(null);