@askexenow/exe-os 0.9.6 → 0.9.8

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 (95) hide show
  1. package/dist/bin/backfill-conversations.js +754 -79
  2. package/dist/bin/backfill-responses.js +752 -77
  3. package/dist/bin/backfill-vectors.js +752 -77
  4. package/dist/bin/cleanup-stale-review-tasks.js +668 -37
  5. package/dist/bin/cli.js +1399 -607
  6. package/dist/bin/exe-agent-config.js +123 -95
  7. package/dist/bin/exe-agent.js +41 -25
  8. package/dist/bin/exe-assign.js +732 -57
  9. package/dist/bin/exe-boot.js +795 -155
  10. package/dist/bin/exe-call.js +209 -138
  11. package/dist/bin/exe-cloud.js +35 -12
  12. package/dist/bin/exe-dispatch.js +703 -72
  13. package/dist/bin/exe-doctor.js +648 -26
  14. package/dist/bin/exe-export-behaviors.js +650 -20
  15. package/dist/bin/exe-forget.js +635 -13
  16. package/dist/bin/exe-gateway.js +1064 -273
  17. package/dist/bin/exe-heartbeat.js +676 -45
  18. package/dist/bin/exe-kill.js +646 -16
  19. package/dist/bin/exe-launch-agent.js +887 -97
  20. package/dist/bin/exe-link.js +658 -43
  21. package/dist/bin/exe-new-employee.js +378 -177
  22. package/dist/bin/exe-pending-messages.js +656 -34
  23. package/dist/bin/exe-pending-notifications.js +635 -13
  24. package/dist/bin/exe-pending-reviews.js +659 -37
  25. package/dist/bin/exe-rename.js +645 -30
  26. package/dist/bin/exe-review.js +635 -13
  27. package/dist/bin/exe-search.js +771 -88
  28. package/dist/bin/exe-session-cleanup.js +845 -152
  29. package/dist/bin/exe-settings.js +127 -91
  30. package/dist/bin/exe-start-codex.js +729 -94
  31. package/dist/bin/exe-start-opencode.js +717 -82
  32. package/dist/bin/exe-status.js +668 -37
  33. package/dist/bin/exe-team.js +635 -13
  34. package/dist/bin/git-sweep.js +731 -91
  35. package/dist/bin/graph-backfill.js +643 -13
  36. package/dist/bin/graph-export.js +646 -16
  37. package/dist/bin/install.js +596 -193
  38. package/dist/bin/scan-tasks.js +735 -95
  39. package/dist/bin/setup.js +1038 -210
  40. package/dist/bin/shard-migrate.js +645 -15
  41. package/dist/bin/wiki-sync.js +646 -16
  42. package/dist/gateway/index.js +1038 -247
  43. package/dist/hooks/bug-report-worker.js +902 -172
  44. package/dist/hooks/commit-complete.js +729 -89
  45. package/dist/hooks/error-recall.js +776 -93
  46. package/dist/hooks/exe-heartbeat-hook.js +85 -71
  47. package/dist/hooks/ingest-worker.js +851 -158
  48. package/dist/hooks/ingest.js +90 -73
  49. package/dist/hooks/instructions-loaded.js +669 -38
  50. package/dist/hooks/notification.js +661 -30
  51. package/dist/hooks/post-compact.js +685 -45
  52. package/dist/hooks/pre-compact.js +729 -89
  53. package/dist/hooks/pre-tool-use.js +883 -127
  54. package/dist/hooks/prompt-ingest-worker.js +758 -83
  55. package/dist/hooks/prompt-submit.js +1071 -321
  56. package/dist/hooks/response-ingest-worker.js +758 -83
  57. package/dist/hooks/session-end.js +732 -92
  58. package/dist/hooks/session-start.js +1042 -209
  59. package/dist/hooks/stop.js +691 -51
  60. package/dist/hooks/subagent-stop.js +685 -45
  61. package/dist/hooks/summary-worker.js +827 -134
  62. package/dist/index.js +1026 -234
  63. package/dist/lib/cloud-sync.js +663 -48
  64. package/dist/lib/consolidation.js +26 -3
  65. package/dist/lib/database.js +626 -18
  66. package/dist/lib/db.js +2261 -0
  67. package/dist/lib/device-registry.js +640 -25
  68. package/dist/lib/embedder.js +96 -43
  69. package/dist/lib/employee-templates.js +16 -0
  70. package/dist/lib/employees.js +259 -83
  71. package/dist/lib/exe-daemon-client.js +101 -63
  72. package/dist/lib/exe-daemon.js +905 -164
  73. package/dist/lib/hybrid-search.js +771 -88
  74. package/dist/lib/identity.js +27 -7
  75. package/dist/lib/messaging.js +66 -30
  76. package/dist/lib/reminders.js +21 -1
  77. package/dist/lib/schedules.js +636 -14
  78. package/dist/lib/skill-learning.js +21 -1
  79. package/dist/lib/store.js +643 -13
  80. package/dist/lib/task-router.js +82 -71
  81. package/dist/lib/tasks.js +109 -73
  82. package/dist/lib/tmux-routing.js +98 -62
  83. package/dist/lib/token-spend.js +26 -6
  84. package/dist/mcp/server.js +1807 -472
  85. package/dist/mcp/tools/complete-reminder.js +21 -1
  86. package/dist/mcp/tools/create-reminder.js +21 -1
  87. package/dist/mcp/tools/create-task.js +301 -166
  88. package/dist/mcp/tools/deactivate-behavior.js +24 -4
  89. package/dist/mcp/tools/list-reminders.js +21 -1
  90. package/dist/mcp/tools/list-tasks.js +206 -40
  91. package/dist/mcp/tools/send-message.js +69 -33
  92. package/dist/mcp/tools/update-task.js +86 -50
  93. package/dist/runtime/index.js +731 -91
  94. package/dist/tui/App.js +864 -125
  95. package/package.json +3 -2
@@ -272,6 +272,118 @@ var init_config = __esm({
272
272
  }
273
273
  });
274
274
 
275
+ // src/lib/runtime-table.ts
276
+ var RUNTIME_TABLE, DEFAULT_RUNTIME;
277
+ var init_runtime_table = __esm({
278
+ "src/lib/runtime-table.ts"() {
279
+ "use strict";
280
+ RUNTIME_TABLE = {
281
+ codex: {
282
+ binary: "codex",
283
+ launchMode: "interactive",
284
+ autoApproveFlag: "--dangerously-bypass-approvals-and-sandbox",
285
+ inlineFlag: "--no-alt-screen",
286
+ apiKeyEnv: "OPENAI_API_KEY",
287
+ defaultModel: "gpt-5.4"
288
+ },
289
+ opencode: {
290
+ binary: "opencode",
291
+ launchMode: "exec",
292
+ autoApproveFlag: "--dangerously-skip-permissions",
293
+ inlineFlag: "",
294
+ apiKeyEnv: "ANTHROPIC_API_KEY",
295
+ defaultModel: "anthropic/claude-sonnet-4-6"
296
+ }
297
+ };
298
+ DEFAULT_RUNTIME = "claude";
299
+ }
300
+ });
301
+
302
+ // src/lib/agent-config.ts
303
+ var agent_config_exports = {};
304
+ __export(agent_config_exports, {
305
+ AGENT_CONFIG_PATH: () => AGENT_CONFIG_PATH,
306
+ DEFAULT_MODELS: () => DEFAULT_MODELS,
307
+ KNOWN_RUNTIMES: () => KNOWN_RUNTIMES,
308
+ RUNTIME_LABELS: () => RUNTIME_LABELS,
309
+ clearAgentRuntime: () => clearAgentRuntime,
310
+ getAgentRuntime: () => getAgentRuntime,
311
+ loadAgentConfig: () => loadAgentConfig,
312
+ saveAgentConfig: () => saveAgentConfig,
313
+ setAgentRuntime: () => setAgentRuntime
314
+ });
315
+ import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
316
+ import path2 from "path";
317
+ function loadAgentConfig() {
318
+ if (!existsSync2(AGENT_CONFIG_PATH)) return {};
319
+ try {
320
+ return JSON.parse(readFileSync2(AGENT_CONFIG_PATH, "utf-8"));
321
+ } catch {
322
+ return {};
323
+ }
324
+ }
325
+ function saveAgentConfig(config) {
326
+ const dir = path2.dirname(AGENT_CONFIG_PATH);
327
+ if (!existsSync2(dir)) mkdirSync(dir, { recursive: true });
328
+ writeFileSync(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
329
+ }
330
+ function getAgentRuntime(agentId) {
331
+ const config = loadAgentConfig();
332
+ const entry = config[agentId];
333
+ if (entry) return entry;
334
+ const orgDefault = config["default"];
335
+ if (orgDefault) return orgDefault;
336
+ return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
337
+ }
338
+ function setAgentRuntime(agentId, runtime, model) {
339
+ const knownModels = KNOWN_RUNTIMES[runtime];
340
+ if (!knownModels) {
341
+ return {
342
+ ok: false,
343
+ error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
344
+ };
345
+ }
346
+ if (!knownModels.includes(model)) {
347
+ return {
348
+ ok: false,
349
+ error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
350
+ };
351
+ }
352
+ const config = loadAgentConfig();
353
+ config[agentId] = { runtime, model };
354
+ saveAgentConfig(config);
355
+ return { ok: true };
356
+ }
357
+ function clearAgentRuntime(agentId) {
358
+ const config = loadAgentConfig();
359
+ delete config[agentId];
360
+ saveAgentConfig(config);
361
+ }
362
+ var AGENT_CONFIG_PATH, KNOWN_RUNTIMES, RUNTIME_LABELS, DEFAULT_MODELS;
363
+ var init_agent_config = __esm({
364
+ "src/lib/agent-config.ts"() {
365
+ "use strict";
366
+ init_config();
367
+ init_runtime_table();
368
+ AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
369
+ KNOWN_RUNTIMES = {
370
+ claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
371
+ codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
372
+ opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
373
+ };
374
+ RUNTIME_LABELS = {
375
+ claude: "Claude Code (Anthropic)",
376
+ codex: "Codex (OpenAI)",
377
+ opencode: "OpenCode (open source)"
378
+ };
379
+ DEFAULT_MODELS = {
380
+ claude: "claude-opus-4",
381
+ codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
382
+ opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
383
+ };
384
+ }
385
+ });
386
+
275
387
  // src/lib/employees.ts
276
388
  var employees_exports = {};
277
389
  __export(employees_exports, {
@@ -287,6 +399,7 @@ __export(employees_exports, {
287
399
  getEmployeeByRole: () => getEmployeeByRole,
288
400
  getEmployeeNamesByRole: () => getEmployeeNamesByRole,
289
401
  hasRole: () => hasRole,
402
+ hireEmployee: () => hireEmployee,
290
403
  isCoordinatorName: () => isCoordinatorName,
291
404
  isCoordinatorRole: () => isCoordinatorRole,
292
405
  isMultiInstance: () => isMultiInstance,
@@ -299,9 +412,9 @@ __export(employees_exports, {
299
412
  validateEmployeeName: () => validateEmployeeName
300
413
  });
301
414
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
302
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
415
+ import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
303
416
  import { execSync } from "child_process";
304
- import path2 from "path";
417
+ import path3 from "path";
305
418
  import os2 from "os";
306
419
  function normalizeRole(role) {
307
420
  return (role ?? "").trim().toLowerCase();
@@ -338,7 +451,7 @@ function validateEmployeeName(name) {
338
451
  return { valid: true };
339
452
  }
340
453
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
341
- if (!existsSync2(employeesPath)) {
454
+ if (!existsSync3(employeesPath)) {
342
455
  return [];
343
456
  }
344
457
  const raw = await readFile2(employeesPath, "utf-8");
@@ -349,13 +462,13 @@ async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
349
462
  }
350
463
  }
351
464
  async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
352
- await mkdir2(path2.dirname(employeesPath), { recursive: true });
465
+ await mkdir2(path3.dirname(employeesPath), { recursive: true });
353
466
  await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
354
467
  }
355
468
  function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
356
- if (!existsSync2(employeesPath)) return [];
469
+ if (!existsSync3(employeesPath)) return [];
357
470
  try {
358
- return JSON.parse(readFileSync2(employeesPath, "utf-8"));
471
+ return JSON.parse(readFileSync3(employeesPath, "utf-8"));
359
472
  } catch {
360
473
  return [];
361
474
  }
@@ -397,6 +510,52 @@ function addEmployee(employees, employee) {
397
510
  }
398
511
  return [...employees, normalized];
399
512
  }
513
+ function appendToCoordinatorTeam(employee) {
514
+ const coordinator = getCoordinatorEmployee(loadEmployeesSync());
515
+ if (!coordinator) return;
516
+ const idPath = path3.join(IDENTITY_DIR, `${coordinator.name}.md`);
517
+ if (!existsSync3(idPath)) return;
518
+ const content = readFileSync3(idPath, "utf-8");
519
+ if (content.includes(`**${capitalize(employee.name)}`)) return;
520
+ const teamMatch = content.match(TEAM_SECTION_RE);
521
+ if (!teamMatch || teamMatch.index === void 0) return;
522
+ const afterTeam = content.slice(teamMatch.index + teamMatch[0].length);
523
+ const nextHeading = afterTeam.match(/\n## /);
524
+ const entry = `
525
+ **${capitalize(employee.name)} (${employee.role}):** Newly hired. Update this description as the role develops.
526
+ `;
527
+ let updated;
528
+ if (nextHeading && nextHeading.index !== void 0) {
529
+ const insertAt = teamMatch.index + teamMatch[0].length + nextHeading.index;
530
+ updated = content.slice(0, insertAt) + entry + content.slice(insertAt);
531
+ } else {
532
+ updated = content.trimEnd() + "\n" + entry;
533
+ }
534
+ writeFileSync2(idPath, updated, "utf-8");
535
+ }
536
+ function capitalize(s) {
537
+ return s.charAt(0).toUpperCase() + s.slice(1);
538
+ }
539
+ async function hireEmployee(employee) {
540
+ const employees = await loadEmployees();
541
+ const updated = addEmployee(employees, employee);
542
+ await saveEmployees(updated);
543
+ try {
544
+ appendToCoordinatorTeam(employee);
545
+ } catch {
546
+ }
547
+ try {
548
+ const { loadAgentConfig: loadAgentConfig2, saveAgentConfig: saveAgentConfig2 } = await Promise.resolve().then(() => (init_agent_config(), agent_config_exports));
549
+ const config = loadAgentConfig2();
550
+ const name = employee.name.toLowerCase();
551
+ if (!config[name] && config["default"]) {
552
+ config[name] = { ...config["default"] };
553
+ saveAgentConfig2(config);
554
+ }
555
+ } catch {
556
+ }
557
+ return updated;
558
+ }
400
559
  async function normalizeRosterCase(rosterPath) {
401
560
  const employees = await loadEmployees(rosterPath);
402
561
  let changed = false;
@@ -406,14 +565,14 @@ async function normalizeRosterCase(rosterPath) {
406
565
  emp.name = emp.name.toLowerCase();
407
566
  changed = true;
408
567
  try {
409
- const identityDir = path2.join(os2.homedir(), ".exe-os", "identity");
410
- const oldPath = path2.join(identityDir, `${oldName}.md`);
411
- const newPath = path2.join(identityDir, `${emp.name}.md`);
412
- if (existsSync2(oldPath) && !existsSync2(newPath)) {
568
+ const identityDir = path3.join(os2.homedir(), ".exe-os", "identity");
569
+ const oldPath = path3.join(identityDir, `${oldName}.md`);
570
+ const newPath = path3.join(identityDir, `${emp.name}.md`);
571
+ if (existsSync3(oldPath) && !existsSync3(newPath)) {
413
572
  renameSync2(oldPath, newPath);
414
- } else if (existsSync2(oldPath) && oldPath !== newPath) {
415
- const content = readFileSync2(oldPath, "utf-8");
416
- writeFileSync(newPath, content, "utf-8");
573
+ } else if (existsSync3(oldPath) && oldPath !== newPath) {
574
+ const content = readFileSync3(oldPath, "utf-8");
575
+ writeFileSync2(newPath, content, "utf-8");
417
576
  if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
418
577
  unlinkSync(oldPath);
419
578
  }
@@ -443,7 +602,7 @@ function registerBinSymlinks(name) {
443
602
  errors.push("Could not find 'exe-os' in PATH");
444
603
  return { created, skipped, errors };
445
604
  }
446
- const binDir = path2.dirname(exeBinPath);
605
+ const binDir = path3.dirname(exeBinPath);
447
606
  let target;
448
607
  try {
449
608
  target = readlinkSync(exeBinPath);
@@ -453,8 +612,8 @@ function registerBinSymlinks(name) {
453
612
  }
454
613
  for (const suffix of ["", "-opencode"]) {
455
614
  const linkName = `${name}${suffix}`;
456
- const linkPath = path2.join(binDir, linkName);
457
- if (existsSync2(linkPath)) {
615
+ const linkPath = path3.join(binDir, linkName);
616
+ if (existsSync3(linkPath)) {
458
617
  skipped.push(linkName);
459
618
  continue;
460
619
  }
@@ -467,24 +626,50 @@ function registerBinSymlinks(name) {
467
626
  }
468
627
  return { created, skipped, errors };
469
628
  }
470
- var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES;
629
+ var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES, IDENTITY_DIR, TEAM_SECTION_RE;
471
630
  var init_employees = __esm({
472
631
  "src/lib/employees.ts"() {
473
632
  "use strict";
474
633
  init_config();
475
- EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
634
+ EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
476
635
  DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
477
636
  COORDINATOR_ROLE = "COO";
478
637
  MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
638
+ IDENTITY_DIR = path3.join(EXE_AI_DIR, "identity");
639
+ TEAM_SECTION_RE = /^## Team\b.*$/m;
640
+ }
641
+ });
642
+
643
+ // src/lib/database-adapter.ts
644
+ import os3 from "os";
645
+ import path4 from "path";
646
+ import { createRequire } from "module";
647
+ import { pathToFileURL } from "url";
648
+ var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
649
+ var init_database_adapter = __esm({
650
+ "src/lib/database-adapter.ts"() {
651
+ "use strict";
652
+ BOOLEAN_COLUMNS_BY_TABLE = {
653
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
654
+ behaviors: /* @__PURE__ */ new Set(["active"]),
655
+ notifications: /* @__PURE__ */ new Set(["read"]),
656
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
657
+ };
658
+ BOOLEAN_COLUMN_NAMES = new Set(
659
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
660
+ );
479
661
  }
480
662
  });
481
663
 
482
664
  // src/lib/database.ts
483
665
  import { createClient } from "@libsql/client";
484
666
  function getClient() {
485
- if (!_resilientClient) {
667
+ if (!_adapterClient) {
486
668
  throw new Error("Database client not initialized. Call initDatabase() first.");
487
669
  }
670
+ if (process.env.DATABASE_URL) {
671
+ return _adapterClient;
672
+ }
488
673
  if (process.env.EXE_IS_DAEMON === "1") {
489
674
  return _resilientClient;
490
675
  }
@@ -493,26 +678,28 @@ function getClient() {
493
678
  }
494
679
  return _resilientClient;
495
680
  }
496
- var _resilientClient, _daemonClient;
681
+ var _resilientClient, _daemonClient, _adapterClient;
497
682
  var init_database = __esm({
498
683
  "src/lib/database.ts"() {
499
684
  "use strict";
500
685
  init_db_retry();
501
686
  init_employees();
687
+ init_database_adapter();
502
688
  _resilientClient = null;
503
689
  _daemonClient = null;
690
+ _adapterClient = null;
504
691
  }
505
692
  });
506
693
 
507
694
  // src/lib/notifications.ts
508
695
  import crypto from "crypto";
509
- import path3 from "path";
510
- import os3 from "os";
696
+ import path5 from "path";
697
+ import os4 from "os";
511
698
  import {
512
- readFileSync as readFileSync3,
699
+ readFileSync as readFileSync4,
513
700
  readdirSync,
514
701
  unlinkSync as unlinkSync2,
515
- existsSync as existsSync3,
702
+ existsSync as existsSync4,
516
703
  rmdirSync
517
704
  } from "fs";
518
705
  async function writeNotification(notification) {
@@ -612,13 +799,13 @@ var init_state_bus = __esm({
612
799
  });
613
800
 
614
801
  // src/lib/session-registry.ts
615
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync4 } from "fs";
616
- import path4 from "path";
617
- import os4 from "os";
802
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync5 } from "fs";
803
+ import path6 from "path";
804
+ import os5 from "os";
618
805
  function registerSession(entry) {
619
- const dir = path4.dirname(REGISTRY_PATH);
620
- if (!existsSync4(dir)) {
621
- mkdirSync(dir, { recursive: true });
806
+ const dir = path6.dirname(REGISTRY_PATH);
807
+ if (!existsSync5(dir)) {
808
+ mkdirSync2(dir, { recursive: true });
622
809
  }
623
810
  const sessions = listSessions();
624
811
  const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
@@ -627,11 +814,11 @@ function registerSession(entry) {
627
814
  } else {
628
815
  sessions.push(entry);
629
816
  }
630
- writeFileSync2(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
817
+ writeFileSync3(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
631
818
  }
632
819
  function listSessions() {
633
820
  try {
634
- const raw = readFileSync4(REGISTRY_PATH, "utf8");
821
+ const raw = readFileSync5(REGISTRY_PATH, "utf8");
635
822
  return JSON.parse(raw);
636
823
  } catch {
637
824
  return [];
@@ -641,7 +828,7 @@ var REGISTRY_PATH;
641
828
  var init_session_registry = __esm({
642
829
  "src/lib/session-registry.ts"() {
643
830
  "use strict";
644
- REGISTRY_PATH = path4.join(os4.homedir(), ".exe-os", "session-registry.json");
831
+ REGISTRY_PATH = path6.join(os5.homedir(), ".exe-os", "session-registry.json");
645
832
  }
646
833
  });
647
834
 
@@ -893,67 +1080,6 @@ var init_provider_table = __esm({
893
1080
  }
894
1081
  });
895
1082
 
896
- // src/lib/runtime-table.ts
897
- var RUNTIME_TABLE, DEFAULT_RUNTIME;
898
- var init_runtime_table = __esm({
899
- "src/lib/runtime-table.ts"() {
900
- "use strict";
901
- RUNTIME_TABLE = {
902
- codex: {
903
- binary: "codex",
904
- launchMode: "interactive",
905
- autoApproveFlag: "--dangerously-bypass-approvals-and-sandbox",
906
- inlineFlag: "--no-alt-screen",
907
- apiKeyEnv: "OPENAI_API_KEY",
908
- defaultModel: "gpt-5.4"
909
- },
910
- opencode: {
911
- binary: "opencode",
912
- launchMode: "exec",
913
- autoApproveFlag: "--dangerously-skip-permissions",
914
- inlineFlag: "",
915
- apiKeyEnv: "ANTHROPIC_API_KEY",
916
- defaultModel: "anthropic/claude-sonnet-4-6"
917
- }
918
- };
919
- DEFAULT_RUNTIME = "claude";
920
- }
921
- });
922
-
923
- // src/lib/agent-config.ts
924
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
925
- import path5 from "path";
926
- function loadAgentConfig() {
927
- if (!existsSync5(AGENT_CONFIG_PATH)) return {};
928
- try {
929
- return JSON.parse(readFileSync5(AGENT_CONFIG_PATH, "utf-8"));
930
- } catch {
931
- return {};
932
- }
933
- }
934
- function getAgentRuntime(agentId) {
935
- const config = loadAgentConfig();
936
- const entry = config[agentId];
937
- if (entry) return entry;
938
- const orgDefault = config["default"];
939
- if (orgDefault) return orgDefault;
940
- return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
941
- }
942
- var AGENT_CONFIG_PATH, DEFAULT_MODELS;
943
- var init_agent_config = __esm({
944
- "src/lib/agent-config.ts"() {
945
- "use strict";
946
- init_config();
947
- init_runtime_table();
948
- AGENT_CONFIG_PATH = path5.join(EXE_AI_DIR, "agent-config.json");
949
- DEFAULT_MODELS = {
950
- claude: "claude-opus-4",
951
- codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
952
- opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
953
- };
954
- }
955
- });
956
-
957
1083
  // src/lib/intercom-queue.ts
958
1084
  var intercom_queue_exports = {};
959
1085
  __export(intercom_queue_exports, {
@@ -964,10 +1090,10 @@ __export(intercom_queue_exports, {
964
1090
  readQueue: () => readQueue
965
1091
  });
966
1092
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
967
- import path6 from "path";
968
- import os5 from "os";
1093
+ import path7 from "path";
1094
+ import os6 from "os";
969
1095
  function ensureDir() {
970
- const dir = path6.dirname(QUEUE_PATH);
1096
+ const dir = path7.dirname(QUEUE_PATH);
971
1097
  if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
972
1098
  }
973
1099
  function readQueue() {
@@ -1073,26 +1199,26 @@ var QUEUE_PATH, MAX_RETRIES, TTL_MS, INTERCOM_LOG;
1073
1199
  var init_intercom_queue = __esm({
1074
1200
  "src/lib/intercom-queue.ts"() {
1075
1201
  "use strict";
1076
- QUEUE_PATH = path6.join(os5.homedir(), ".exe-os", "intercom-queue.json");
1202
+ QUEUE_PATH = path7.join(os6.homedir(), ".exe-os", "intercom-queue.json");
1077
1203
  MAX_RETRIES = 5;
1078
1204
  TTL_MS = 60 * 60 * 1e3;
1079
- INTERCOM_LOG = path6.join(os5.homedir(), ".exe-os", "intercom.log");
1205
+ INTERCOM_LOG = path7.join(os6.homedir(), ".exe-os", "intercom.log");
1080
1206
  }
1081
1207
  });
1082
1208
 
1083
1209
  // src/lib/license.ts
1084
1210
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
1085
1211
  import { randomUUID } from "crypto";
1086
- import path7 from "path";
1212
+ import path8 from "path";
1087
1213
  import { jwtVerify, importSPKI } from "jose";
1088
1214
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, PLAN_LIMITS;
1089
1215
  var init_license = __esm({
1090
1216
  "src/lib/license.ts"() {
1091
1217
  "use strict";
1092
1218
  init_config();
1093
- LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
1094
- CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
1095
- DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
1219
+ LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
1220
+ CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
1221
+ DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
1096
1222
  PLAN_LIMITS = {
1097
1223
  free: { devices: 1, employees: 1, memories: 5e3 },
1098
1224
  pro: { devices: 3, employees: 5, memories: 1e5 },
@@ -1105,7 +1231,7 @@ var init_license = __esm({
1105
1231
 
1106
1232
  // src/lib/plan-limits.ts
1107
1233
  import { readFileSync as readFileSync8, existsSync as existsSync8 } from "fs";
1108
- import path8 from "path";
1234
+ import path9 from "path";
1109
1235
  function getLicenseSync() {
1110
1236
  try {
1111
1237
  if (!existsSync8(CACHE_PATH2)) return freeLicense();
@@ -1177,7 +1303,7 @@ var init_plan_limits = __esm({
1177
1303
  this.name = "PlanLimitError";
1178
1304
  }
1179
1305
  };
1180
- CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
1306
+ CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
1181
1307
  }
1182
1308
  });
1183
1309
 
@@ -1526,12 +1652,12 @@ __export(tmux_routing_exports, {
1526
1652
  });
1527
1653
  import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
1528
1654
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync9, appendFileSync, readdirSync as readdirSync2 } from "fs";
1529
- import path9 from "path";
1530
- import os6 from "os";
1655
+ import path10 from "path";
1656
+ import os7 from "os";
1531
1657
  import { fileURLToPath } from "url";
1532
1658
  import { unlinkSync as unlinkSync3 } from "fs";
1533
1659
  function spawnLockPath(sessionName) {
1534
- return path9.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
1660
+ return path10.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
1535
1661
  }
1536
1662
  function isProcessAlive(pid) {
1537
1663
  try {
@@ -1568,8 +1694,8 @@ function releaseSpawnLock(sessionName) {
1568
1694
  function resolveBehaviorsExporterScript() {
1569
1695
  try {
1570
1696
  const thisFile = fileURLToPath(import.meta.url);
1571
- const scriptPath = path9.join(
1572
- path9.dirname(thisFile),
1697
+ const scriptPath = path10.join(
1698
+ path10.dirname(thisFile),
1573
1699
  "..",
1574
1700
  "bin",
1575
1701
  "exe-export-behaviors.js"
@@ -1644,7 +1770,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
1644
1770
  mkdirSync5(SESSION_CACHE, { recursive: true });
1645
1771
  }
1646
1772
  const rootExe = extractRootExe(parentExe) ?? parentExe;
1647
- const filePath = path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
1773
+ const filePath = path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
1648
1774
  writeFileSync6(filePath, JSON.stringify({
1649
1775
  parentExe: rootExe,
1650
1776
  dispatchedBy: dispatchedBy || rootExe,
@@ -1653,7 +1779,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
1653
1779
  }
1654
1780
  function getParentExe(sessionKey) {
1655
1781
  try {
1656
- const data = JSON.parse(readFileSync9(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
1782
+ const data = JSON.parse(readFileSync9(path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
1657
1783
  return data.parentExe || null;
1658
1784
  } catch {
1659
1785
  return null;
@@ -1662,7 +1788,7 @@ function getParentExe(sessionKey) {
1662
1788
  function getDispatchedBy(sessionKey) {
1663
1789
  try {
1664
1790
  const data = JSON.parse(readFileSync9(
1665
- path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
1791
+ path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
1666
1792
  "utf8"
1667
1793
  ));
1668
1794
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -1673,15 +1799,24 @@ function getDispatchedBy(sessionKey) {
1673
1799
  function resolveExeSession() {
1674
1800
  const mySession = getMySession();
1675
1801
  if (!mySession) return null;
1802
+ const fromSessionName = extractRootExe(mySession);
1676
1803
  try {
1677
1804
  const key = getSessionKey();
1678
1805
  const parentExe = getParentExe(key);
1679
1806
  if (parentExe) {
1680
- return extractRootExe(parentExe) ?? parentExe;
1807
+ const fromCache = extractRootExe(parentExe) ?? parentExe;
1808
+ if (fromSessionName && fromCache !== fromSessionName) {
1809
+ process.stderr.write(
1810
+ `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
1811
+ `
1812
+ );
1813
+ return fromSessionName;
1814
+ }
1815
+ return fromCache;
1681
1816
  }
1682
1817
  } catch {
1683
1818
  }
1684
- return extractRootExe(mySession) ?? mySession;
1819
+ return fromSessionName ?? mySession;
1685
1820
  }
1686
1821
  function isEmployeeAlive(sessionName) {
1687
1822
  return getTransport().isAlive(sessionName);
@@ -1839,7 +1974,7 @@ function sendIntercom(targetSession) {
1839
1974
  try {
1840
1975
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
1841
1976
  const agent = baseAgentName(rawAgent);
1842
- const markerPath = path9.join(SESSION_CACHE, `current-task-${agent}.json`);
1977
+ const markerPath = path10.join(SESSION_CACHE, `current-task-${agent}.json`);
1843
1978
  if (existsSync9(markerPath)) {
1844
1979
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
1845
1980
  return "debounced";
@@ -1849,7 +1984,7 @@ function sendIntercom(targetSession) {
1849
1984
  try {
1850
1985
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
1851
1986
  const agent = baseAgentName(rawAgent);
1852
- const taskDir = path9.join(process.cwd(), "exe", agent);
1987
+ const taskDir = path10.join(process.cwd(), "exe", agent);
1853
1988
  if (existsSync9(taskDir)) {
1854
1989
  const files = readdirSync2(taskDir).filter(
1855
1990
  (f) => f.endsWith(".md") && f !== "DONE.txt"
@@ -1983,8 +2118,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
1983
2118
  const transport = getTransport();
1984
2119
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
1985
2120
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
1986
- const logDir = path9.join(os6.homedir(), ".exe-os", "session-logs");
1987
- const logFile = path9.join(logDir, `${instanceLabel}-${Date.now()}.log`);
2121
+ const logDir = path10.join(os7.homedir(), ".exe-os", "session-logs");
2122
+ const logFile = path10.join(logDir, `${instanceLabel}-${Date.now()}.log`);
1988
2123
  if (!existsSync9(logDir)) {
1989
2124
  mkdirSync5(logDir, { recursive: true });
1990
2125
  }
@@ -1992,14 +2127,14 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
1992
2127
  let cleanupSuffix = "";
1993
2128
  try {
1994
2129
  const thisFile = fileURLToPath(import.meta.url);
1995
- const cleanupScript = path9.join(path9.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
2130
+ const cleanupScript = path10.join(path10.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
1996
2131
  if (existsSync9(cleanupScript)) {
1997
2132
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
1998
2133
  }
1999
2134
  } catch {
2000
2135
  }
2001
2136
  try {
2002
- const claudeJsonPath = path9.join(os6.homedir(), ".claude.json");
2137
+ const claudeJsonPath = path10.join(os7.homedir(), ".claude.json");
2003
2138
  let claudeJson = {};
2004
2139
  try {
2005
2140
  claudeJson = JSON.parse(readFileSync9(claudeJsonPath, "utf8"));
@@ -2014,10 +2149,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2014
2149
  } catch {
2015
2150
  }
2016
2151
  try {
2017
- const settingsDir = path9.join(os6.homedir(), ".claude", "projects");
2152
+ const settingsDir = path10.join(os7.homedir(), ".claude", "projects");
2018
2153
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
2019
- const projSettingsDir = path9.join(settingsDir, normalizedKey);
2020
- const settingsPath = path9.join(projSettingsDir, "settings.json");
2154
+ const projSettingsDir = path10.join(settingsDir, normalizedKey);
2155
+ const settingsPath = path10.join(projSettingsDir, "settings.json");
2021
2156
  let settings = {};
2022
2157
  try {
2023
2158
  settings = JSON.parse(readFileSync9(settingsPath, "utf8"));
@@ -2064,8 +2199,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2064
2199
  let behaviorsFlag = "";
2065
2200
  let legacyFallbackWarned = false;
2066
2201
  if (!useExeAgent && !useBinSymlink) {
2067
- const identityPath2 = path9.join(
2068
- os6.homedir(),
2202
+ const identityPath2 = path10.join(
2203
+ os7.homedir(),
2069
2204
  ".exe-os",
2070
2205
  "identity",
2071
2206
  `${employeeName}.md`
@@ -2080,7 +2215,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2080
2215
  }
2081
2216
  const behaviorsFile = exportBehaviorsSync(
2082
2217
  employeeName,
2083
- path9.basename(spawnCwd),
2218
+ path10.basename(spawnCwd),
2084
2219
  sessionName
2085
2220
  );
2086
2221
  if (behaviorsFile) {
@@ -2095,9 +2230,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2095
2230
  }
2096
2231
  let sessionContextFlag = "";
2097
2232
  try {
2098
- const ctxDir = path9.join(os6.homedir(), ".exe-os", "session-cache");
2233
+ const ctxDir = path10.join(os7.homedir(), ".exe-os", "session-cache");
2099
2234
  mkdirSync5(ctxDir, { recursive: true });
2100
- const ctxFile = path9.join(ctxDir, `session-context-${sessionName}.md`);
2235
+ const ctxFile = path10.join(ctxDir, `session-context-${sessionName}.md`);
2101
2236
  const ctxContent = [
2102
2237
  `## Session Context`,
2103
2238
  `You are running in tmux session: ${sessionName}.`,
@@ -2181,7 +2316,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2181
2316
  transport.pipeLog(sessionName, logFile);
2182
2317
  try {
2183
2318
  const mySession = getMySession();
2184
- const dispatchInfo = path9.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
2319
+ const dispatchInfo = path10.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
2185
2320
  writeFileSync6(dispatchInfo, JSON.stringify({
2186
2321
  dispatchedBy: mySession,
2187
2322
  rootExe: exeSession,
@@ -2256,15 +2391,15 @@ var init_tmux_routing = __esm({
2256
2391
  init_intercom_queue();
2257
2392
  init_plan_limits();
2258
2393
  init_employees();
2259
- SPAWN_LOCK_DIR = path9.join(os6.homedir(), ".exe-os", "spawn-locks");
2260
- SESSION_CACHE = path9.join(os6.homedir(), ".exe-os", "session-cache");
2394
+ SPAWN_LOCK_DIR = path10.join(os7.homedir(), ".exe-os", "spawn-locks");
2395
+ SESSION_CACHE = path10.join(os7.homedir(), ".exe-os", "session-cache");
2261
2396
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
2262
2397
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
2263
2398
  VERIFY_PANE_LINES = 200;
2264
2399
  INTERCOM_DEBOUNCE_MS = 3e4;
2265
2400
  CODEX_DEBOUNCE_MS = 12e4;
2266
- INTERCOM_LOG2 = path9.join(os6.homedir(), ".exe-os", "intercom.log");
2267
- DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
2401
+ INTERCOM_LOG2 = path10.join(os7.homedir(), ".exe-os", "intercom.log");
2402
+ DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
2268
2403
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
2269
2404
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
2270
2405
  }
@@ -2296,8 +2431,8 @@ var init_task_scope = __esm({
2296
2431
 
2297
2432
  // src/lib/tasks-crud.ts
2298
2433
  import crypto3 from "crypto";
2299
- import path10 from "path";
2300
- import os7 from "os";
2434
+ import path11 from "path";
2435
+ import os8 from "os";
2301
2436
  import { execSync as execSync5 } from "child_process";
2302
2437
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
2303
2438
  import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
@@ -2475,8 +2610,8 @@ ${laneWarning}` : laneWarning;
2475
2610
  }
2476
2611
  if (input.baseDir) {
2477
2612
  try {
2478
- await mkdir3(path10.join(input.baseDir, "exe", "output"), { recursive: true });
2479
- await mkdir3(path10.join(input.baseDir, "exe", "research"), { recursive: true });
2613
+ await mkdir3(path11.join(input.baseDir, "exe", "output"), { recursive: true });
2614
+ await mkdir3(path11.join(input.baseDir, "exe", "research"), { recursive: true });
2480
2615
  await ensureArchitectureDoc(input.baseDir, input.projectName);
2481
2616
  await ensureGitignoreExe(input.baseDir);
2482
2617
  } catch {
@@ -2512,9 +2647,9 @@ ${laneWarning}` : laneWarning;
2512
2647
  });
2513
2648
  if (input.baseDir) {
2514
2649
  try {
2515
- const EXE_OS_DIR = path10.join(os7.homedir(), ".exe-os");
2516
- const mdPath = path10.join(EXE_OS_DIR, taskFile);
2517
- const mdDir = path10.dirname(mdPath);
2650
+ const EXE_OS_DIR = path11.join(os8.homedir(), ".exe-os");
2651
+ const mdPath = path11.join(EXE_OS_DIR, taskFile);
2652
+ const mdDir = path11.dirname(mdPath);
2518
2653
  if (!existsSync10(mdDir)) await mkdir3(mdDir, { recursive: true });
2519
2654
  const reviewer = input.reviewer ?? input.assignedBy;
2520
2655
  const mdContent = `# ${input.title}
@@ -2815,7 +2950,7 @@ async function deleteTaskCore(taskId, _baseDir) {
2815
2950
  return { taskFile, assignedTo, assignedBy, taskSlug };
2816
2951
  }
2817
2952
  async function ensureArchitectureDoc(baseDir, projectName) {
2818
- const archPath = path10.join(baseDir, "exe", "ARCHITECTURE.md");
2953
+ const archPath = path11.join(baseDir, "exe", "ARCHITECTURE.md");
2819
2954
  try {
2820
2955
  if (existsSync10(archPath)) return;
2821
2956
  const template = [
@@ -2850,7 +2985,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
2850
2985
  }
2851
2986
  }
2852
2987
  async function ensureGitignoreExe(baseDir) {
2853
- const gitignorePath = path10.join(baseDir, ".gitignore");
2988
+ const gitignorePath = path11.join(baseDir, ".gitignore");
2854
2989
  try {
2855
2990
  if (existsSync10(gitignorePath)) {
2856
2991
  const content = readFileSync10(gitignorePath, "utf-8");
@@ -2884,13 +3019,13 @@ var init_tasks_crud = __esm({
2884
3019
  });
2885
3020
 
2886
3021
  // src/lib/tasks-review.ts
2887
- import path11 from "path";
3022
+ import path12 from "path";
2888
3023
  import { existsSync as existsSync11, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
2889
3024
  async function countPendingReviews(sessionScope) {
2890
3025
  const client = getClient();
2891
3026
  if (sessionScope) {
2892
3027
  const result2 = await client.execute({
2893
- sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND (session_scope = ? OR session_scope IS NULL)",
3028
+ sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND session_scope = ?",
2894
3029
  args: [sessionScope]
2895
3030
  });
2896
3031
  return Number(result2.rows[0]?.cnt) || 0;
@@ -3066,11 +3201,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
3066
3201
  );
3067
3202
  }
3068
3203
  try {
3069
- const cacheDir = path11.join(EXE_AI_DIR, "session-cache");
3204
+ const cacheDir = path12.join(EXE_AI_DIR, "session-cache");
3070
3205
  if (existsSync11(cacheDir)) {
3071
3206
  for (const f of readdirSync3(cacheDir)) {
3072
3207
  if (f.startsWith("review-notified-")) {
3073
- unlinkSync4(path11.join(cacheDir, f));
3208
+ unlinkSync4(path12.join(cacheDir, f));
3074
3209
  }
3075
3210
  }
3076
3211
  }
@@ -3091,7 +3226,7 @@ var init_tasks_review = __esm({
3091
3226
  });
3092
3227
 
3093
3228
  // src/lib/tasks-chain.ts
3094
- import path12 from "path";
3229
+ import path13 from "path";
3095
3230
  import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
3096
3231
  async function cascadeUnblock(taskId, baseDir, now) {
3097
3232
  const client = getClient();
@@ -3108,7 +3243,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
3108
3243
  });
3109
3244
  for (const ur of unblockedRows.rows) {
3110
3245
  try {
3111
- const ubFile = path12.join(baseDir, String(ur.task_file));
3246
+ const ubFile = path13.join(baseDir, String(ur.task_file));
3112
3247
  let ubContent = await readFile3(ubFile, "utf-8");
3113
3248
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
3114
3249
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -3177,7 +3312,7 @@ var init_tasks_chain = __esm({
3177
3312
 
3178
3313
  // src/lib/project-name.ts
3179
3314
  import { execSync as execSync6 } from "child_process";
3180
- import path13 from "path";
3315
+ import path14 from "path";
3181
3316
  function getProjectName(cwd) {
3182
3317
  const dir = cwd ?? process.cwd();
3183
3318
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -3190,7 +3325,7 @@ function getProjectName(cwd) {
3190
3325
  timeout: 2e3,
3191
3326
  stdio: ["pipe", "pipe", "pipe"]
3192
3327
  }).trim();
3193
- repoRoot = path13.dirname(gitCommonDir);
3328
+ repoRoot = path14.dirname(gitCommonDir);
3194
3329
  } catch {
3195
3330
  repoRoot = execSync6("git rev-parse --show-toplevel", {
3196
3331
  cwd: dir,
@@ -3199,11 +3334,11 @@ function getProjectName(cwd) {
3199
3334
  stdio: ["pipe", "pipe", "pipe"]
3200
3335
  }).trim();
3201
3336
  }
3202
- _cached2 = path13.basename(repoRoot);
3337
+ _cached2 = path14.basename(repoRoot);
3203
3338
  _cachedCwd = dir;
3204
3339
  return _cached2;
3205
3340
  } catch {
3206
- _cached2 = path13.basename(dir);
3341
+ _cached2 = path14.basename(dir);
3207
3342
  _cachedCwd = dir;
3208
3343
  return _cached2;
3209
3344
  }
@@ -3676,7 +3811,7 @@ __export(tasks_exports, {
3676
3811
  updateTaskStatus: () => updateTaskStatus,
3677
3812
  writeCheckpoint: () => writeCheckpoint
3678
3813
  });
3679
- import path14 from "path";
3814
+ import path15 from "path";
3680
3815
  import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5 } from "fs";
3681
3816
  async function createTask(input) {
3682
3817
  const result = await createTaskCore(input);
@@ -3696,8 +3831,8 @@ async function updateTask(input) {
3696
3831
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
3697
3832
  try {
3698
3833
  const agent = String(row.assigned_to);
3699
- const cacheDir = path14.join(EXE_AI_DIR, "session-cache");
3700
- const cachePath = path14.join(cacheDir, `current-task-${agent}.json`);
3834
+ const cacheDir = path15.join(EXE_AI_DIR, "session-cache");
3835
+ const cachePath = path15.join(cacheDir, `current-task-${agent}.json`);
3701
3836
  if (input.status === "in_progress") {
3702
3837
  mkdirSync6(cacheDir, { recursive: true });
3703
3838
  writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
@@ -3868,15 +4003,15 @@ __export(identity_exports, {
3868
4003
  });
3869
4004
  import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
3870
4005
  import { readdirSync as readdirSync5 } from "fs";
3871
- import path16 from "path";
4006
+ import path17 from "path";
3872
4007
  import { createHash } from "crypto";
3873
4008
  function ensureDir2() {
3874
- if (!existsSync12(IDENTITY_DIR)) {
3875
- mkdirSync8(IDENTITY_DIR, { recursive: true });
4009
+ if (!existsSync12(IDENTITY_DIR2)) {
4010
+ mkdirSync8(IDENTITY_DIR2, { recursive: true });
3876
4011
  }
3877
4012
  }
3878
4013
  function identityPath(agentId) {
3879
- return path16.join(IDENTITY_DIR, `${agentId}.md`);
4014
+ return path17.join(IDENTITY_DIR2, `${agentId}.md`);
3880
4015
  }
3881
4016
  function parseFrontmatter(raw) {
3882
4017
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
@@ -3949,7 +4084,7 @@ async function updateIdentity(agentId, content, updatedBy) {
3949
4084
  }
3950
4085
  function listIdentities() {
3951
4086
  ensureDir2();
3952
- const files = readdirSync5(IDENTITY_DIR).filter((f) => f.endsWith(".md"));
4087
+ const files = readdirSync5(IDENTITY_DIR2).filter((f) => f.endsWith(".md"));
3953
4088
  const results = [];
3954
4089
  for (const file of files) {
3955
4090
  const agentId = file.replace(".md", "");
@@ -3982,13 +4117,13 @@ ${teamLines.join("\n")}`);
3982
4117
  }
3983
4118
  return parts.join("\n\n");
3984
4119
  }
3985
- var IDENTITY_DIR;
4120
+ var IDENTITY_DIR2;
3986
4121
  var init_identity = __esm({
3987
4122
  "src/lib/identity.ts"() {
3988
4123
  "use strict";
3989
4124
  init_config();
3990
4125
  init_database();
3991
- IDENTITY_DIR = path16.join(EXE_AI_DIR, "identity");
4126
+ IDENTITY_DIR2 = path17.join(EXE_AI_DIR, "identity");
3992
4127
  }
3993
4128
  });
3994
4129
 
@@ -4543,8 +4678,8 @@ init_session_key();
4543
4678
  init_employees();
4544
4679
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, unlinkSync as unlinkSync6, readdirSync as readdirSync4 } from "fs";
4545
4680
  import { execSync as execSync7 } from "child_process";
4546
- import path15 from "path";
4547
- var CACHE_DIR = path15.join(EXE_AI_DIR, "session-cache");
4681
+ import path16 from "path";
4682
+ var CACHE_DIR = path16.join(EXE_AI_DIR, "session-cache");
4548
4683
  var STALE_MS = 24 * 60 * 60 * 1e3;
4549
4684
  function isNameWithOptionalInstance(candidate, baseName) {
4550
4685
  if (candidate === baseName) return true;
@@ -4589,7 +4724,7 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
4589
4724
  return null;
4590
4725
  }
4591
4726
  function getMarkerPath() {
4592
- return path15.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
4727
+ return path16.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
4593
4728
  }
4594
4729
  function getActiveAgent() {
4595
4730
  try {