@askexenow/exe-os 0.8.64 → 0.8.68

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 (55) hide show
  1. package/dist/bin/cleanup-stale-review-tasks.js +8 -7
  2. package/dist/bin/cli.js +215 -120
  3. package/dist/bin/exe-assign.js +11 -10
  4. package/dist/bin/exe-boot.js +83 -78
  5. package/dist/bin/exe-call.js +33 -1
  6. package/dist/bin/exe-cloud.js +3 -2
  7. package/dist/bin/exe-dispatch.js +31 -30
  8. package/dist/bin/exe-gateway.js +33 -32
  9. package/dist/bin/exe-heartbeat.js +21 -20
  10. package/dist/bin/exe-launch-agent.js +48 -16
  11. package/dist/bin/exe-link.js +16 -11
  12. package/dist/bin/exe-new-employee.js +20 -19
  13. package/dist/bin/exe-pending-messages.js +7 -6
  14. package/dist/bin/exe-pending-reviews.js +16 -15
  15. package/dist/bin/exe-rename.js +12 -11
  16. package/dist/bin/exe-review.js +4 -3
  17. package/dist/bin/exe-session-cleanup.js +20 -19
  18. package/dist/bin/exe-settings.js +3 -2
  19. package/dist/bin/exe-start.sh +2 -2
  20. package/dist/bin/exe-status.js +16 -15
  21. package/dist/bin/exe-team.js +4 -3
  22. package/dist/bin/git-sweep.js +31 -30
  23. package/dist/bin/install.js +284 -113
  24. package/dist/bin/scan-tasks.js +33 -32
  25. package/dist/bin/setup.js +114 -30
  26. package/dist/gateway/index.js +32 -31
  27. package/dist/hooks/bug-report-worker.js +58 -26
  28. package/dist/hooks/commit-complete.js +31 -30
  29. package/dist/hooks/ingest-worker.js +58 -57
  30. package/dist/hooks/post-compact.js +10 -9
  31. package/dist/hooks/pre-compact.js +31 -30
  32. package/dist/hooks/pre-tool-use.js +46 -14
  33. package/dist/hooks/prompt-ingest-worker.js +15 -14
  34. package/dist/hooks/prompt-submit.js +15 -14
  35. package/dist/hooks/response-ingest-worker.js +8 -7
  36. package/dist/hooks/session-end.js +14 -13
  37. package/dist/hooks/session-start.js +10 -9
  38. package/dist/hooks/stop.js +10 -9
  39. package/dist/hooks/subagent-stop.js +10 -9
  40. package/dist/hooks/summary-worker.js +41 -36
  41. package/dist/index.js +43 -42
  42. package/dist/lib/cloud-sync.js +16 -11
  43. package/dist/lib/employees.js +33 -1
  44. package/dist/lib/exe-daemon.js +56 -55
  45. package/dist/lib/messaging.js +9 -8
  46. package/dist/lib/tasks.js +27 -26
  47. package/dist/lib/tmux-routing.js +29 -28
  48. package/dist/mcp/server.js +94 -62
  49. package/dist/mcp/tools/create-task.js +60 -28
  50. package/dist/mcp/tools/list-tasks.js +10 -9
  51. package/dist/mcp/tools/send-message.js +11 -10
  52. package/dist/mcp/tools/update-task.js +21 -20
  53. package/dist/runtime/index.js +31 -30
  54. package/dist/tui/App.js +67 -35
  55. package/package.json +1 -1
@@ -1530,9 +1530,10 @@ ${p.content}`).join("\n\n");
1530
1530
  // src/lib/employees.ts
1531
1531
  init_config();
1532
1532
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
1533
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2 } from "fs";
1533
+ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
1534
1534
  import { execSync } from "child_process";
1535
1535
  import path2 from "path";
1536
+ import os2 from "os";
1536
1537
  var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
1537
1538
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
1538
1539
  if (!existsSync2(employeesPath)) {
@@ -1680,7 +1681,7 @@ init_config();
1680
1681
  import net from "net";
1681
1682
  import { spawn } from "child_process";
1682
1683
  import { randomUUID as randomUUID2 } from "crypto";
1683
- import { existsSync as existsSync3, unlinkSync, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
1684
+ import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
1684
1685
  import path3 from "path";
1685
1686
  import { fileURLToPath } from "url";
1686
1687
  var SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path3.join(EXE_AI_DIR, "exed.sock");
@@ -1733,11 +1734,11 @@ function cleanupStaleFiles() {
1733
1734
  } catch {
1734
1735
  }
1735
1736
  try {
1736
- unlinkSync(PID_PATH);
1737
+ unlinkSync2(PID_PATH);
1737
1738
  } catch {
1738
1739
  }
1739
1740
  try {
1740
- unlinkSync(SOCKET_PATH);
1741
+ unlinkSync2(SOCKET_PATH);
1741
1742
  } catch {
1742
1743
  }
1743
1744
  }
@@ -1799,7 +1800,7 @@ function acquireSpawnLock() {
1799
1800
  const stat = statSync(SPAWN_LOCK_PATH);
1800
1801
  if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
1801
1802
  try {
1802
- unlinkSync(SPAWN_LOCK_PATH);
1803
+ unlinkSync2(SPAWN_LOCK_PATH);
1803
1804
  } catch {
1804
1805
  }
1805
1806
  try {
@@ -1816,7 +1817,7 @@ function acquireSpawnLock() {
1816
1817
  }
1817
1818
  function releaseSpawnLock() {
1818
1819
  try {
1819
- unlinkSync(SPAWN_LOCK_PATH);
1820
+ unlinkSync2(SPAWN_LOCK_PATH);
1820
1821
  } catch {
1821
1822
  }
1822
1823
  }
@@ -1947,11 +1948,11 @@ function killAndRespawnDaemon() {
1947
1948
  _connected = false;
1948
1949
  _buffer = "";
1949
1950
  try {
1950
- unlinkSync(PID_PATH);
1951
+ unlinkSync2(PID_PATH);
1951
1952
  } catch {
1952
1953
  }
1953
1954
  try {
1954
- unlinkSync(SOCKET_PATH);
1955
+ unlinkSync2(SOCKET_PATH);
1955
1956
  } catch {
1956
1957
  }
1957
1958
  spawnDaemon();
@@ -2021,11 +2022,11 @@ init_database();
2021
2022
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2022
2023
  import { existsSync as existsSync4 } from "fs";
2023
2024
  import path4 from "path";
2024
- import os2 from "os";
2025
+ import os3 from "os";
2025
2026
  var SERVICE = "exe-mem";
2026
2027
  var ACCOUNT = "master-key";
2027
2028
  function getKeyDir() {
2028
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os2.homedir(), ".exe-os");
2029
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os3.homedir(), ".exe-os");
2029
2030
  }
2030
2031
  function getKeyPath() {
2031
2032
  return path4.join(getKeyDir(), "master.key");
@@ -276,9 +276,10 @@ var init_config = __esm({
276
276
 
277
277
  // src/lib/employees.ts
278
278
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
279
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2 } from "fs";
279
+ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
280
280
  import { execSync } from "child_process";
281
281
  import path2 from "path";
282
+ import os2 from "os";
282
283
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
283
284
  if (!existsSync2(employeesPath)) {
284
285
  return [];
@@ -1471,9 +1472,9 @@ __export(keychain_exports, {
1471
1472
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
1472
1473
  import { existsSync as existsSync3 } from "fs";
1473
1474
  import path3 from "path";
1474
- import os2 from "os";
1475
+ import os3 from "os";
1475
1476
  function getKeyDir() {
1476
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(os2.homedir(), ".exe-os");
1477
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(os3.homedir(), ".exe-os");
1477
1478
  }
1478
1479
  function getKeyPath() {
1479
1480
  return path3.join(getKeyDir(), "master.key");
@@ -1966,10 +1967,10 @@ __export(session_registry_exports, {
1966
1967
  pruneStaleSessions: () => pruneStaleSessions,
1967
1968
  registerSession: () => registerSession
1968
1969
  });
1969
- import { readFileSync as readFileSync3, writeFileSync, mkdirSync as mkdirSync2, existsSync as existsSync5 } from "fs";
1970
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync5 } from "fs";
1970
1971
  import { execSync as execSync2 } from "child_process";
1971
1972
  import path5 from "path";
1972
- import os3 from "os";
1973
+ import os4 from "os";
1973
1974
  function registerSession(entry) {
1974
1975
  const dir = path5.dirname(REGISTRY_PATH);
1975
1976
  if (!existsSync5(dir)) {
@@ -1982,7 +1983,7 @@ function registerSession(entry) {
1982
1983
  } else {
1983
1984
  sessions.push(entry);
1984
1985
  }
1985
- writeFileSync(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
1986
+ writeFileSync2(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
1986
1987
  }
1987
1988
  function listSessions() {
1988
1989
  try {
@@ -2007,7 +2008,7 @@ function pruneStaleSessions() {
2007
2008
  const alive = sessions.filter((s) => liveSet.has(s.windowName));
2008
2009
  const pruned = sessions.length - alive.length;
2009
2010
  if (pruned > 0) {
2010
- writeFileSync(REGISTRY_PATH, JSON.stringify(alive, null, 2));
2011
+ writeFileSync2(REGISTRY_PATH, JSON.stringify(alive, null, 2));
2011
2012
  }
2012
2013
  return pruned;
2013
2014
  }
@@ -2015,7 +2016,7 @@ var REGISTRY_PATH;
2015
2016
  var init_session_registry = __esm({
2016
2017
  "src/lib/session-registry.ts"() {
2017
2018
  "use strict";
2018
- REGISTRY_PATH = path5.join(os3.homedir(), ".exe-os", "session-registry.json");
2019
+ REGISTRY_PATH = path5.join(os4.homedir(), ".exe-os", "session-registry.json");
2019
2020
  }
2020
2021
  });
2021
2022
 
@@ -2235,9 +2236,9 @@ var init_provider_table = __esm({
2235
2236
  });
2236
2237
 
2237
2238
  // src/lib/intercom-queue.ts
2238
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync as renameSync2, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
2239
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
2239
2240
  import path6 from "path";
2240
- import os4 from "os";
2241
+ import os5 from "os";
2241
2242
  function ensureDir() {
2242
2243
  const dir = path6.dirname(QUEUE_PATH);
2243
2244
  if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
@@ -2253,8 +2254,8 @@ function readQueue() {
2253
2254
  function writeQueue(queue) {
2254
2255
  ensureDir();
2255
2256
  const tmp = `${QUEUE_PATH}.tmp`;
2256
- writeFileSync2(tmp, JSON.stringify(queue, null, 2));
2257
- renameSync2(tmp, QUEUE_PATH);
2257
+ writeFileSync3(tmp, JSON.stringify(queue, null, 2));
2258
+ renameSync3(tmp, QUEUE_PATH);
2258
2259
  }
2259
2260
  function queueIntercom(targetSession, reason) {
2260
2261
  const queue = readQueue();
@@ -2277,9 +2278,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
2277
2278
  var init_intercom_queue = __esm({
2278
2279
  "src/lib/intercom-queue.ts"() {
2279
2280
  "use strict";
2280
- QUEUE_PATH = path6.join(os4.homedir(), ".exe-os", "intercom-queue.json");
2281
+ QUEUE_PATH = path6.join(os5.homedir(), ".exe-os", "intercom-queue.json");
2281
2282
  TTL_MS = 60 * 60 * 1e3;
2282
- INTERCOM_LOG = path6.join(os4.homedir(), ".exe-os", "intercom.log");
2283
+ INTERCOM_LOG = path6.join(os5.homedir(), ".exe-os", "intercom.log");
2283
2284
  }
2284
2285
  });
2285
2286
 
@@ -2300,7 +2301,7 @@ __export(license_exports, {
2300
2301
  stopLicenseRevalidation: () => stopLicenseRevalidation,
2301
2302
  validateLicense: () => validateLicense
2302
2303
  });
2303
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
2304
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
2304
2305
  import { randomUUID as randomUUID2 } from "crypto";
2305
2306
  import path7 from "path";
2306
2307
  import { jwtVerify, importSPKI } from "jose";
@@ -2330,7 +2331,7 @@ function loadDeviceId() {
2330
2331
  }
2331
2332
  const id = randomUUID2();
2332
2333
  mkdirSync4(EXE_AI_DIR, { recursive: true });
2333
- writeFileSync3(DEVICE_ID_PATH, id, "utf8");
2334
+ writeFileSync4(DEVICE_ID_PATH, id, "utf8");
2334
2335
  return id;
2335
2336
  }
2336
2337
  function loadLicense() {
@@ -2343,7 +2344,7 @@ function loadLicense() {
2343
2344
  }
2344
2345
  function saveLicense(apiKey) {
2345
2346
  mkdirSync4(EXE_AI_DIR, { recursive: true });
2346
- writeFileSync3(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
2347
+ writeFileSync4(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
2347
2348
  }
2348
2349
  async function verifyLicenseJwt(token) {
2349
2350
  try {
@@ -2414,7 +2415,7 @@ function getRawCachedPlan() {
2414
2415
  }
2415
2416
  function cacheResponse(token) {
2416
2417
  try {
2417
- writeFileSync3(CACHE_PATH, JSON.stringify({ token }), "utf8");
2418
+ writeFileSync4(CACHE_PATH, JSON.stringify({ token }), "utf8");
2418
2419
  } catch {
2419
2420
  }
2420
2421
  }
@@ -2751,11 +2752,11 @@ var init_plan_limits = __esm({
2751
2752
  // src/lib/notifications.ts
2752
2753
  import crypto from "crypto";
2753
2754
  import path9 from "path";
2754
- import os5 from "os";
2755
+ import os6 from "os";
2755
2756
  import {
2756
2757
  readFileSync as readFileSync7,
2757
2758
  readdirSync as readdirSync2,
2758
- unlinkSync,
2759
+ unlinkSync as unlinkSync2,
2759
2760
  existsSync as existsSync9,
2760
2761
  rmdirSync
2761
2762
  } from "fs";
@@ -2869,7 +2870,7 @@ async function markDoneTaskNotificationsAsRead() {
2869
2870
  }
2870
2871
  }
2871
2872
  async function migrateJsonNotifications() {
2872
- const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path9.join(os5.homedir(), ".exe-os");
2873
+ const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path9.join(os6.homedir(), ".exe-os");
2873
2874
  const notifDir = path9.join(base, "notifications");
2874
2875
  if (!existsSync9(notifDir)) return 0;
2875
2876
  let migrated = 0;
@@ -2896,7 +2897,7 @@ async function migrateJsonNotifications() {
2896
2897
  data.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
2897
2898
  ]
2898
2899
  });
2899
- unlinkSync(filePath);
2900
+ unlinkSync2(filePath);
2900
2901
  migrated++;
2901
2902
  } catch {
2902
2903
  }
@@ -3443,7 +3444,7 @@ var init_tasks_crud = __esm({
3443
3444
 
3444
3445
  // src/lib/tasks-review.ts
3445
3446
  import path11 from "path";
3446
- import { existsSync as existsSync11, readdirSync as readdirSync3, unlinkSync as unlinkSync2 } from "fs";
3447
+ import { existsSync as existsSync11, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
3447
3448
  async function countPendingReviews(sessionScope) {
3448
3449
  const client = getClient();
3449
3450
  if (sessionScope) {
@@ -3628,7 +3629,7 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
3628
3629
  if (existsSync11(cacheDir)) {
3629
3630
  for (const f of readdirSync3(cacheDir)) {
3630
3631
  if (f.startsWith("review-notified-")) {
3631
- unlinkSync2(path11.join(cacheDir, f));
3632
+ unlinkSync3(path11.join(cacheDir, f));
3632
3633
  }
3633
3634
  }
3634
3635
  }
@@ -4243,7 +4244,7 @@ __export(tasks_exports, {
4243
4244
  writeCheckpoint: () => writeCheckpoint
4244
4245
  });
4245
4246
  import path14 from "path";
4246
- import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, unlinkSync as unlinkSync3 } from "fs";
4247
+ import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4 } from "fs";
4247
4248
  async function createTask(input) {
4248
4249
  const result = await createTaskCore(input);
4249
4250
  if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
@@ -4266,10 +4267,10 @@ async function updateTask(input) {
4266
4267
  const cachePath = path14.join(cacheDir, `current-task-${agent}.json`);
4267
4268
  if (input.status === "in_progress") {
4268
4269
  mkdirSync5(cacheDir, { recursive: true });
4269
- writeFileSync4(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
4270
+ writeFileSync5(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
4270
4271
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
4271
4272
  try {
4272
- unlinkSync3(cachePath);
4273
+ unlinkSync4(cachePath);
4273
4274
  } catch {
4274
4275
  }
4275
4276
  }
@@ -4711,11 +4712,11 @@ __export(tmux_routing_exports, {
4711
4712
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
4712
4713
  });
4713
4714
  import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
4714
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync12, appendFileSync } from "fs";
4715
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync12, appendFileSync } from "fs";
4715
4716
  import path15 from "path";
4716
- import os6 from "os";
4717
+ import os7 from "os";
4717
4718
  import { fileURLToPath } from "url";
4718
- import { unlinkSync as unlinkSync4 } from "fs";
4719
+ import { unlinkSync as unlinkSync5 } from "fs";
4719
4720
  function spawnLockPath(sessionName) {
4720
4721
  return path15.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
4721
4722
  }
@@ -4742,12 +4743,12 @@ function acquireSpawnLock(sessionName) {
4742
4743
  } catch {
4743
4744
  }
4744
4745
  }
4745
- writeFileSync5(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
4746
+ writeFileSync6(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
4746
4747
  return true;
4747
4748
  }
4748
4749
  function releaseSpawnLock(sessionName) {
4749
4750
  try {
4750
- unlinkSync4(spawnLockPath(sessionName));
4751
+ unlinkSync5(spawnLockPath(sessionName));
4751
4752
  } catch {
4752
4753
  }
4753
4754
  }
@@ -4829,7 +4830,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
4829
4830
  }
4830
4831
  const rootExe = extractRootExe(parentExe) ?? parentExe;
4831
4832
  const filePath = path15.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
4832
- writeFileSync5(filePath, JSON.stringify({
4833
+ writeFileSync6(filePath, JSON.stringify({
4833
4834
  parentExe: rootExe,
4834
4835
  dispatchedBy: dispatchedBy || rootExe,
4835
4836
  registeredAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -4916,7 +4917,7 @@ function readDebounceState() {
4916
4917
  function writeDebounceState(state) {
4917
4918
  try {
4918
4919
  if (!existsSync12(SESSION_CACHE)) mkdirSync6(SESSION_CACHE, { recursive: true });
4919
- writeFileSync5(DEBOUNCE_FILE, JSON.stringify(state));
4920
+ writeFileSync6(DEBOUNCE_FILE, JSON.stringify(state));
4920
4921
  } catch {
4921
4922
  }
4922
4923
  }
@@ -5105,7 +5106,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5105
5106
  const transport = getTransport();
5106
5107
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
5107
5108
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
5108
- const logDir = path15.join(os6.homedir(), ".exe-os", "session-logs");
5109
+ const logDir = path15.join(os7.homedir(), ".exe-os", "session-logs");
5109
5110
  const logFile = path15.join(logDir, `${instanceLabel}-${Date.now()}.log`);
5110
5111
  if (!existsSync12(logDir)) {
5111
5112
  mkdirSync6(logDir, { recursive: true });
@@ -5121,7 +5122,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5121
5122
  } catch {
5122
5123
  }
5123
5124
  try {
5124
- const claudeJsonPath = path15.join(os6.homedir(), ".claude.json");
5125
+ const claudeJsonPath = path15.join(os7.homedir(), ".claude.json");
5125
5126
  let claudeJson = {};
5126
5127
  try {
5127
5128
  claudeJson = JSON.parse(readFileSync9(claudeJsonPath, "utf8"));
@@ -5132,11 +5133,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5132
5133
  const trustDir = opts?.cwd ?? projectDir;
5133
5134
  if (!projects[trustDir]) projects[trustDir] = {};
5134
5135
  projects[trustDir].hasTrustDialogAccepted = true;
5135
- writeFileSync5(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
5136
+ writeFileSync6(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
5136
5137
  } catch {
5137
5138
  }
5138
5139
  try {
5139
- const settingsDir = path15.join(os6.homedir(), ".claude", "projects");
5140
+ const settingsDir = path15.join(os7.homedir(), ".claude", "projects");
5140
5141
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
5141
5142
  const projSettingsDir = path15.join(settingsDir, normalizedKey);
5142
5143
  const settingsPath = path15.join(projSettingsDir, "settings.json");
@@ -5171,7 +5172,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5171
5172
  perms.allow = allow;
5172
5173
  settings.permissions = perms;
5173
5174
  mkdirSync6(projSettingsDir, { recursive: true });
5174
- writeFileSync5(settingsPath, JSON.stringify(settings, null, 2) + "\n");
5175
+ writeFileSync6(settingsPath, JSON.stringify(settings, null, 2) + "\n");
5175
5176
  }
5176
5177
  } catch {
5177
5178
  }
@@ -5184,7 +5185,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5184
5185
  let legacyFallbackWarned = false;
5185
5186
  if (!useExeAgent && !useBinSymlink) {
5186
5187
  const identityPath = path15.join(
5187
- os6.homedir(),
5188
+ os7.homedir(),
5188
5189
  ".exe-os",
5189
5190
  "identity",
5190
5191
  `${employeeName}.md`
@@ -5214,7 +5215,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5214
5215
  }
5215
5216
  let sessionContextFlag = "";
5216
5217
  try {
5217
- const ctxDir = path15.join(os6.homedir(), ".exe-os", "session-cache");
5218
+ const ctxDir = path15.join(os7.homedir(), ".exe-os", "session-cache");
5218
5219
  mkdirSync6(ctxDir, { recursive: true });
5219
5220
  const ctxFile = path15.join(ctxDir, `session-context-${sessionName}.md`);
5220
5221
  const ctxContent = [
@@ -5223,7 +5224,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5223
5224
  `Your parent exe session is ${exeSession}.`,
5224
5225
  `Your employees (if any) use the -${exeSession} suffix (e.g., tom-${exeSession}).`
5225
5226
  ].join("\n");
5226
- writeFileSync5(ctxFile, ctxContent);
5227
+ writeFileSync6(ctxFile, ctxContent);
5227
5228
  sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
5228
5229
  } catch {
5229
5230
  }
@@ -5262,7 +5263,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5262
5263
  try {
5263
5264
  const mySession = getMySession();
5264
5265
  const dispatchInfo = path15.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
5265
- writeFileSync5(dispatchInfo, JSON.stringify({
5266
+ writeFileSync6(dispatchInfo, JSON.stringify({
5266
5267
  dispatchedBy: mySession,
5267
5268
  rootExe: exeSession,
5268
5269
  provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : "anthropic",
@@ -5325,13 +5326,13 @@ var init_tmux_routing = __esm({
5325
5326
  init_provider_table();
5326
5327
  init_intercom_queue();
5327
5328
  init_plan_limits();
5328
- SPAWN_LOCK_DIR = path15.join(os6.homedir(), ".exe-os", "spawn-locks");
5329
- SESSION_CACHE = path15.join(os6.homedir(), ".exe-os", "session-cache");
5329
+ SPAWN_LOCK_DIR = path15.join(os7.homedir(), ".exe-os", "spawn-locks");
5330
+ SESSION_CACHE = path15.join(os7.homedir(), ".exe-os", "session-cache");
5330
5331
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
5331
5332
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
5332
5333
  VERIFY_PANE_LINES = 200;
5333
5334
  INTERCOM_DEBOUNCE_MS = 3e4;
5334
- INTERCOM_LOG2 = path15.join(os6.homedir(), ".exe-os", "intercom.log");
5335
+ INTERCOM_LOG2 = path15.join(os7.homedir(), ".exe-os", "intercom.log");
5335
5336
  DEBOUNCE_FILE = path15.join(SESSION_CACHE, "intercom-debounce.json");
5336
5337
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
5337
5338
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -5507,14 +5508,14 @@ __export(worker_gate_exports, {
5507
5508
  tryAcquireBackfillLock: () => tryAcquireBackfillLock,
5508
5509
  tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
5509
5510
  });
5510
- import { readdirSync as readdirSync6, writeFileSync as writeFileSync7, unlinkSync as unlinkSync6, mkdirSync as mkdirSync8, existsSync as existsSync14 } from "fs";
5511
+ import { readdirSync as readdirSync6, writeFileSync as writeFileSync8, unlinkSync as unlinkSync7, mkdirSync as mkdirSync8, existsSync as existsSync14 } from "fs";
5511
5512
  import path18 from "path";
5512
5513
  function tryAcquireWorkerSlot() {
5513
5514
  try {
5514
5515
  mkdirSync8(WORKER_PID_DIR, { recursive: true });
5515
5516
  const reservationId = `res-${process.pid}-${Date.now()}`;
5516
5517
  const reservationPath = path18.join(WORKER_PID_DIR, `${reservationId}.pid`);
5517
- writeFileSync7(reservationPath, String(process.pid));
5518
+ writeFileSync8(reservationPath, String(process.pid));
5518
5519
  const files = readdirSync6(WORKER_PID_DIR);
5519
5520
  let alive = 0;
5520
5521
  for (const f of files) {
@@ -5531,20 +5532,20 @@ function tryAcquireWorkerSlot() {
5531
5532
  alive++;
5532
5533
  } catch {
5533
5534
  try {
5534
- unlinkSync6(path18.join(WORKER_PID_DIR, f));
5535
+ unlinkSync7(path18.join(WORKER_PID_DIR, f));
5535
5536
  } catch {
5536
5537
  }
5537
5538
  }
5538
5539
  }
5539
5540
  if (alive > MAX_CONCURRENT_WORKERS) {
5540
5541
  try {
5541
- unlinkSync6(reservationPath);
5542
+ unlinkSync7(reservationPath);
5542
5543
  } catch {
5543
5544
  }
5544
5545
  return false;
5545
5546
  }
5546
5547
  try {
5547
- unlinkSync6(reservationPath);
5548
+ unlinkSync7(reservationPath);
5548
5549
  } catch {
5549
5550
  }
5550
5551
  return true;
@@ -5555,13 +5556,13 @@ function tryAcquireWorkerSlot() {
5555
5556
  function registerWorkerPid(pid) {
5556
5557
  try {
5557
5558
  mkdirSync8(WORKER_PID_DIR, { recursive: true });
5558
- writeFileSync7(path18.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
5559
+ writeFileSync8(path18.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
5559
5560
  } catch {
5560
5561
  }
5561
5562
  }
5562
5563
  function cleanupWorkerPid() {
5563
5564
  try {
5564
- unlinkSync6(path18.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
5565
+ unlinkSync7(path18.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
5565
5566
  } catch {
5566
5567
  }
5567
5568
  }
@@ -5584,7 +5585,7 @@ function tryAcquireBackfillLock() {
5584
5585
  } catch {
5585
5586
  }
5586
5587
  }
5587
- writeFileSync7(BACKFILL_LOCK, String(process.pid));
5588
+ writeFileSync8(BACKFILL_LOCK, String(process.pid));
5588
5589
  return true;
5589
5590
  } catch {
5590
5591
  return true;
@@ -5592,7 +5593,7 @@ function tryAcquireBackfillLock() {
5592
5593
  }
5593
5594
  function releaseBackfillLock() {
5594
5595
  try {
5595
- unlinkSync6(BACKFILL_LOCK);
5596
+ unlinkSync7(BACKFILL_LOCK);
5596
5597
  } catch {
5597
5598
  }
5598
5599
  }
@@ -5714,7 +5715,7 @@ __export(cloud_sync_exports, {
5714
5715
  mergeRosterFromRemote: () => mergeRosterFromRemote,
5715
5716
  recordRosterDeletion: () => recordRosterDeletion
5716
5717
  });
5717
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, existsSync as existsSync15, readdirSync as readdirSync7, mkdirSync as mkdirSync9, appendFileSync as appendFileSync2, unlinkSync as unlinkSync7, openSync, closeSync } from "fs";
5718
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, existsSync as existsSync15, readdirSync as readdirSync7, mkdirSync as mkdirSync9, appendFileSync as appendFileSync2, unlinkSync as unlinkSync8, openSync, closeSync } from "fs";
5718
5719
  import crypto7 from "crypto";
5719
5720
  import path19 from "path";
5720
5721
  import { homedir } from "os";
@@ -5733,7 +5734,7 @@ async function withRosterLock(fn) {
5733
5734
  try {
5734
5735
  const fd = openSync(ROSTER_LOCK_PATH, "wx");
5735
5736
  closeSync(fd);
5736
- writeFileSync8(ROSTER_LOCK_PATH, String(Date.now()));
5737
+ writeFileSync9(ROSTER_LOCK_PATH, String(Date.now()));
5737
5738
  } catch (err) {
5738
5739
  if (err.code === "EEXIST") {
5739
5740
  try {
@@ -5741,10 +5742,10 @@ async function withRosterLock(fn) {
5741
5742
  if (Date.now() - ts < LOCK_STALE_MS) {
5742
5743
  throw new Error("Roster merge already in progress \u2014 another sync is running");
5743
5744
  }
5744
- unlinkSync7(ROSTER_LOCK_PATH);
5745
+ unlinkSync8(ROSTER_LOCK_PATH);
5745
5746
  const fd = openSync(ROSTER_LOCK_PATH, "wx");
5746
5747
  closeSync(fd);
5747
- writeFileSync8(ROSTER_LOCK_PATH, String(Date.now()));
5748
+ writeFileSync9(ROSTER_LOCK_PATH, String(Date.now()));
5748
5749
  } catch (retryErr) {
5749
5750
  if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
5750
5751
  throw new Error("Roster merge already in progress \u2014 another sync is running");
@@ -5757,7 +5758,7 @@ async function withRosterLock(fn) {
5757
5758
  return await fn();
5758
5759
  } finally {
5759
5760
  try {
5760
- unlinkSync7(ROSTER_LOCK_PATH);
5761
+ unlinkSync8(ROSTER_LOCK_PATH);
5761
5762
  } catch {
5762
5763
  }
5763
5764
  }
@@ -6057,13 +6058,13 @@ function recordRosterDeletion(name) {
6057
6058
  } catch {
6058
6059
  }
6059
6060
  if (!deletions.includes(name)) deletions.push(name);
6060
- writeFileSync8(ROSTER_DELETIONS_PATH, JSON.stringify(deletions));
6061
+ writeFileSync9(ROSTER_DELETIONS_PATH, JSON.stringify(deletions));
6061
6062
  }
6062
6063
  function consumeRosterDeletions() {
6063
6064
  try {
6064
6065
  if (!existsSync15(ROSTER_DELETIONS_PATH)) return [];
6065
6066
  const deletions = JSON.parse(readFileSync12(ROSTER_DELETIONS_PATH, "utf-8"));
6066
- writeFileSync8(ROSTER_DELETIONS_PATH, "[]");
6067
+ writeFileSync9(ROSTER_DELETIONS_PATH, "[]");
6067
6068
  return deletions;
6068
6069
  } catch {
6069
6070
  return [];
@@ -6179,7 +6180,7 @@ function mergeConfig(remoteConfig, configPath) {
6179
6180
  const merged = { ...remoteConfig, ...local };
6180
6181
  const dir = path19.dirname(cfgPath);
6181
6182
  if (!existsSync15(dir)) mkdirSync9(dir, { recursive: true });
6182
- writeFileSync8(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
6183
+ writeFileSync9(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
6183
6184
  }
6184
6185
  async function mergeRosterFromRemote(remote, paths) {
6185
6186
  return withRosterLock(async () => {
@@ -6199,7 +6200,11 @@ async function mergeRosterFromRemote(remote, paths) {
6199
6200
  } catch {
6200
6201
  }
6201
6202
  }
6202
- const remoteIdentity = remote.identities[`${remoteEmp.name}.md`];
6203
+ const lookupKey = `${remoteEmp.name}.md`;
6204
+ const matchedKey = Object.keys(remote.identities).find(
6205
+ (k) => k.toLowerCase() === lookupKey.toLowerCase()
6206
+ ) ?? lookupKey;
6207
+ const remoteIdentity = remote.identities[matchedKey];
6203
6208
  if (remoteIdentity) {
6204
6209
  if (!existsSync15(identityDir)) mkdirSync9(identityDir, { recursive: true });
6205
6210
  const idPath = path19.join(identityDir, `${remoteEmp.name}.md`);
@@ -6209,7 +6214,7 @@ async function mergeRosterFromRemote(remote, paths) {
6209
6214
  } catch {
6210
6215
  }
6211
6216
  if (localIdentity !== remoteIdentity) {
6212
- writeFileSync8(idPath, remoteIdentity, "utf-8");
6217
+ writeFileSync9(idPath, remoteIdentity, "utf-8");
6213
6218
  identitiesUpdated++;
6214
6219
  }
6215
6220
  }
@@ -6852,8 +6857,8 @@ var init_schedules = __esm({
6852
6857
  init_employees();
6853
6858
  import path20 from "path";
6854
6859
  import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
6855
- import { existsSync as existsSync16, readFileSync as readFileSync13, readdirSync as readdirSync8, unlinkSync as unlinkSync8 } from "fs";
6856
- import os7 from "os";
6860
+ import { existsSync as existsSync16, readFileSync as readFileSync13, readdirSync as readdirSync8, unlinkSync as unlinkSync9 } from "fs";
6861
+ import os8 from "os";
6857
6862
 
6858
6863
  // src/lib/employee-templates.ts
6859
6864
  init_global_procedures();
@@ -7331,7 +7336,7 @@ init_notifications();
7331
7336
 
7332
7337
  // src/adapters/claude/active-agent.ts
7333
7338
  init_config();
7334
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, unlinkSync as unlinkSync5, readdirSync as readdirSync4 } from "fs";
7339
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, unlinkSync as unlinkSync6, readdirSync as readdirSync4 } from "fs";
7335
7340
  import { execSync as execSync8 } from "child_process";
7336
7341
  import path16 from "path";
7337
7342
 
@@ -7347,7 +7352,7 @@ function getMarkerPath() {
7347
7352
  function writeActiveAgent(agentId, agentRole) {
7348
7353
  try {
7349
7354
  mkdirSync7(CACHE_DIR, { recursive: true });
7350
- writeFileSync6(
7355
+ writeFileSync7(
7351
7356
  getMarkerPath(),
7352
7357
  JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
7353
7358
  );
@@ -7357,11 +7362,11 @@ function writeActiveAgent(agentId, agentRole) {
7357
7362
  function cleanupSessionMarkers() {
7358
7363
  const key = getSessionKey();
7359
7364
  try {
7360
- unlinkSync5(path16.join(CACHE_DIR, `active-agent-${key}.json`));
7365
+ unlinkSync6(path16.join(CACHE_DIR, `active-agent-${key}.json`));
7361
7366
  } catch {
7362
7367
  }
7363
7368
  try {
7364
- unlinkSync5(path16.join(CACHE_DIR, "active-agent-undefined.json"));
7369
+ unlinkSync6(path16.join(CACHE_DIR, "active-agent-undefined.json"));
7365
7370
  } catch {
7366
7371
  }
7367
7372
  }
@@ -7550,7 +7555,7 @@ async function boot(options) {
7550
7555
  for (const f of readdirSync8(exeExeDir)) {
7551
7556
  if (f.startsWith("review-") && f.endsWith(".md")) {
7552
7557
  try {
7553
- unlinkSync8(path20.join(exeExeDir, f));
7558
+ unlinkSync9(path20.join(exeExeDir, f));
7554
7559
  } catch {
7555
7560
  }
7556
7561
  }
@@ -7599,8 +7604,8 @@ async function boot(options) {
7599
7604
  if (existsSync16(filePath)) {
7600
7605
  let content = readFileSync13(filePath, "utf8");
7601
7606
  content = content.replace(/\*\*Status:\*\* needs_review/, "**Status:** done");
7602
- const { writeFileSync: writeFileSync9 } = await import("fs");
7603
- writeFileSync9(filePath, content);
7607
+ const { writeFileSync: writeFileSync10 } = await import("fs");
7608
+ writeFileSync10(filePath, content);
7604
7609
  }
7605
7610
  } catch {
7606
7611
  }
@@ -8070,7 +8075,7 @@ async function boot(options) {
8070
8075
  ]);
8071
8076
  try {
8072
8077
  const configPath = path20.join(
8073
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path20.join(os7.homedir(), ".exe-os"),
8078
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path20.join(os8.homedir(), ".exe-os"),
8074
8079
  "config.json"
8075
8080
  );
8076
8081
  if (existsSync16(configPath)) {
@@ -8162,8 +8167,8 @@ async function boot(options) {
8162
8167
  try {
8163
8168
  const flagPath = path20.join(EXE_AI_DIR, "session-cache", "needs-backfill");
8164
8169
  if (existsSync16(flagPath)) {
8165
- const { unlinkSync: unlinkSync9 } = await import("fs");
8166
- unlinkSync9(flagPath);
8170
+ const { unlinkSync: unlinkSync10 } = await import("fs");
8171
+ unlinkSync10(flagPath);
8167
8172
  }
8168
8173
  } catch {
8169
8174
  }
@@ -8270,7 +8275,7 @@ ${brief}`;
8270
8275
  console.log(brief);
8271
8276
  try {
8272
8277
  const configPath2 = path20.join(
8273
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path20.join(os7.homedir(), ".exe-os"),
8278
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path20.join(os8.homedir(), ".exe-os"),
8274
8279
  "config.json"
8275
8280
  );
8276
8281
  if (existsSync16(configPath2)) {