@askexenow/exe-os 0.9.55 → 0.9.56

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 (44) hide show
  1. package/dist/bin/cleanup-stale-review-tasks.js +26 -8
  2. package/dist/bin/cli.js +14 -1
  3. package/dist/bin/exe-boot.js +267 -190
  4. package/dist/bin/exe-dispatch.js +182 -105
  5. package/dist/bin/exe-export-behaviors.js +7 -0
  6. package/dist/bin/exe-gateway.js +177 -100
  7. package/dist/bin/exe-heartbeat.js +38 -20
  8. package/dist/bin/exe-launch-agent.js +7 -0
  9. package/dist/bin/exe-pending-messages.js +50 -32
  10. package/dist/bin/exe-pending-notifications.js +53 -35
  11. package/dist/bin/exe-pending-reviews.js +55 -37
  12. package/dist/bin/exe-session-cleanup.js +168 -91
  13. package/dist/bin/exe-start-codex.js +7 -0
  14. package/dist/bin/exe-start-opencode.js +7 -0
  15. package/dist/bin/exe-status.js +26 -8
  16. package/dist/bin/git-sweep.js +184 -107
  17. package/dist/bin/intercom-check.js +170 -93
  18. package/dist/bin/scan-tasks.js +190 -113
  19. package/dist/gateway/index.js +166 -89
  20. package/dist/hooks/bug-report-worker.js +158 -81
  21. package/dist/hooks/codex-stop-task-finalizer.js +57 -39
  22. package/dist/hooks/commit-complete.js +182 -105
  23. package/dist/hooks/post-compact.js +50 -32
  24. package/dist/hooks/pre-compact.js +185 -108
  25. package/dist/hooks/pre-tool-use.js +71 -53
  26. package/dist/hooks/prompt-submit.js +176 -92
  27. package/dist/hooks/session-end.js +193 -116
  28. package/dist/hooks/session-start.js +53 -35
  29. package/dist/hooks/stop.js +62 -44
  30. package/dist/hooks/subagent-stop.js +50 -32
  31. package/dist/hooks/summary-worker.js +109 -91
  32. package/dist/index.js +205 -121
  33. package/dist/lib/exe-daemon.js +381 -304
  34. package/dist/lib/messaging.js +32 -14
  35. package/dist/lib/tasks.js +180 -103
  36. package/dist/lib/tmux-routing.js +180 -103
  37. package/dist/mcp/server.js +356 -279
  38. package/dist/mcp/tools/create-task.js +194 -117
  39. package/dist/mcp/tools/list-tasks.js +45 -27
  40. package/dist/mcp/tools/send-message.js +36 -18
  41. package/dist/mcp/tools/update-task.js +189 -112
  42. package/dist/runtime/index.js +191 -107
  43. package/dist/tui/App.js +228 -151
  44. package/package.json +1 -1
@@ -5090,15 +5090,79 @@ var init_plan_limits = __esm({
5090
5090
  }
5091
5091
  });
5092
5092
 
5093
+ // src/lib/agent-symlinks.ts
5094
+ import os9 from "os";
5095
+ import path13 from "path";
5096
+ import {
5097
+ existsSync as existsSync13,
5098
+ lstatSync,
5099
+ mkdirSync as mkdirSync6,
5100
+ readlinkSync as readlinkSync2,
5101
+ symlinkSync as symlinkSync2
5102
+ } from "fs";
5103
+ function claudeAgentsDir(homeDir) {
5104
+ return path13.join(homeDir, ".claude", "agents");
5105
+ }
5106
+ function identitySourcePath(homeDir, agentId) {
5107
+ return path13.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
5108
+ }
5109
+ function claudeAgentLinkPath(homeDir, agentId) {
5110
+ return path13.join(claudeAgentsDir(homeDir), `${agentId}.md`);
5111
+ }
5112
+ function ensureAgentSymlink(agentId, homeDir = os9.homedir()) {
5113
+ const target = identitySourcePath(homeDir, agentId);
5114
+ const link = claudeAgentLinkPath(homeDir, agentId);
5115
+ mkdirSync6(claudeAgentsDir(homeDir), { recursive: true });
5116
+ if (existsSync13(link)) {
5117
+ let stat;
5118
+ try {
5119
+ stat = lstatSync(link);
5120
+ } catch {
5121
+ return { agentId, action: "conflict", target, link, conflict: "stat_failed" };
5122
+ }
5123
+ if (!stat.isSymbolicLink()) {
5124
+ return { agentId, action: "conflict", target, link, conflict: "regular_file" };
5125
+ }
5126
+ let currentTarget;
5127
+ try {
5128
+ currentTarget = readlinkSync2(link);
5129
+ } catch {
5130
+ return { agentId, action: "conflict", target, link, conflict: "readlink_failed" };
5131
+ }
5132
+ if (currentTarget === target) {
5133
+ return { agentId, action: "already_correct", target, link };
5134
+ }
5135
+ return { agentId, action: "conflict", target, link, conflict: `points_to:${currentTarget}` };
5136
+ }
5137
+ try {
5138
+ symlinkSync2(target, link);
5139
+ } catch (err) {
5140
+ return {
5141
+ agentId,
5142
+ action: "conflict",
5143
+ target,
5144
+ link,
5145
+ conflict: err instanceof Error ? err.message : String(err)
5146
+ };
5147
+ }
5148
+ return { agentId, action: "created", target, link };
5149
+ }
5150
+ var init_agent_symlinks = __esm({
5151
+ "src/lib/agent-symlinks.ts"() {
5152
+ "use strict";
5153
+ init_employees();
5154
+ }
5155
+ });
5156
+
5093
5157
  // src/lib/notifications.ts
5094
5158
  import crypto2 from "crypto";
5095
- import path13 from "path";
5096
- import os9 from "os";
5159
+ import path14 from "path";
5160
+ import os10 from "os";
5097
5161
  import {
5098
5162
  readFileSync as readFileSync10,
5099
5163
  readdirSync as readdirSync2,
5100
5164
  unlinkSync as unlinkSync3,
5101
- existsSync as existsSync13,
5165
+ existsSync as existsSync14,
5102
5166
  rmdirSync
5103
5167
  } from "fs";
5104
5168
  async function writeNotification(notification) {
@@ -5221,9 +5285,9 @@ async function markDoneTaskNotificationsAsRead(sessionScope) {
5221
5285
  }
5222
5286
  }
5223
5287
  async function migrateJsonNotifications() {
5224
- const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path13.join(os9.homedir(), ".exe-os");
5225
- const notifDir = path13.join(base, "notifications");
5226
- if (!existsSync13(notifDir)) return 0;
5288
+ const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path14.join(os10.homedir(), ".exe-os");
5289
+ const notifDir = path14.join(base, "notifications");
5290
+ if (!existsSync14(notifDir)) return 0;
5227
5291
  let migrated = 0;
5228
5292
  try {
5229
5293
  const files = readdirSync2(notifDir).filter((f) => f.endsWith(".json"));
@@ -5231,7 +5295,7 @@ async function migrateJsonNotifications() {
5231
5295
  const client = getClient();
5232
5296
  for (const file of files) {
5233
5297
  try {
5234
- const filePath = path13.join(notifDir, file);
5298
+ const filePath = path14.join(notifDir, file);
5235
5299
  const data = JSON.parse(readFileSync10(filePath, "utf8"));
5236
5300
  await client.execute({
5237
5301
  sql: `INSERT OR IGNORE INTO notifications (id, agent_id, agent_role, event, project, summary, task_file, session_scope, read, created_at)
@@ -5386,7 +5450,7 @@ __export(project_name_exports, {
5386
5450
  getProjectName: () => getProjectName
5387
5451
  });
5388
5452
  import { execSync as execSync6 } from "child_process";
5389
- import path14 from "path";
5453
+ import path15 from "path";
5390
5454
  function getProjectName(cwd) {
5391
5455
  const dir = cwd ?? process.cwd();
5392
5456
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -5399,7 +5463,7 @@ function getProjectName(cwd) {
5399
5463
  timeout: 2e3,
5400
5464
  stdio: ["pipe", "pipe", "pipe"]
5401
5465
  }).trim();
5402
- repoRoot = path14.dirname(gitCommonDir);
5466
+ repoRoot = path15.dirname(gitCommonDir);
5403
5467
  } catch {
5404
5468
  repoRoot = execSync6("git rev-parse --show-toplevel", {
5405
5469
  cwd: dir,
@@ -5408,11 +5472,11 @@ function getProjectName(cwd) {
5408
5472
  stdio: ["pipe", "pipe", "pipe"]
5409
5473
  }).trim();
5410
5474
  }
5411
- _cached2 = path14.basename(repoRoot);
5475
+ _cached2 = path15.basename(repoRoot);
5412
5476
  _cachedCwd = dir;
5413
5477
  return _cached2;
5414
5478
  } catch {
5415
- _cached2 = path14.basename(dir);
5479
+ _cached2 = path15.basename(dir);
5416
5480
  _cachedCwd = dir;
5417
5481
  return _cached2;
5418
5482
  }
@@ -5494,11 +5558,11 @@ var init_session_scope = __esm({
5494
5558
 
5495
5559
  // src/lib/tasks-crud.ts
5496
5560
  import crypto4 from "crypto";
5497
- import path15 from "path";
5498
- import os10 from "os";
5561
+ import path16 from "path";
5562
+ import os11 from "os";
5499
5563
  import { execSync as execSync7 } from "child_process";
5500
5564
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
5501
- import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
5565
+ import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
5502
5566
  async function writeCheckpoint(input) {
5503
5567
  const client = getClient();
5504
5568
  const row = await resolveTask(client, input.taskId);
@@ -5697,8 +5761,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
5697
5761
  }
5698
5762
  if (input.baseDir) {
5699
5763
  try {
5700
- await mkdir4(path15.join(input.baseDir, "exe", "output"), { recursive: true });
5701
- await mkdir4(path15.join(input.baseDir, "exe", "research"), { recursive: true });
5764
+ await mkdir4(path16.join(input.baseDir, "exe", "output"), { recursive: true });
5765
+ await mkdir4(path16.join(input.baseDir, "exe", "research"), { recursive: true });
5702
5766
  await ensureArchitectureDoc(input.baseDir, input.projectName);
5703
5767
  await ensureGitignoreExe(input.baseDir);
5704
5768
  } catch {
@@ -5734,10 +5798,10 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
5734
5798
  });
5735
5799
  if (input.baseDir) {
5736
5800
  try {
5737
- const EXE_OS_DIR = path15.join(os10.homedir(), ".exe-os");
5738
- const mdPath = path15.join(EXE_OS_DIR, taskFile);
5739
- const mdDir = path15.dirname(mdPath);
5740
- if (!existsSync14(mdDir)) await mkdir4(mdDir, { recursive: true });
5801
+ const EXE_OS_DIR = path16.join(os11.homedir(), ".exe-os");
5802
+ const mdPath = path16.join(EXE_OS_DIR, taskFile);
5803
+ const mdDir = path16.dirname(mdPath);
5804
+ if (!existsSync15(mdDir)) await mkdir4(mdDir, { recursive: true });
5741
5805
  const reviewer = input.reviewer ?? input.assignedBy;
5742
5806
  const mdContent = `# ${input.title}
5743
5807
 
@@ -6037,9 +6101,9 @@ async function deleteTaskCore(taskId, _baseDir) {
6037
6101
  return { taskFile, assignedTo, assignedBy, taskSlug };
6038
6102
  }
6039
6103
  async function ensureArchitectureDoc(baseDir, projectName) {
6040
- const archPath = path15.join(baseDir, "exe", "ARCHITECTURE.md");
6104
+ const archPath = path16.join(baseDir, "exe", "ARCHITECTURE.md");
6041
6105
  try {
6042
- if (existsSync14(archPath)) return;
6106
+ if (existsSync15(archPath)) return;
6043
6107
  const template = [
6044
6108
  `# ${projectName} \u2014 System Architecture`,
6045
6109
  "",
@@ -6072,9 +6136,9 @@ async function ensureArchitectureDoc(baseDir, projectName) {
6072
6136
  }
6073
6137
  }
6074
6138
  async function ensureGitignoreExe(baseDir) {
6075
- const gitignorePath = path15.join(baseDir, ".gitignore");
6139
+ const gitignorePath = path16.join(baseDir, ".gitignore");
6076
6140
  try {
6077
- if (existsSync14(gitignorePath)) {
6141
+ if (existsSync15(gitignorePath)) {
6078
6142
  const content = readFileSync11(gitignorePath, "utf-8");
6079
6143
  if (/^\/?exe\/?$/m.test(content)) return;
6080
6144
  await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
@@ -6118,8 +6182,8 @@ __export(tasks_review_exports, {
6118
6182
  isStale: () => isStale,
6119
6183
  listPendingReviews: () => listPendingReviews
6120
6184
  });
6121
- import path16 from "path";
6122
- import { existsSync as existsSync15, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
6185
+ import path17 from "path";
6186
+ import { existsSync as existsSync16, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
6123
6187
  function formatAge(isoTimestamp) {
6124
6188
  if (!isoTimestamp) return "";
6125
6189
  const ms = Date.now() - new Date(isoTimestamp).getTime();
@@ -6388,11 +6452,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
6388
6452
  );
6389
6453
  }
6390
6454
  try {
6391
- const cacheDir = path16.join(EXE_AI_DIR, "session-cache");
6392
- if (existsSync15(cacheDir)) {
6455
+ const cacheDir = path17.join(EXE_AI_DIR, "session-cache");
6456
+ if (existsSync16(cacheDir)) {
6393
6457
  for (const f of readdirSync3(cacheDir)) {
6394
6458
  if (f.startsWith("review-notified-")) {
6395
- unlinkSync4(path16.join(cacheDir, f));
6459
+ unlinkSync4(path17.join(cacheDir, f));
6396
6460
  }
6397
6461
  }
6398
6462
  }
@@ -6414,7 +6478,7 @@ var init_tasks_review = __esm({
6414
6478
  });
6415
6479
 
6416
6480
  // src/lib/tasks-chain.ts
6417
- import path17 from "path";
6481
+ import path18 from "path";
6418
6482
  import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
6419
6483
  async function cascadeUnblock(taskId, baseDir, now) {
6420
6484
  const client = getClient();
@@ -6431,7 +6495,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
6431
6495
  });
6432
6496
  for (const ur of unblockedRows.rows) {
6433
6497
  try {
6434
- const ubFile = path17.join(baseDir, String(ur.task_file));
6498
+ const ubFile = path18.join(baseDir, String(ur.task_file));
6435
6499
  let ubContent = await readFile4(ubFile, "utf-8");
6436
6500
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
6437
6501
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -6615,10 +6679,10 @@ async function disposeEmbedder() {
6615
6679
  async function embedDirect(text) {
6616
6680
  const llamaCpp = await import("node-llama-cpp");
6617
6681
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6618
- const { existsSync: existsSync22 } = await import("fs");
6619
- const path26 = await import("path");
6620
- const modelPath = path26.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
6621
- if (!existsSync22(modelPath)) {
6682
+ const { existsSync: existsSync23 } = await import("fs");
6683
+ const path27 = await import("path");
6684
+ const modelPath = path27.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
6685
+ if (!existsSync23(modelPath)) {
6622
6686
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
6623
6687
  }
6624
6688
  const llama = await llamaCpp.getLlama();
@@ -6984,8 +7048,8 @@ __export(tasks_exports, {
6984
7048
  updateTaskStatus: () => updateTaskStatus,
6985
7049
  writeCheckpoint: () => writeCheckpoint
6986
7050
  });
6987
- import path18 from "path";
6988
- import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5 } from "fs";
7051
+ import path19 from "path";
7052
+ import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, unlinkSync as unlinkSync5 } from "fs";
6989
7053
  async function createTask(input) {
6990
7054
  const result = await createTaskCore(input);
6991
7055
  if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
@@ -7004,10 +7068,10 @@ async function updateTask(input) {
7004
7068
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
7005
7069
  try {
7006
7070
  const agent = String(row.assigned_to);
7007
- const cacheDir = path18.join(EXE_AI_DIR, "session-cache");
7008
- const cachePath = path18.join(cacheDir, `current-task-${agent}.json`);
7071
+ const cacheDir = path19.join(EXE_AI_DIR, "session-cache");
7072
+ const cachePath = path19.join(cacheDir, `current-task-${agent}.json`);
7009
7073
  if (input.status === "in_progress") {
7010
- mkdirSync6(cacheDir, { recursive: true });
7074
+ mkdirSync7(cacheDir, { recursive: true });
7011
7075
  writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
7012
7076
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
7013
7077
  try {
@@ -7477,13 +7541,13 @@ __export(tmux_routing_exports, {
7477
7541
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
7478
7542
  });
7479
7543
  import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
7480
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync16, appendFileSync, readdirSync as readdirSync4 } from "fs";
7481
- import path19 from "path";
7482
- import os11 from "os";
7544
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync17, appendFileSync, readdirSync as readdirSync4 } from "fs";
7545
+ import path20 from "path";
7546
+ import os12 from "os";
7483
7547
  import { fileURLToPath as fileURLToPath2 } from "url";
7484
7548
  import { unlinkSync as unlinkSync6 } from "fs";
7485
7549
  function spawnLockPath(sessionName) {
7486
- return path19.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
7550
+ return path20.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
7487
7551
  }
7488
7552
  function isProcessAlive(pid) {
7489
7553
  try {
@@ -7494,11 +7558,11 @@ function isProcessAlive(pid) {
7494
7558
  }
7495
7559
  }
7496
7560
  function acquireSpawnLock2(sessionName) {
7497
- if (!existsSync16(SPAWN_LOCK_DIR)) {
7498
- mkdirSync7(SPAWN_LOCK_DIR, { recursive: true });
7561
+ if (!existsSync17(SPAWN_LOCK_DIR)) {
7562
+ mkdirSync8(SPAWN_LOCK_DIR, { recursive: true });
7499
7563
  }
7500
7564
  const lockFile = spawnLockPath(sessionName);
7501
- if (existsSync16(lockFile)) {
7565
+ if (existsSync17(lockFile)) {
7502
7566
  try {
7503
7567
  const lock = JSON.parse(readFileSync12(lockFile, "utf8"));
7504
7568
  const age = Date.now() - lock.timestamp;
@@ -7520,13 +7584,13 @@ function releaseSpawnLock2(sessionName) {
7520
7584
  function resolveBehaviorsExporterScript() {
7521
7585
  try {
7522
7586
  const thisFile = fileURLToPath2(import.meta.url);
7523
- const scriptPath = path19.join(
7524
- path19.dirname(thisFile),
7587
+ const scriptPath = path20.join(
7588
+ path20.dirname(thisFile),
7525
7589
  "..",
7526
7590
  "bin",
7527
7591
  "exe-export-behaviors.js"
7528
7592
  );
7529
- return existsSync16(scriptPath) ? scriptPath : null;
7593
+ return existsSync17(scriptPath) ? scriptPath : null;
7530
7594
  } catch {
7531
7595
  return null;
7532
7596
  }
@@ -7592,11 +7656,11 @@ function extractRootExe(name) {
7592
7656
  return parts.length > 0 ? parts[parts.length - 1] : null;
7593
7657
  }
7594
7658
  function registerParentExe(sessionKey, parentExe, dispatchedBy) {
7595
- if (!existsSync16(SESSION_CACHE)) {
7596
- mkdirSync7(SESSION_CACHE, { recursive: true });
7659
+ if (!existsSync17(SESSION_CACHE)) {
7660
+ mkdirSync8(SESSION_CACHE, { recursive: true });
7597
7661
  }
7598
7662
  const rootExe = extractRootExe(parentExe) ?? parentExe;
7599
- const filePath = path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
7663
+ const filePath = path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
7600
7664
  writeFileSync8(filePath, JSON.stringify({
7601
7665
  parentExe: rootExe,
7602
7666
  dispatchedBy: dispatchedBy || rootExe,
@@ -7605,7 +7669,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
7605
7669
  }
7606
7670
  function getParentExe(sessionKey) {
7607
7671
  try {
7608
- const data = JSON.parse(readFileSync12(path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
7672
+ const data = JSON.parse(readFileSync12(path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
7609
7673
  return data.parentExe || null;
7610
7674
  } catch {
7611
7675
  return null;
@@ -7614,7 +7678,7 @@ function getParentExe(sessionKey) {
7614
7678
  function getDispatchedBy(sessionKey) {
7615
7679
  try {
7616
7680
  const data = JSON.parse(readFileSync12(
7617
- path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
7681
+ path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
7618
7682
  "utf8"
7619
7683
  ));
7620
7684
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -7684,7 +7748,7 @@ async function verifyPaneAtCapacity(sessionName) {
7684
7748
  }
7685
7749
  function readDebounceState() {
7686
7750
  try {
7687
- if (!existsSync16(DEBOUNCE_FILE)) return {};
7751
+ if (!existsSync17(DEBOUNCE_FILE)) return {};
7688
7752
  const raw = JSON.parse(readFileSync12(DEBOUNCE_FILE, "utf8"));
7689
7753
  const state = {};
7690
7754
  for (const [key, val] of Object.entries(raw)) {
@@ -7701,7 +7765,7 @@ function readDebounceState() {
7701
7765
  }
7702
7766
  function writeDebounceState(state) {
7703
7767
  try {
7704
- if (!existsSync16(SESSION_CACHE)) mkdirSync7(SESSION_CACHE, { recursive: true });
7768
+ if (!existsSync17(SESSION_CACHE)) mkdirSync8(SESSION_CACHE, { recursive: true });
7705
7769
  writeFileSync8(DEBOUNCE_FILE, JSON.stringify(state));
7706
7770
  } catch {
7707
7771
  }
@@ -7801,8 +7865,8 @@ function sendIntercom(targetSession) {
7801
7865
  try {
7802
7866
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
7803
7867
  const agent = baseAgentName(rawAgent);
7804
- const markerPath = path19.join(SESSION_CACHE, `current-task-${agent}.json`);
7805
- if (existsSync16(markerPath)) {
7868
+ const markerPath = path20.join(SESSION_CACHE, `current-task-${agent}.json`);
7869
+ if (existsSync17(markerPath)) {
7806
7870
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
7807
7871
  return "debounced";
7808
7872
  }
@@ -7812,8 +7876,8 @@ function sendIntercom(targetSession) {
7812
7876
  try {
7813
7877
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
7814
7878
  const agent = baseAgentName(rawAgent);
7815
- const taskDir = path19.join(process.cwd(), "exe", agent);
7816
- if (existsSync16(taskDir)) {
7879
+ const taskDir = path20.join(process.cwd(), "exe", agent);
7880
+ if (existsSync17(taskDir)) {
7817
7881
  const files = readdirSync4(taskDir).filter(
7818
7882
  (f) => f.endsWith(".md") && f !== "DONE.txt"
7819
7883
  );
@@ -7972,23 +8036,23 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7972
8036
  const transport = getTransport();
7973
8037
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
7974
8038
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
7975
- const logDir = path19.join(os11.homedir(), ".exe-os", "session-logs");
7976
- const logFile = path19.join(logDir, `${instanceLabel}-${Date.now()}.log`);
7977
- if (!existsSync16(logDir)) {
7978
- mkdirSync7(logDir, { recursive: true });
8039
+ const logDir = path20.join(os12.homedir(), ".exe-os", "session-logs");
8040
+ const logFile = path20.join(logDir, `${instanceLabel}-${Date.now()}.log`);
8041
+ if (!existsSync17(logDir)) {
8042
+ mkdirSync8(logDir, { recursive: true });
7979
8043
  }
7980
8044
  transport.kill(sessionName);
7981
8045
  let cleanupSuffix = "";
7982
8046
  try {
7983
8047
  const thisFile = fileURLToPath2(import.meta.url);
7984
- const cleanupScript = path19.join(path19.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
7985
- if (existsSync16(cleanupScript)) {
8048
+ const cleanupScript = path20.join(path20.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
8049
+ if (existsSync17(cleanupScript)) {
7986
8050
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
7987
8051
  }
7988
8052
  } catch {
7989
8053
  }
7990
8054
  try {
7991
- const claudeJsonPath = path19.join(os11.homedir(), ".claude.json");
8055
+ const claudeJsonPath = path20.join(os12.homedir(), ".claude.json");
7992
8056
  let claudeJson = {};
7993
8057
  try {
7994
8058
  claudeJson = JSON.parse(readFileSync12(claudeJsonPath, "utf8"));
@@ -8003,10 +8067,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8003
8067
  } catch {
8004
8068
  }
8005
8069
  try {
8006
- const settingsDir = path19.join(os11.homedir(), ".claude", "projects");
8070
+ const settingsDir = path20.join(os12.homedir(), ".claude", "projects");
8007
8071
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
8008
- const projSettingsDir = path19.join(settingsDir, normalizedKey);
8009
- const settingsPath = path19.join(projSettingsDir, "settings.json");
8072
+ const projSettingsDir = path20.join(settingsDir, normalizedKey);
8073
+ const settingsPath = path20.join(projSettingsDir, "settings.json");
8010
8074
  let settings = {};
8011
8075
  try {
8012
8076
  settings = JSON.parse(readFileSync12(settingsPath, "utf8"));
@@ -8037,7 +8101,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8037
8101
  if (changed) {
8038
8102
  perms.allow = allow;
8039
8103
  settings.permissions = perms;
8040
- mkdirSync7(projSettingsDir, { recursive: true });
8104
+ mkdirSync8(projSettingsDir, { recursive: true });
8041
8105
  writeFileSync8(settingsPath, JSON.stringify(settings, null, 2) + "\n");
8042
8106
  }
8043
8107
  } catch {
@@ -8053,8 +8117,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8053
8117
  let behaviorsFlag = "";
8054
8118
  let legacyFallbackWarned = false;
8055
8119
  if (!useExeAgent && !useBinSymlink) {
8056
- const identityPath = path19.join(
8057
- os11.homedir(),
8120
+ const identityPath = path20.join(
8121
+ os12.homedir(),
8058
8122
  ".exe-os",
8059
8123
  "identity",
8060
8124
  `${employeeName}.md`
@@ -8062,14 +8126,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8062
8126
  _resetCcAgentSupportCache();
8063
8127
  const hasAgentFlag = claudeSupportsAgentFlag();
8064
8128
  if (hasAgentFlag) {
8065
- identityFlag = ` --agent ${employeeName}`;
8066
- } else if (existsSync16(identityPath)) {
8129
+ const symlink = ensureAgentSymlink(employeeName);
8130
+ if (symlink.action === "created" || symlink.action === "already_correct") {
8131
+ identityFlag = ` --agent ${employeeName}`;
8132
+ } else if (existsSync17(identityPath)) {
8133
+ identityFlag = ` --append-system-prompt-file ${identityPath}`;
8134
+ legacyFallbackWarned = true;
8135
+ process.stderr.write(
8136
+ `[tmux-routing] WARN: ~/.claude/agents/${employeeName}.md is not the exe-os identity symlink (${symlink.conflict}). Using authoritative ${identityPath} via --append-system-prompt-file.
8137
+ `
8138
+ );
8139
+ } else {
8140
+ identityFlag = ` --agent ${employeeName}`;
8141
+ }
8142
+ } else if (existsSync17(identityPath)) {
8067
8143
  identityFlag = ` --append-system-prompt-file ${identityPath}`;
8068
8144
  legacyFallbackWarned = true;
8069
8145
  }
8070
8146
  const behaviorsFile = exportBehaviorsSync(
8071
8147
  employeeName,
8072
- path19.basename(spawnCwd),
8148
+ path20.basename(spawnCwd),
8073
8149
  sessionName
8074
8150
  );
8075
8151
  if (behaviorsFile) {
@@ -8084,9 +8160,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8084
8160
  }
8085
8161
  let sessionContextFlag = "";
8086
8162
  try {
8087
- const ctxDir = path19.join(os11.homedir(), ".exe-os", "session-cache");
8088
- mkdirSync7(ctxDir, { recursive: true });
8089
- const ctxFile = path19.join(ctxDir, `session-context-${sessionName}.md`);
8163
+ const ctxDir = path20.join(os12.homedir(), ".exe-os", "session-cache");
8164
+ mkdirSync8(ctxDir, { recursive: true });
8165
+ const ctxFile = path20.join(ctxDir, `session-context-${sessionName}.md`);
8090
8166
  const ctxContent = [
8091
8167
  `## Session Context`,
8092
8168
  `You are running in tmux session: ${sessionName}.`,
@@ -8176,7 +8252,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8176
8252
  transport.pipeLog(sessionName, logFile);
8177
8253
  try {
8178
8254
  const mySession = getMySession();
8179
- const dispatchInfo = path19.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
8255
+ const dispatchInfo = path20.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
8180
8256
  writeFileSync8(dispatchInfo, JSON.stringify({
8181
8257
  dispatchedBy: mySession,
8182
8258
  rootExe: exeSession,
@@ -8251,15 +8327,16 @@ var init_tmux_routing = __esm({
8251
8327
  init_intercom_queue();
8252
8328
  init_plan_limits();
8253
8329
  init_employees();
8254
- SPAWN_LOCK_DIR = path19.join(os11.homedir(), ".exe-os", "spawn-locks");
8255
- SESSION_CACHE = path19.join(os11.homedir(), ".exe-os", "session-cache");
8330
+ init_agent_symlinks();
8331
+ SPAWN_LOCK_DIR = path20.join(os12.homedir(), ".exe-os", "spawn-locks");
8332
+ SESSION_CACHE = path20.join(os12.homedir(), ".exe-os", "session-cache");
8256
8333
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
8257
8334
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
8258
8335
  VERIFY_PANE_LINES = 200;
8259
8336
  INTERCOM_DEBOUNCE_MS = 3e4;
8260
8337
  CODEX_DEBOUNCE_MS = 12e4;
8261
- INTERCOM_LOG2 = path19.join(os11.homedir(), ".exe-os", "intercom.log");
8262
- DEBOUNCE_FILE = path19.join(SESSION_CACHE, "intercom-debounce.json");
8338
+ INTERCOM_LOG2 = path20.join(os12.homedir(), ".exe-os", "intercom.log");
8339
+ DEBOUNCE_FILE = path20.join(SESSION_CACHE, "intercom-debounce.json");
8263
8340
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
8264
8341
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
8265
8342
  }
@@ -8325,13 +8402,13 @@ __export(worker_gate_exports, {
8325
8402
  tryAcquireBackfillLock: () => tryAcquireBackfillLock,
8326
8403
  tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
8327
8404
  });
8328
- import { readdirSync as readdirSync6, writeFileSync as writeFileSync10, unlinkSync as unlinkSync8, mkdirSync as mkdirSync9, existsSync as existsSync17 } from "fs";
8329
- import path21 from "path";
8405
+ import { readdirSync as readdirSync6, writeFileSync as writeFileSync10, unlinkSync as unlinkSync8, mkdirSync as mkdirSync10, existsSync as existsSync18 } from "fs";
8406
+ import path22 from "path";
8330
8407
  function tryAcquireWorkerSlot() {
8331
8408
  try {
8332
- mkdirSync9(WORKER_PID_DIR, { recursive: true });
8409
+ mkdirSync10(WORKER_PID_DIR, { recursive: true });
8333
8410
  const reservationId = `res-${process.pid}-${Date.now()}`;
8334
- const reservationPath = path21.join(WORKER_PID_DIR, `${reservationId}.pid`);
8411
+ const reservationPath = path22.join(WORKER_PID_DIR, `${reservationId}.pid`);
8335
8412
  writeFileSync10(reservationPath, String(process.pid));
8336
8413
  const files = readdirSync6(WORKER_PID_DIR);
8337
8414
  let alive = 0;
@@ -8349,7 +8426,7 @@ function tryAcquireWorkerSlot() {
8349
8426
  alive++;
8350
8427
  } catch {
8351
8428
  try {
8352
- unlinkSync8(path21.join(WORKER_PID_DIR, f));
8429
+ unlinkSync8(path22.join(WORKER_PID_DIR, f));
8353
8430
  } catch {
8354
8431
  }
8355
8432
  }
@@ -8372,21 +8449,21 @@ function tryAcquireWorkerSlot() {
8372
8449
  }
8373
8450
  function registerWorkerPid(pid) {
8374
8451
  try {
8375
- mkdirSync9(WORKER_PID_DIR, { recursive: true });
8376
- writeFileSync10(path21.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
8452
+ mkdirSync10(WORKER_PID_DIR, { recursive: true });
8453
+ writeFileSync10(path22.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
8377
8454
  } catch {
8378
8455
  }
8379
8456
  }
8380
8457
  function cleanupWorkerPid() {
8381
8458
  try {
8382
- unlinkSync8(path21.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
8459
+ unlinkSync8(path22.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
8383
8460
  } catch {
8384
8461
  }
8385
8462
  }
8386
8463
  function tryAcquireBackfillLock() {
8387
8464
  try {
8388
- mkdirSync9(WORKER_PID_DIR, { recursive: true });
8389
- if (existsSync17(BACKFILL_LOCK)) {
8465
+ mkdirSync10(WORKER_PID_DIR, { recursive: true });
8466
+ if (existsSync18(BACKFILL_LOCK)) {
8390
8467
  try {
8391
8468
  const pid = parseInt(
8392
8469
  __require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
@@ -8419,9 +8496,9 @@ var init_worker_gate = __esm({
8419
8496
  "src/lib/worker-gate.ts"() {
8420
8497
  "use strict";
8421
8498
  init_config();
8422
- WORKER_PID_DIR = path21.join(EXE_AI_DIR, "worker-pids");
8499
+ WORKER_PID_DIR = path22.join(EXE_AI_DIR, "worker-pids");
8423
8500
  MAX_CONCURRENT_WORKERS = 3;
8424
- BACKFILL_LOCK = path21.join(WORKER_PID_DIR, "backfill.lock");
8501
+ BACKFILL_LOCK = path22.join(WORKER_PID_DIR, "backfill.lock");
8425
8502
  }
8426
8503
  });
8427
8504
 
@@ -8523,8 +8600,8 @@ __export(crdt_sync_exports, {
8523
8600
  rebuildFromDb: () => rebuildFromDb
8524
8601
  });
8525
8602
  import * as Y from "yjs";
8526
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, existsSync as existsSync18, mkdirSync as mkdirSync10, unlinkSync as unlinkSync9 } from "fs";
8527
- import path22 from "path";
8603
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, existsSync as existsSync19, mkdirSync as mkdirSync11, unlinkSync as unlinkSync9 } from "fs";
8604
+ import path23 from "path";
8528
8605
  import { homedir } from "os";
8529
8606
  function getStatePath() {
8530
8607
  return _statePathOverride ?? DEFAULT_STATE_PATH;
@@ -8536,7 +8613,7 @@ function initCrdtDoc() {
8536
8613
  if (doc) return doc;
8537
8614
  doc = new Y.Doc();
8538
8615
  const sp = getStatePath();
8539
- if (existsSync18(sp)) {
8616
+ if (existsSync19(sp)) {
8540
8617
  try {
8541
8618
  const state = readFileSync14(sp);
8542
8619
  Y.applyUpdate(doc, new Uint8Array(state));
@@ -8680,8 +8757,8 @@ function persistState() {
8680
8757
  if (!doc) return;
8681
8758
  try {
8682
8759
  const sp = getStatePath();
8683
- const dir = path22.dirname(sp);
8684
- if (!existsSync18(dir)) mkdirSync10(dir, { recursive: true });
8760
+ const dir = path23.dirname(sp);
8761
+ if (!existsSync19(dir)) mkdirSync11(dir, { recursive: true });
8685
8762
  const state = Y.encodeStateAsUpdate(doc);
8686
8763
  writeFileSync11(sp, Buffer.from(state));
8687
8764
  } catch {
@@ -8724,7 +8801,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
8724
8801
  var init_crdt_sync = __esm({
8725
8802
  "src/lib/crdt-sync.ts"() {
8726
8803
  "use strict";
8727
- DEFAULT_STATE_PATH = path22.join(homedir(), ".exe-os", "crdt-state.bin");
8804
+ DEFAULT_STATE_PATH = path23.join(homedir(), ".exe-os", "crdt-state.bin");
8728
8805
  _statePathOverride = null;
8729
8806
  doc = null;
8730
8807
  }
@@ -8741,33 +8818,33 @@ __export(db_backup_exports, {
8741
8818
  listBackups: () => listBackups,
8742
8819
  rotateBackups: () => rotateBackups
8743
8820
  });
8744
- import { copyFileSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readdirSync as readdirSync7, unlinkSync as unlinkSync10, statSync as statSync3 } from "fs";
8745
- import path23 from "path";
8821
+ import { copyFileSync, existsSync as existsSync20, mkdirSync as mkdirSync12, readdirSync as readdirSync7, unlinkSync as unlinkSync10, statSync as statSync3 } from "fs";
8822
+ import path24 from "path";
8746
8823
  function findActiveDb() {
8747
8824
  for (const name of DB_NAMES) {
8748
- const p = path23.join(EXE_AI_DIR, name);
8749
- if (existsSync19(p)) return p;
8825
+ const p = path24.join(EXE_AI_DIR, name);
8826
+ if (existsSync20(p)) return p;
8750
8827
  }
8751
8828
  return null;
8752
8829
  }
8753
8830
  function createBackup(reason = "manual") {
8754
8831
  const dbPath = findActiveDb();
8755
8832
  if (!dbPath) return null;
8756
- mkdirSync11(BACKUP_DIR, { recursive: true });
8757
- const dbName = path23.basename(dbPath, ".db");
8833
+ mkdirSync12(BACKUP_DIR, { recursive: true });
8834
+ const dbName = path24.basename(dbPath, ".db");
8758
8835
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
8759
8836
  const backupName = `${dbName}-${reason}-${timestamp}.db`;
8760
- const backupPath = path23.join(BACKUP_DIR, backupName);
8837
+ const backupPath = path24.join(BACKUP_DIR, backupName);
8761
8838
  copyFileSync(dbPath, backupPath);
8762
8839
  const walPath = dbPath + "-wal";
8763
- if (existsSync19(walPath)) {
8840
+ if (existsSync20(walPath)) {
8764
8841
  try {
8765
8842
  copyFileSync(walPath, backupPath + "-wal");
8766
8843
  } catch {
8767
8844
  }
8768
8845
  }
8769
8846
  const shmPath = dbPath + "-shm";
8770
- if (existsSync19(shmPath)) {
8847
+ if (existsSync20(shmPath)) {
8771
8848
  try {
8772
8849
  copyFileSync(shmPath, backupPath + "-shm");
8773
8850
  } catch {
@@ -8776,14 +8853,14 @@ function createBackup(reason = "manual") {
8776
8853
  return backupPath;
8777
8854
  }
8778
8855
  function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
8779
- if (!existsSync19(BACKUP_DIR)) return 0;
8856
+ if (!existsSync20(BACKUP_DIR)) return 0;
8780
8857
  const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
8781
8858
  let deleted = 0;
8782
8859
  try {
8783
8860
  const files = readdirSync7(BACKUP_DIR);
8784
8861
  for (const file of files) {
8785
8862
  if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
8786
- const filePath = path23.join(BACKUP_DIR, file);
8863
+ const filePath = path24.join(BACKUP_DIR, file);
8787
8864
  try {
8788
8865
  const stat = statSync3(filePath);
8789
8866
  if (stat.mtimeMs < cutoff) {
@@ -8798,11 +8875,11 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
8798
8875
  return deleted;
8799
8876
  }
8800
8877
  function listBackups() {
8801
- if (!existsSync19(BACKUP_DIR)) return [];
8878
+ if (!existsSync20(BACKUP_DIR)) return [];
8802
8879
  try {
8803
8880
  const files = readdirSync7(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
8804
8881
  return files.map((name) => {
8805
- const p = path23.join(BACKUP_DIR, name);
8882
+ const p = path24.join(BACKUP_DIR, name);
8806
8883
  const stat = statSync3(p);
8807
8884
  return { path: p, name, size: stat.size, date: stat.mtime };
8808
8885
  }).sort((a, b) => b.date.getTime() - a.date.getTime());
@@ -8827,7 +8904,7 @@ var init_db_backup = __esm({
8827
8904
  "src/lib/db-backup.ts"() {
8828
8905
  "use strict";
8829
8906
  init_config();
8830
- BACKUP_DIR = path23.join(EXE_AI_DIR, "backups");
8907
+ BACKUP_DIR = path24.join(EXE_AI_DIR, "backups");
8831
8908
  DEFAULT_KEEP_DAYS = 3;
8832
8909
  DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
8833
8910
  }
@@ -8862,16 +8939,16 @@ __export(cloud_sync_exports, {
8862
8939
  pushToPostgres: () => pushToPostgres,
8863
8940
  recordRosterDeletion: () => recordRosterDeletion
8864
8941
  });
8865
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync20, readdirSync as readdirSync8, mkdirSync as mkdirSync12, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync4 } from "fs";
8942
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync21, readdirSync as readdirSync8, mkdirSync as mkdirSync13, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync4 } from "fs";
8866
8943
  import crypto8 from "crypto";
8867
- import path24 from "path";
8944
+ import path25 from "path";
8868
8945
  import { homedir as homedir2 } from "os";
8869
8946
  function sqlSafe(v) {
8870
8947
  return v === void 0 ? null : v;
8871
8948
  }
8872
8949
  function logError(msg) {
8873
8950
  try {
8874
- const logPath = path24.join(homedir2(), ".exe-os", "workers.log");
8951
+ const logPath = path25.join(homedir2(), ".exe-os", "workers.log");
8875
8952
  appendFileSync2(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
8876
8953
  `);
8877
8954
  } catch {
@@ -8880,10 +8957,10 @@ function logError(msg) {
8880
8957
  function loadPgClient() {
8881
8958
  if (_pgFailed) return null;
8882
8959
  const postgresUrl = process.env.DATABASE_URL;
8883
- const configPath = path24.join(EXE_AI_DIR, "config.json");
8960
+ const configPath = path25.join(EXE_AI_DIR, "config.json");
8884
8961
  let cloudPostgresUrl;
8885
8962
  try {
8886
- if (existsSync20(configPath)) {
8963
+ if (existsSync21(configPath)) {
8887
8964
  const cfg = JSON.parse(readFileSync15(configPath, "utf8"));
8888
8965
  cloudPostgresUrl = cfg.cloud?.postgresUrl;
8889
8966
  if (cfg.cloud?.syncToPostgres === false) {
@@ -8902,8 +8979,8 @@ function loadPgClient() {
8902
8979
  _pgPromise = (async () => {
8903
8980
  const { createRequire: createRequire3 } = await import("module");
8904
8981
  const { pathToFileURL: pathToFileURL3 } = await import("url");
8905
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path24.join(homedir2(), "exe-db");
8906
- const req = createRequire3(path24.join(exeDbRoot, "package.json"));
8982
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path25.join(homedir2(), "exe-db");
8983
+ const req = createRequire3(path25.join(exeDbRoot, "package.json"));
8907
8984
  const entry = req.resolve("@prisma/client");
8908
8985
  const mod = await import(pathToFileURL3(entry).href);
8909
8986
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -9343,8 +9420,8 @@ async function cloudSync(config) {
9343
9420
  try {
9344
9421
  const employees = await loadEmployees();
9345
9422
  rosterResult.employees = employees.length;
9346
- const idDir = path24.join(EXE_AI_DIR, "identity");
9347
- if (existsSync20(idDir)) {
9423
+ const idDir = path25.join(EXE_AI_DIR, "identity");
9424
+ if (existsSync21(idDir)) {
9348
9425
  rosterResult.identities = readdirSync8(idDir).filter((f) => f.endsWith(".md")).length;
9349
9426
  }
9350
9427
  } catch {
@@ -9365,7 +9442,7 @@ async function cloudSync(config) {
9365
9442
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${config.apiKey}` },
9366
9443
  body: JSON.stringify({
9367
9444
  device_id: deviceId,
9368
- filename: path24.basename(latestBackup),
9445
+ filename: path25.basename(latestBackup),
9369
9446
  blob: encrypted,
9370
9447
  size: backupData.length
9371
9448
  })
@@ -9393,7 +9470,7 @@ async function cloudSync(config) {
9393
9470
  function recordRosterDeletion(name) {
9394
9471
  let deletions = [];
9395
9472
  try {
9396
- if (existsSync20(ROSTER_DELETIONS_PATH)) {
9473
+ if (existsSync21(ROSTER_DELETIONS_PATH)) {
9397
9474
  deletions = JSON.parse(readFileSync15(ROSTER_DELETIONS_PATH, "utf-8"));
9398
9475
  }
9399
9476
  } catch {
@@ -9403,7 +9480,7 @@ function recordRosterDeletion(name) {
9403
9480
  }
9404
9481
  function consumeRosterDeletions() {
9405
9482
  try {
9406
- if (!existsSync20(ROSTER_DELETIONS_PATH)) return [];
9483
+ if (!existsSync21(ROSTER_DELETIONS_PATH)) return [];
9407
9484
  const deletions = JSON.parse(readFileSync15(ROSTER_DELETIONS_PATH, "utf-8"));
9408
9485
  writeFileSync12(ROSTER_DELETIONS_PATH, "[]");
9409
9486
  return deletions;
@@ -9412,35 +9489,35 @@ function consumeRosterDeletions() {
9412
9489
  }
9413
9490
  }
9414
9491
  function buildRosterBlob(paths) {
9415
- const rosterPath = paths?.rosterPath ?? path24.join(EXE_AI_DIR, "exe-employees.json");
9416
- const identityDir = paths?.identityDir ?? path24.join(EXE_AI_DIR, "identity");
9417
- const configPath = paths?.configPath ?? path24.join(EXE_AI_DIR, "config.json");
9492
+ const rosterPath = paths?.rosterPath ?? path25.join(EXE_AI_DIR, "exe-employees.json");
9493
+ const identityDir = paths?.identityDir ?? path25.join(EXE_AI_DIR, "identity");
9494
+ const configPath = paths?.configPath ?? path25.join(EXE_AI_DIR, "config.json");
9418
9495
  let roster = [];
9419
- if (existsSync20(rosterPath)) {
9496
+ if (existsSync21(rosterPath)) {
9420
9497
  try {
9421
9498
  roster = JSON.parse(readFileSync15(rosterPath, "utf-8"));
9422
9499
  } catch {
9423
9500
  }
9424
9501
  }
9425
9502
  const identities = {};
9426
- if (existsSync20(identityDir)) {
9503
+ if (existsSync21(identityDir)) {
9427
9504
  for (const file of readdirSync8(identityDir).filter((f) => f.endsWith(".md"))) {
9428
9505
  try {
9429
- identities[file] = readFileSync15(path24.join(identityDir, file), "utf-8");
9506
+ identities[file] = readFileSync15(path25.join(identityDir, file), "utf-8");
9430
9507
  } catch {
9431
9508
  }
9432
9509
  }
9433
9510
  }
9434
9511
  let config;
9435
- if (existsSync20(configPath)) {
9512
+ if (existsSync21(configPath)) {
9436
9513
  try {
9437
9514
  config = JSON.parse(readFileSync15(configPath, "utf-8"));
9438
9515
  } catch {
9439
9516
  }
9440
9517
  }
9441
9518
  let agentConfig;
9442
- const agentConfigPath = path24.join(EXE_AI_DIR, "agent-config.json");
9443
- if (existsSync20(agentConfigPath)) {
9519
+ const agentConfigPath = path25.join(EXE_AI_DIR, "agent-config.json");
9520
+ if (existsSync21(agentConfigPath)) {
9444
9521
  try {
9445
9522
  agentConfig = JSON.parse(readFileSync15(agentConfigPath, "utf-8"));
9446
9523
  } catch {
@@ -9518,16 +9595,16 @@ async function cloudPullRoster(config) {
9518
9595
  }
9519
9596
  }
9520
9597
  function mergeConfig(remoteConfig, configPath) {
9521
- const cfgPath = configPath ?? path24.join(EXE_AI_DIR, "config.json");
9598
+ const cfgPath = configPath ?? path25.join(EXE_AI_DIR, "config.json");
9522
9599
  let local = {};
9523
- if (existsSync20(cfgPath)) {
9600
+ if (existsSync21(cfgPath)) {
9524
9601
  try {
9525
9602
  local = JSON.parse(readFileSync15(cfgPath, "utf-8"));
9526
9603
  } catch {
9527
9604
  }
9528
9605
  }
9529
9606
  const merged = { ...remoteConfig, ...local };
9530
- const dir = path24.dirname(cfgPath);
9607
+ const dir = path25.dirname(cfgPath);
9531
9608
  ensurePrivateDirSync(dir);
9532
9609
  writeFileSync12(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
9533
9610
  enforcePrivateFileSync(cfgPath);
@@ -9535,7 +9612,7 @@ function mergeConfig(remoteConfig, configPath) {
9535
9612
  async function mergeRosterFromRemote(remote, paths) {
9536
9613
  return withRosterLock(async () => {
9537
9614
  const rosterPath = paths?.rosterPath ?? void 0;
9538
- const identityDir = paths?.identityDir ?? path24.join(EXE_AI_DIR, "identity");
9615
+ const identityDir = paths?.identityDir ?? path25.join(EXE_AI_DIR, "identity");
9539
9616
  const localEmployees = await loadEmployees(rosterPath);
9540
9617
  const localNames = new Set(localEmployees.map((e) => e.name));
9541
9618
  let added = 0;
@@ -9556,11 +9633,11 @@ async function mergeRosterFromRemote(remote, paths) {
9556
9633
  ) ?? lookupKey;
9557
9634
  const remoteIdentity = remote.identities[matchedKey];
9558
9635
  if (remoteIdentity) {
9559
- if (!existsSync20(identityDir)) mkdirSync12(identityDir, { recursive: true });
9560
- const idPath = path24.join(identityDir, `${remoteEmp.name}.md`);
9636
+ if (!existsSync21(identityDir)) mkdirSync13(identityDir, { recursive: true });
9637
+ const idPath = path25.join(identityDir, `${remoteEmp.name}.md`);
9561
9638
  let localIdentity = null;
9562
9639
  try {
9563
- localIdentity = existsSync20(idPath) ? readFileSync15(idPath, "utf-8") : null;
9640
+ localIdentity = existsSync21(idPath) ? readFileSync15(idPath, "utf-8") : null;
9564
9641
  } catch {
9565
9642
  }
9566
9643
  if (localIdentity !== remoteIdentity) {
@@ -9590,16 +9667,16 @@ async function mergeRosterFromRemote(remote, paths) {
9590
9667
  }
9591
9668
  if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
9592
9669
  try {
9593
- const agentConfigPath = path24.join(EXE_AI_DIR, "agent-config.json");
9670
+ const agentConfigPath = path25.join(EXE_AI_DIR, "agent-config.json");
9594
9671
  let local = {};
9595
- if (existsSync20(agentConfigPath)) {
9672
+ if (existsSync21(agentConfigPath)) {
9596
9673
  try {
9597
9674
  local = JSON.parse(readFileSync15(agentConfigPath, "utf-8"));
9598
9675
  } catch {
9599
9676
  }
9600
9677
  }
9601
9678
  const merged = { ...remote.agentConfig, ...local };
9602
- ensurePrivateDirSync(path24.dirname(agentConfigPath));
9679
+ ensurePrivateDirSync(path25.dirname(agentConfigPath));
9603
9680
  writeFileSync12(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
9604
9681
  enforcePrivateFileSync(agentConfigPath);
9605
9682
  } catch {
@@ -10040,11 +10117,11 @@ var init_cloud_sync = __esm({
10040
10117
  LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
10041
10118
  FETCH_TIMEOUT_MS = 3e4;
10042
10119
  PUSH_BATCH_SIZE = 5e3;
10043
- ROSTER_LOCK_PATH = path24.join(EXE_AI_DIR, "roster-merge.lock");
10120
+ ROSTER_LOCK_PATH = path25.join(EXE_AI_DIR, "roster-merge.lock");
10044
10121
  LOCK_STALE_MS = 3e4;
10045
10122
  _pgPromise = null;
10046
10123
  _pgFailed = false;
10047
- ROSTER_DELETIONS_PATH = path24.join(EXE_AI_DIR, "roster-deletions.json");
10124
+ ROSTER_DELETIONS_PATH = path25.join(EXE_AI_DIR, "roster-deletions.json");
10048
10125
  }
10049
10126
  });
10050
10127
 
@@ -10248,10 +10325,10 @@ var init_schedules = __esm({
10248
10325
 
10249
10326
  // src/bin/exe-boot.ts
10250
10327
  init_employees();
10251
- import path25 from "path";
10328
+ import path26 from "path";
10252
10329
  import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
10253
- import { existsSync as existsSync21, readFileSync as readFileSync16, readdirSync as readdirSync9, unlinkSync as unlinkSync12 } from "fs";
10254
- import os12 from "os";
10330
+ import { existsSync as existsSync22, readFileSync as readFileSync16, readdirSync as readdirSync9, unlinkSync as unlinkSync12 } from "fs";
10331
+ import os13 from "os";
10255
10332
 
10256
10333
  // src/lib/employee-templates.ts
10257
10334
  init_global_procedures();
@@ -10753,9 +10830,9 @@ init_notifications();
10753
10830
  // src/lib/active-agent.ts
10754
10831
  init_config();
10755
10832
  init_session_key();
10756
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7, readdirSync as readdirSync5 } from "fs";
10833
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7, readdirSync as readdirSync5 } from "fs";
10757
10834
  import { execSync as execSync9 } from "child_process";
10758
- import path20 from "path";
10835
+ import path21 from "path";
10759
10836
 
10760
10837
  // src/mcp/agent-context.ts
10761
10838
  import { AsyncLocalStorage } from "async_hooks";
@@ -10763,14 +10840,14 @@ var agentStore = new AsyncLocalStorage();
10763
10840
 
10764
10841
  // src/lib/active-agent.ts
10765
10842
  init_employees();
10766
- var CACHE_DIR = path20.join(EXE_AI_DIR, "session-cache");
10843
+ var CACHE_DIR = path21.join(EXE_AI_DIR, "session-cache");
10767
10844
  var STALE_MS = 24 * 60 * 60 * 1e3;
10768
10845
  function getMarkerPath() {
10769
- return path20.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
10846
+ return path21.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
10770
10847
  }
10771
10848
  function writeActiveAgent(agentId, agentRole) {
10772
10849
  try {
10773
- mkdirSync8(CACHE_DIR, { recursive: true });
10850
+ mkdirSync9(CACHE_DIR, { recursive: true });
10774
10851
  writeFileSync9(
10775
10852
  getMarkerPath(),
10776
10853
  JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
@@ -10781,11 +10858,11 @@ function writeActiveAgent(agentId, agentRole) {
10781
10858
  function cleanupSessionMarkers() {
10782
10859
  const key = getSessionKey();
10783
10860
  try {
10784
- unlinkSync7(path20.join(CACHE_DIR, `active-agent-${key}.json`));
10861
+ unlinkSync7(path21.join(CACHE_DIR, `active-agent-${key}.json`));
10785
10862
  } catch {
10786
10863
  }
10787
10864
  try {
10788
- unlinkSync7(path20.join(CACHE_DIR, "active-agent-undefined.json"));
10865
+ unlinkSync7(path21.join(CACHE_DIR, "active-agent-undefined.json"));
10789
10866
  } catch {
10790
10867
  }
10791
10868
  }
@@ -10875,7 +10952,7 @@ async function boot(options) {
10875
10952
  const employeeDirs = entries.filter((e) => e.isDirectory() && !["output", "research"].includes(e.name));
10876
10953
  for (const dir of employeeDirs) {
10877
10954
  const employee = dir.name;
10878
- const taskDir = path25.join(exeDir, employee);
10955
+ const taskDir = path26.join(exeDir, employee);
10879
10956
  let files;
10880
10957
  try {
10881
10958
  files = readdirSync10(taskDir).filter((f) => f.endsWith(".md"));
@@ -10886,7 +10963,7 @@ async function boot(options) {
10886
10963
  const taskFilePath = `exe/${employee}/${file}`;
10887
10964
  let content;
10888
10965
  try {
10889
- content = readFs(path25.join(taskDir, file), "utf8");
10966
+ content = readFs(path26.join(taskDir, file), "utf8");
10890
10967
  } catch {
10891
10968
  continue;
10892
10969
  }
@@ -10972,12 +11049,12 @@ async function boot(options) {
10972
11049
  }
10973
11050
  try {
10974
11051
  for (const reviewDirName of /* @__PURE__ */ new Set(["exe", coordinatorName])) {
10975
- const reviewDir = path25.join(process.cwd(), "exe", reviewDirName);
10976
- if (existsSync21(reviewDir)) {
11052
+ const reviewDir = path26.join(process.cwd(), "exe", reviewDirName);
11053
+ if (existsSync22(reviewDir)) {
10977
11054
  for (const f of readdirSync9(reviewDir)) {
10978
11055
  if (f.startsWith("review-") && f.endsWith(".md")) {
10979
11056
  try {
10980
- unlinkSync12(path25.join(reviewDir, f));
11057
+ unlinkSync12(path26.join(reviewDir, f));
10981
11058
  } catch {
10982
11059
  }
10983
11060
  }
@@ -11023,8 +11100,8 @@ async function boot(options) {
11023
11100
  });
11024
11101
  const taskFile = String(r.task_file);
11025
11102
  try {
11026
- const filePath = path25.join(process.cwd(), taskFile);
11027
- if (existsSync21(filePath)) {
11103
+ const filePath = path26.join(process.cwd(), taskFile);
11104
+ if (existsSync22(filePath)) {
11028
11105
  let content = readFileSync16(filePath, "utf8");
11029
11106
  content = content.replace(/\*\*Status:\*\* needs_review/, "**Status:** done");
11030
11107
  const { writeFileSync: writeFileSync13 } = await import("fs");
@@ -11522,19 +11599,19 @@ async function boot(options) {
11522
11599
  })()
11523
11600
  ]);
11524
11601
  try {
11525
- const configPath = path25.join(
11526
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path25.join(os12.homedir(), ".exe-os"),
11602
+ const configPath = path26.join(
11603
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path26.join(os13.homedir(), ".exe-os"),
11527
11604
  "config.json"
11528
11605
  );
11529
- if (existsSync21(configPath)) {
11606
+ if (existsSync22(configPath)) {
11530
11607
  const raw = JSON.parse(readFileSync16(configPath, "utf8"));
11531
11608
  briefData.cloudConnected = !!(raw.cloud || raw.turso);
11532
11609
  }
11533
11610
  } catch {
11534
11611
  }
11535
11612
  try {
11536
- const backfillFlagPath = path25.join(EXE_AI_DIR, "session-cache", "needs-backfill");
11537
- const isBackfillNeeded = () => existsSync21(backfillFlagPath);
11613
+ const backfillFlagPath = path26.join(EXE_AI_DIR, "session-cache", "needs-backfill");
11614
+ const isBackfillNeeded = () => existsSync22(backfillFlagPath);
11538
11615
  const coverageResult = await client.execute({
11539
11616
  sql: `SELECT COUNT(*) as total,
11540
11617
  SUM(CASE WHEN vector IS NOT NULL THEN 1 ELSE 0 END) as with_vectors
@@ -11556,8 +11633,8 @@ async function boot(options) {
11556
11633
  let daemonRunning = false;
11557
11634
  let daemonUptime;
11558
11635
  let daemonRequestsServed;
11559
- const socketPath = path25.join(EXE_AI_DIR, "exed.sock");
11560
- if (existsSync21(socketPath)) {
11636
+ const socketPath = path26.join(EXE_AI_DIR, "exed.sock");
11637
+ if (existsSync22(socketPath)) {
11561
11638
  try {
11562
11639
  const net2 = await import("net");
11563
11640
  const health = await new Promise((resolve) => {
@@ -11599,8 +11676,8 @@ async function boot(options) {
11599
11676
  }
11600
11677
  }
11601
11678
  if (!daemonRunning) {
11602
- const pidPath = path25.join(EXE_AI_DIR, "exed.pid");
11603
- if (existsSync21(pidPath)) {
11679
+ const pidPath = path26.join(EXE_AI_DIR, "exed.pid");
11680
+ if (existsSync22(pidPath)) {
11604
11681
  try {
11605
11682
  const pid = parseInt(readFileSync16(pidPath, "utf8").trim(), 10);
11606
11683
  if (pid > 0) {
@@ -11613,8 +11690,8 @@ async function boot(options) {
11613
11690
  }
11614
11691
  if (nullCount === 0) {
11615
11692
  try {
11616
- const flagPath = path25.join(EXE_AI_DIR, "session-cache", "needs-backfill");
11617
- if (existsSync21(flagPath)) {
11693
+ const flagPath = path26.join(EXE_AI_DIR, "session-cache", "needs-backfill");
11694
+ if (existsSync22(flagPath)) {
11618
11695
  const { unlinkSync: unlinkSync13 } = await import("fs");
11619
11696
  unlinkSync13(flagPath);
11620
11697
  }
@@ -11640,10 +11717,10 @@ async function boot(options) {
11640
11717
  const { spawn: spawn2 } = await import("child_process");
11641
11718
  const { fileURLToPath: fileURLToPath4 } = await import("url");
11642
11719
  const thisFile = fileURLToPath4(import.meta.url);
11643
- const backfillPath = path25.resolve(path25.dirname(thisFile), "backfill-vectors.js");
11644
- if (existsSync21(backfillPath)) {
11720
+ const backfillPath = path26.resolve(path26.dirname(thisFile), "backfill-vectors.js");
11721
+ if (existsSync22(backfillPath)) {
11645
11722
  const { openSync: openSync3, closeSync: closeSync3 } = await import("fs");
11646
- const workerLogPath = path25.join(EXE_AI_DIR, "workers.log");
11723
+ const workerLogPath = path26.join(EXE_AI_DIR, "workers.log");
11647
11724
  let stderrFd = "ignore";
11648
11725
  try {
11649
11726
  stderrFd = openSync3(workerLogPath, "a");
@@ -11673,8 +11750,8 @@ async function boot(options) {
11673
11750
  const criticalBinaries = ["backfill-vectors.js", "scan-tasks.js"];
11674
11751
  const missing = [];
11675
11752
  for (const bin of criticalBinaries) {
11676
- const binPath = path25.resolve(path25.dirname(thisFile), bin);
11677
- if (!existsSync21(binPath)) {
11753
+ const binPath = path26.resolve(path26.dirname(thisFile), bin);
11754
+ if (!existsSync22(binPath)) {
11678
11755
  missing.push(`dist/bin/${bin}`);
11679
11756
  }
11680
11757
  }
@@ -11703,10 +11780,10 @@ async function boot(options) {
11703
11780
  console.log(brief);
11704
11781
  return;
11705
11782
  }
11706
- const sessionDir = path25.join(EXE_AI_DIR, "sessions", coordinatorName);
11783
+ const sessionDir = path26.join(EXE_AI_DIR, "sessions", coordinatorName);
11707
11784
  await mkdir5(sessionDir, { recursive: true });
11708
- const coordinatorIdentityPath = path25.join(EXE_AI_DIR, "identity", `${coordinatorName}.md`);
11709
- const coordinatorPrompt = existsSync21(coordinatorIdentityPath) ? readFileSync16(coordinatorIdentityPath, "utf-8") : coordinatorEmployee.systemPrompt ?? "";
11785
+ const coordinatorIdentityPath = path26.join(EXE_AI_DIR, "identity", `${coordinatorName}.md`);
11786
+ const coordinatorPrompt = existsSync22(coordinatorIdentityPath) ? readFileSync16(coordinatorIdentityPath, "utf-8") : coordinatorEmployee.systemPrompt ?? "";
11710
11787
  const claudeMdContent = `${getSessionPrompt(coordinatorPrompt)}
11711
11788
 
11712
11789
  ---
@@ -11714,7 +11791,7 @@ async function boot(options) {
11714
11791
  # Status Brief
11715
11792
 
11716
11793
  ${brief}`;
11717
- await writeFile6(path25.join(sessionDir, "CLAUDE.md"), claudeMdContent, "utf-8");
11794
+ await writeFile6(path26.join(sessionDir, "CLAUDE.md"), claudeMdContent, "utf-8");
11718
11795
  const unread = await readUnreadNotifications();
11719
11796
  if (unread.length > 0) {
11720
11797
  console.log(`\u{1F4EC} ${unread.length} unread notification${unread.length === 1 ? "" : "s"}`);
@@ -11723,11 +11800,11 @@ ${brief}`;
11723
11800
  await cleanupOldNotifications();
11724
11801
  console.log(brief);
11725
11802
  try {
11726
- const configPath2 = path25.join(
11727
- process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path25.join(os12.homedir(), ".exe-os"),
11803
+ const configPath2 = path26.join(
11804
+ process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path26.join(os13.homedir(), ".exe-os"),
11728
11805
  "config.json"
11729
11806
  );
11730
- if (existsSync21(configPath2)) {
11807
+ if (existsSync22(configPath2)) {
11731
11808
  const rawCfg = JSON.parse(readFileSync16(configPath2, "utf8"));
11732
11809
  const cloudCfg = rawCfg.cloud;
11733
11810
  if (cloudCfg?.apiKey) {