@askexenow/exe-os 0.9.85 → 0.9.86

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 (80) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +32 -14
  2. package/dist/bin/agentic-reflection-backfill.js +32 -14
  3. package/dist/bin/agentic-semantic-label.js +32 -14
  4. package/dist/bin/backfill-conversations.js +32 -14
  5. package/dist/bin/backfill-responses.js +32 -14
  6. package/dist/bin/backfill-vectors.js +32 -14
  7. package/dist/bin/bulk-sync-postgres.js +32 -14
  8. package/dist/bin/cleanup-stale-review-tasks.js +35 -17
  9. package/dist/bin/cli.js +152 -77
  10. package/dist/bin/exe-assign.js +32 -14
  11. package/dist/bin/exe-boot.js +57 -39
  12. package/dist/bin/exe-cloud.js +22 -4
  13. package/dist/bin/exe-dispatch.js +43 -25
  14. package/dist/bin/exe-doctor.js +22 -4
  15. package/dist/bin/exe-export-behaviors.js +32 -14
  16. package/dist/bin/exe-forget.js +32 -14
  17. package/dist/bin/exe-gateway.js +47 -29
  18. package/dist/bin/exe-heartbeat.js +37 -19
  19. package/dist/bin/exe-kill.js +36 -18
  20. package/dist/bin/exe-launch-agent.js +40 -22
  21. package/dist/bin/exe-pending-messages.js +35 -17
  22. package/dist/bin/exe-pending-notifications.js +35 -17
  23. package/dist/bin/exe-pending-reviews.js +37 -19
  24. package/dist/bin/exe-rename.js +34 -16
  25. package/dist/bin/exe-review.js +32 -14
  26. package/dist/bin/exe-search.js +40 -22
  27. package/dist/bin/exe-session-cleanup.js +67 -44
  28. package/dist/bin/exe-start-codex.js +39 -21
  29. package/dist/bin/exe-start-opencode.js +37 -19
  30. package/dist/bin/exe-status.js +44 -26
  31. package/dist/bin/exe-team.js +32 -14
  32. package/dist/bin/git-sweep.js +45 -27
  33. package/dist/bin/graph-backfill.js +32 -14
  34. package/dist/bin/graph-export.js +32 -14
  35. package/dist/bin/intercom-check.js +49 -31
  36. package/dist/bin/scan-tasks.js +45 -27
  37. package/dist/bin/setup.js +29 -11
  38. package/dist/bin/shard-migrate.js +32 -14
  39. package/dist/bin/stack-update.js +59 -2
  40. package/dist/bin/update.js +1 -1
  41. package/dist/gateway/index.js +47 -29
  42. package/dist/hooks/bug-report-worker.js +47 -29
  43. package/dist/hooks/codex-stop-task-finalizer.js +41 -23
  44. package/dist/hooks/commit-complete.js +46 -28
  45. package/dist/hooks/error-recall.js +44 -26
  46. package/dist/hooks/ingest-worker.js +4 -4
  47. package/dist/hooks/ingest.js +38 -20
  48. package/dist/hooks/instructions-loaded.js +32 -14
  49. package/dist/hooks/notification.js +32 -14
  50. package/dist/hooks/post-compact.js +32 -14
  51. package/dist/hooks/post-tool-combined.js +45 -27
  52. package/dist/hooks/pre-compact.js +43 -25
  53. package/dist/hooks/pre-tool-use.js +40 -22
  54. package/dist/hooks/prompt-submit.js +60 -42
  55. package/dist/hooks/session-end.js +48 -30
  56. package/dist/hooks/session-start.js +50 -32
  57. package/dist/hooks/stop.js +35 -17
  58. package/dist/hooks/subagent-stop.js +32 -14
  59. package/dist/hooks/summary-worker.js +37 -19
  60. package/dist/index.js +43 -25
  61. package/dist/lib/cloud-sync.js +32 -14
  62. package/dist/lib/database.js +22 -4
  63. package/dist/lib/db-daemon-client.js +16 -4
  64. package/dist/lib/db.js +22 -4
  65. package/dist/lib/device-registry.js +22 -4
  66. package/dist/lib/embedder.js +16 -4
  67. package/dist/lib/exe-daemon-client.js +16 -4
  68. package/dist/lib/exe-daemon.js +165 -66
  69. package/dist/lib/hybrid-search.js +40 -22
  70. package/dist/lib/schedules.js +35 -17
  71. package/dist/lib/skill-learning.js +16 -4
  72. package/dist/lib/store.js +32 -14
  73. package/dist/lib/tasks.js +16 -4
  74. package/dist/lib/tmux-routing.js +18 -6
  75. package/dist/mcp/server.js +142 -60
  76. package/dist/mcp/tools/create-task.js +18 -6
  77. package/dist/mcp/tools/update-task.js +18 -6
  78. package/dist/runtime/index.js +43 -25
  79. package/dist/tui/App.js +73 -55
  80. package/package.json +1 -1
@@ -1101,7 +1101,7 @@ __export(exe_daemon_client_exports, {
1101
1101
  });
1102
1102
  import net from "net";
1103
1103
  import os4 from "os";
1104
- import { spawn } from "child_process";
1104
+ import { spawn, execSync as execSync2 } from "child_process";
1105
1105
  import { randomUUID } from "crypto";
1106
1106
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
1107
1107
  import path5 from "path";
@@ -1131,6 +1131,14 @@ function handleData(chunk) {
1131
1131
  }
1132
1132
  }
1133
1133
  }
1134
+ function isZombie(pid) {
1135
+ try {
1136
+ const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
1137
+ return state.startsWith("Z");
1138
+ } catch {
1139
+ return false;
1140
+ }
1141
+ }
1134
1142
  function cleanupStaleFiles() {
1135
1143
  if (existsSync5(PID_PATH)) {
1136
1144
  try {
@@ -1138,7 +1146,11 @@ function cleanupStaleFiles() {
1138
1146
  if (pid > 0) {
1139
1147
  try {
1140
1148
  process.kill(pid, 0);
1141
- return;
1149
+ if (!isZombie(pid)) {
1150
+ return;
1151
+ }
1152
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
1153
+ `);
1142
1154
  } catch {
1143
1155
  }
1144
1156
  }
@@ -1166,8 +1178,8 @@ function findPackageRoot() {
1166
1178
  function getAvailableMemoryGB() {
1167
1179
  if (process.platform === "darwin") {
1168
1180
  try {
1169
- const { execSync: execSync8 } = __require("child_process");
1170
- const vmstat = execSync8("vm_stat", { encoding: "utf8" });
1181
+ const { execSync: execSync9 } = __require("child_process");
1182
+ const vmstat = execSync9("vm_stat", { encoding: "utf8" });
1171
1183
  const pageSize = 16384;
1172
1184
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1173
1185
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3157,6 +3169,12 @@ async function disposeDatabase() {
3157
3169
  clearInterval(_walCheckpointTimer);
3158
3170
  _walCheckpointTimer = null;
3159
3171
  }
3172
+ if (_client) {
3173
+ try {
3174
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
3175
+ } catch {
3176
+ }
3177
+ }
3160
3178
  if (_daemonClient) {
3161
3179
  _daemonClient.close();
3162
3180
  _daemonClient = null;
@@ -3193,7 +3211,7 @@ var init_database = __esm({
3193
3211
  // src/lib/keychain.ts
3194
3212
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3195
3213
  import { existsSync as existsSync6, statSync as statSync2 } from "fs";
3196
- import { execSync as execSync2 } from "child_process";
3214
+ import { execSync as execSync3 } from "child_process";
3197
3215
  import path6 from "path";
3198
3216
  import os5 from "os";
3199
3217
  function getKeyDir() {
@@ -3210,13 +3228,13 @@ function linuxSecretAvailable() {
3210
3228
  if (process.platform !== "linux") return false;
3211
3229
  if (linuxSecretAvailability !== null) return linuxSecretAvailability;
3212
3230
  try {
3213
- execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3231
+ execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3214
3232
  } catch {
3215
3233
  linuxSecretAvailability = false;
3216
3234
  return false;
3217
3235
  }
3218
3236
  try {
3219
- execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3237
+ execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3220
3238
  linuxSecretAvailability = true;
3221
3239
  } catch {
3222
3240
  linuxSecretAvailability = false;
@@ -3240,7 +3258,7 @@ function macKeychainGet(service = SERVICE) {
3240
3258
  if (!nativeKeychainAllowed()) return null;
3241
3259
  if (process.platform !== "darwin") return null;
3242
3260
  try {
3243
- return execSync2(
3261
+ return execSync3(
3244
3262
  `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
3245
3263
  { encoding: "utf-8", timeout: 5e3 }
3246
3264
  ).trim();
@@ -3253,13 +3271,13 @@ function macKeychainSet(value, service = SERVICE) {
3253
3271
  if (process.platform !== "darwin") return false;
3254
3272
  try {
3255
3273
  try {
3256
- execSync2(
3274
+ execSync3(
3257
3275
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3258
3276
  { timeout: 5e3 }
3259
3277
  );
3260
3278
  } catch {
3261
3279
  }
3262
- execSync2(
3280
+ execSync3(
3263
3281
  `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
3264
3282
  { timeout: 5e3 }
3265
3283
  );
@@ -3272,7 +3290,7 @@ function macKeychainDelete(service = SERVICE) {
3272
3290
  if (!nativeKeychainAllowed()) return false;
3273
3291
  if (process.platform !== "darwin") return false;
3274
3292
  try {
3275
- execSync2(
3293
+ execSync3(
3276
3294
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3277
3295
  { timeout: 5e3 }
3278
3296
  );
@@ -3284,7 +3302,7 @@ function macKeychainDelete(service = SERVICE) {
3284
3302
  function linuxSecretGet(service = SERVICE) {
3285
3303
  if (!linuxSecretAvailable()) return null;
3286
3304
  try {
3287
- return execSync2(
3305
+ return execSync3(
3288
3306
  `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3289
3307
  { encoding: "utf-8", timeout: 5e3 }
3290
3308
  ).trim();
@@ -3295,7 +3313,7 @@ function linuxSecretGet(service = SERVICE) {
3295
3313
  function linuxSecretSet(value, service = SERVICE) {
3296
3314
  if (!linuxSecretAvailable()) return false;
3297
3315
  try {
3298
- execSync2(
3316
+ execSync3(
3299
3317
  `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3300
3318
  { timeout: 5e3 }
3301
3319
  );
@@ -3308,7 +3326,7 @@ function linuxSecretDelete(service = SERVICE) {
3308
3326
  if (!nativeKeychainAllowed()) return false;
3309
3327
  if (process.platform !== "linux") return false;
3310
3328
  try {
3311
- execSync2(
3329
+ execSync3(
3312
3330
  `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3313
3331
  { timeout: 5e3 }
3314
3332
  );
@@ -5591,7 +5609,7 @@ var init_session_registry = __esm({
5591
5609
  });
5592
5610
 
5593
5611
  // src/lib/session-key.ts
5594
- import { execSync as execSync3 } from "child_process";
5612
+ import { execSync as execSync4 } from "child_process";
5595
5613
  function normalizeCommand(command) {
5596
5614
  const trimmed = command.trim().toLowerCase();
5597
5615
  const parts = trimmed.split(/[\\/]/);
@@ -5610,7 +5628,7 @@ function resolveRuntimeProcess() {
5610
5628
  let pid = process.ppid;
5611
5629
  for (let i = 0; i < 10; i++) {
5612
5630
  try {
5613
- const info = execSync3(`ps -p ${pid} -o ppid=,comm=`, {
5631
+ const info = execSync4(`ps -p ${pid} -o ppid=,comm=`, {
5614
5632
  encoding: "utf8",
5615
5633
  timeout: 2e3
5616
5634
  }).trim();
@@ -5788,14 +5806,14 @@ var init_transport = __esm({
5788
5806
  });
5789
5807
 
5790
5808
  // src/lib/cc-agent-support.ts
5791
- import { execSync as execSync4 } from "child_process";
5809
+ import { execSync as execSync5 } from "child_process";
5792
5810
  function _resetCcAgentSupportCache() {
5793
5811
  _cachedSupport = null;
5794
5812
  }
5795
5813
  function claudeSupportsAgentFlag() {
5796
5814
  if (_cachedSupport !== null) return _cachedSupport;
5797
5815
  try {
5798
- const helpOutput = execSync4("claude --help 2>&1", {
5816
+ const helpOutput = execSync5("claude --help 2>&1", {
5799
5817
  encoding: "utf-8",
5800
5818
  timeout: 5e3
5801
5819
  });
@@ -6256,7 +6274,7 @@ __export(project_name_exports, {
6256
6274
  _resetCache: () => _resetCache,
6257
6275
  getProjectName: () => getProjectName
6258
6276
  });
6259
- import { execSync as execSync5 } from "child_process";
6277
+ import { execSync as execSync6 } from "child_process";
6260
6278
  import path14 from "path";
6261
6279
  function getProjectName(cwd) {
6262
6280
  const dir = cwd ?? process.cwd();
@@ -6264,7 +6282,7 @@ function getProjectName(cwd) {
6264
6282
  try {
6265
6283
  let repoRoot;
6266
6284
  try {
6267
- const gitCommonDir = execSync5("git rev-parse --path-format=absolute --git-common-dir", {
6285
+ const gitCommonDir = execSync6("git rev-parse --path-format=absolute --git-common-dir", {
6268
6286
  cwd: dir,
6269
6287
  encoding: "utf8",
6270
6288
  timeout: 2e3,
@@ -6272,7 +6290,7 @@ function getProjectName(cwd) {
6272
6290
  }).trim();
6273
6291
  repoRoot = path14.dirname(gitCommonDir);
6274
6292
  } catch {
6275
- repoRoot = execSync5("git rev-parse --show-toplevel", {
6293
+ repoRoot = execSync6("git rev-parse --show-toplevel", {
6276
6294
  cwd: dir,
6277
6295
  encoding: "utf8",
6278
6296
  timeout: 2e3,
@@ -6367,7 +6385,7 @@ var init_session_scope = __esm({
6367
6385
  import crypto3 from "crypto";
6368
6386
  import path15 from "path";
6369
6387
  import os10 from "os";
6370
- import { execSync as execSync6 } from "child_process";
6388
+ import { execSync as execSync7 } from "child_process";
6371
6389
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
6372
6390
  import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
6373
6391
  async function writeCheckpoint(input) {
@@ -6712,14 +6730,14 @@ function isTmuxSessionAlive(identifier) {
6712
6730
  if (!identifier || identifier === "unknown") return true;
6713
6731
  try {
6714
6732
  if (identifier.startsWith("%")) {
6715
- const output = execSync6("tmux list-panes -a -F '#{pane_id}'", {
6733
+ const output = execSync7("tmux list-panes -a -F '#{pane_id}'", {
6716
6734
  timeout: 2e3,
6717
6735
  encoding: "utf8",
6718
6736
  stdio: ["pipe", "pipe", "pipe"]
6719
6737
  });
6720
6738
  return output.split("\n").some((l) => l.trim() === identifier);
6721
6739
  } else {
6722
- execSync6(`tmux has-session -t ${JSON.stringify(identifier)}`, {
6740
+ execSync7(`tmux has-session -t ${JSON.stringify(identifier)}`, {
6723
6741
  timeout: 2e3,
6724
6742
  stdio: ["pipe", "pipe", "pipe"]
6725
6743
  });
@@ -6728,7 +6746,7 @@ function isTmuxSessionAlive(identifier) {
6728
6746
  } catch {
6729
6747
  if (identifier.startsWith("%")) return true;
6730
6748
  try {
6731
- execSync6("tmux list-sessions", {
6749
+ execSync7("tmux list-sessions", {
6732
6750
  timeout: 2e3,
6733
6751
  stdio: ["pipe", "pipe", "pipe"]
6734
6752
  });
@@ -6743,12 +6761,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
6743
6761
  if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
6744
6762
  try {
6745
6763
  const since = new Date(taskCreatedAt).toISOString();
6746
- const branch = execSync6(
6764
+ const branch = execSync7(
6747
6765
  "git rev-parse --abbrev-ref HEAD 2>/dev/null",
6748
6766
  { encoding: "utf8", timeout: 3e3 }
6749
6767
  ).trim();
6750
6768
  const branchArg = branch && branch !== "HEAD" ? branch : "";
6751
- const commitCount = execSync6(
6769
+ const commitCount = execSync7(
6752
6770
  `git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
6753
6771
  { encoding: "utf8", timeout: 5e3 }
6754
6772
  ).trim();
@@ -8039,7 +8057,7 @@ __export(tmux_routing_exports, {
8039
8057
  spawnEmployee: () => spawnEmployee,
8040
8058
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
8041
8059
  });
8042
- import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
8060
+ import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
8043
8061
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync15, appendFileSync, readdirSync as readdirSync2 } from "fs";
8044
8062
  import path18 from "path";
8045
8063
  import os11 from "os";
@@ -8760,7 +8778,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
8760
8778
  let booted = false;
8761
8779
  for (let i = 0; i < 30; i++) {
8762
8780
  try {
8763
- execSync7("sleep 0.5");
8781
+ execSync8("sleep 0.5");
8764
8782
  } catch {
8765
8783
  }
8766
8784
  try {
@@ -9633,8 +9651,8 @@ async function main() {
9633
9651
  const agentId = folderArg.startsWith("exe/") ? folderArg.slice(4) : folderArg;
9634
9652
  let tmuxSession;
9635
9653
  try {
9636
- const { execSync: execSync8 } = await import("child_process");
9637
- const out = execSync8("tmux display-message -p '#{session_name}' 2>/dev/null", {
9654
+ const { execSync: execSync9 } = await import("child_process");
9655
+ const out = execSync9("tmux display-message -p '#{session_name}' 2>/dev/null", {
9638
9656
  encoding: "utf8",
9639
9657
  timeout: 1e3
9640
9658
  }).trim();
@@ -1593,7 +1593,7 @@ __export(exe_daemon_client_exports, {
1593
1593
  });
1594
1594
  import net from "net";
1595
1595
  import os6 from "os";
1596
- import { spawn } from "child_process";
1596
+ import { spawn, execSync as execSync4 } from "child_process";
1597
1597
  import { randomUUID } from "crypto";
1598
1598
  import { existsSync as existsSync8, unlinkSync as unlinkSync2, readFileSync as readFileSync7, openSync, closeSync, statSync } from "fs";
1599
1599
  import path8 from "path";
@@ -1623,6 +1623,14 @@ function handleData(chunk) {
1623
1623
  }
1624
1624
  }
1625
1625
  }
1626
+ function isZombie(pid) {
1627
+ try {
1628
+ const state = execSync4(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
1629
+ return state.startsWith("Z");
1630
+ } catch {
1631
+ return false;
1632
+ }
1633
+ }
1626
1634
  function cleanupStaleFiles() {
1627
1635
  if (existsSync8(PID_PATH)) {
1628
1636
  try {
@@ -1630,7 +1638,11 @@ function cleanupStaleFiles() {
1630
1638
  if (pid > 0) {
1631
1639
  try {
1632
1640
  process.kill(pid, 0);
1633
- return;
1641
+ if (!isZombie(pid)) {
1642
+ return;
1643
+ }
1644
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
1645
+ `);
1634
1646
  } catch {
1635
1647
  }
1636
1648
  }
@@ -1658,8 +1670,8 @@ function findPackageRoot() {
1658
1670
  function getAvailableMemoryGB() {
1659
1671
  if (process.platform === "darwin") {
1660
1672
  try {
1661
- const { execSync: execSync8 } = __require("child_process");
1662
- const vmstat = execSync8("vm_stat", { encoding: "utf8" });
1673
+ const { execSync: execSync9 } = __require("child_process");
1674
+ const vmstat = execSync9("vm_stat", { encoding: "utf8" });
1663
1675
  const pageSize = 16384;
1664
1676
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1665
1677
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3649,6 +3661,12 @@ async function disposeDatabase() {
3649
3661
  clearInterval(_walCheckpointTimer);
3650
3662
  _walCheckpointTimer = null;
3651
3663
  }
3664
+ if (_client) {
3665
+ try {
3666
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
3667
+ } catch {
3668
+ }
3669
+ }
3652
3670
  if (_daemonClient) {
3653
3671
  _daemonClient.close();
3654
3672
  _daemonClient = null;
@@ -4002,7 +4020,7 @@ __export(project_name_exports, {
4002
4020
  _resetCache: () => _resetCache,
4003
4021
  getProjectName: () => getProjectName
4004
4022
  });
4005
- import { execSync as execSync4 } from "child_process";
4023
+ import { execSync as execSync5 } from "child_process";
4006
4024
  import path13 from "path";
4007
4025
  function getProjectName(cwd) {
4008
4026
  const dir = cwd ?? process.cwd();
@@ -4010,7 +4028,7 @@ function getProjectName(cwd) {
4010
4028
  try {
4011
4029
  let repoRoot;
4012
4030
  try {
4013
- const gitCommonDir = execSync4("git rev-parse --path-format=absolute --git-common-dir", {
4031
+ const gitCommonDir = execSync5("git rev-parse --path-format=absolute --git-common-dir", {
4014
4032
  cwd: dir,
4015
4033
  encoding: "utf8",
4016
4034
  timeout: 2e3,
@@ -4018,7 +4036,7 @@ function getProjectName(cwd) {
4018
4036
  }).trim();
4019
4037
  repoRoot = path13.dirname(gitCommonDir);
4020
4038
  } catch {
4021
- repoRoot = execSync4("git rev-parse --show-toplevel", {
4039
+ repoRoot = execSync5("git rev-parse --show-toplevel", {
4022
4040
  cwd: dir,
4023
4041
  encoding: "utf8",
4024
4042
  timeout: 2e3,
@@ -4113,7 +4131,7 @@ var init_session_scope = __esm({
4113
4131
  import crypto4 from "crypto";
4114
4132
  import path14 from "path";
4115
4133
  import os10 from "os";
4116
- import { execSync as execSync5 } from "child_process";
4134
+ import { execSync as execSync6 } from "child_process";
4117
4135
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
4118
4136
  import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
4119
4137
  async function writeCheckpoint(input) {
@@ -4458,14 +4476,14 @@ function isTmuxSessionAlive(identifier) {
4458
4476
  if (!identifier || identifier === "unknown") return true;
4459
4477
  try {
4460
4478
  if (identifier.startsWith("%")) {
4461
- const output = execSync5("tmux list-panes -a -F '#{pane_id}'", {
4479
+ const output = execSync6("tmux list-panes -a -F '#{pane_id}'", {
4462
4480
  timeout: 2e3,
4463
4481
  encoding: "utf8",
4464
4482
  stdio: ["pipe", "pipe", "pipe"]
4465
4483
  });
4466
4484
  return output.split("\n").some((l) => l.trim() === identifier);
4467
4485
  } else {
4468
- execSync5(`tmux has-session -t ${JSON.stringify(identifier)}`, {
4486
+ execSync6(`tmux has-session -t ${JSON.stringify(identifier)}`, {
4469
4487
  timeout: 2e3,
4470
4488
  stdio: ["pipe", "pipe", "pipe"]
4471
4489
  });
@@ -4474,7 +4492,7 @@ function isTmuxSessionAlive(identifier) {
4474
4492
  } catch {
4475
4493
  if (identifier.startsWith("%")) return true;
4476
4494
  try {
4477
- execSync5("tmux list-sessions", {
4495
+ execSync6("tmux list-sessions", {
4478
4496
  timeout: 2e3,
4479
4497
  stdio: ["pipe", "pipe", "pipe"]
4480
4498
  });
@@ -4489,12 +4507,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
4489
4507
  if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
4490
4508
  try {
4491
4509
  const since = new Date(taskCreatedAt).toISOString();
4492
- const branch = execSync5(
4510
+ const branch = execSync6(
4493
4511
  "git rev-parse --abbrev-ref HEAD 2>/dev/null",
4494
4512
  { encoding: "utf8", timeout: 3e3 }
4495
4513
  ).trim();
4496
4514
  const branchArg = branch && branch !== "HEAD" ? branch : "";
4497
- const commitCount = execSync5(
4515
+ const commitCount = execSync6(
4498
4516
  `git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
4499
4517
  { encoding: "utf8", timeout: 5e3 }
4500
4518
  ).trim();
@@ -6093,7 +6111,7 @@ __export(tmux_routing_exports, {
6093
6111
  spawnEmployee: () => spawnEmployee,
6094
6112
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
6095
6113
  });
6096
- import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
6114
+ import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
6097
6115
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync15, appendFileSync, readdirSync as readdirSync3 } from "fs";
6098
6116
  import path18 from "path";
6099
6117
  import os11 from "os";
@@ -6814,7 +6832,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6814
6832
  let booted = false;
6815
6833
  for (let i = 0; i < 30; i++) {
6816
6834
  try {
6817
- execSync6("sleep 0.5");
6835
+ execSync7("sleep 0.5");
6818
6836
  } catch {
6819
6837
  }
6820
6838
  try {
@@ -6926,7 +6944,7 @@ var init_task_scope = __esm({
6926
6944
  // src/lib/keychain.ts
6927
6945
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
6928
6946
  import { existsSync as existsSync16, statSync as statSync2 } from "fs";
6929
- import { execSync as execSync7 } from "child_process";
6947
+ import { execSync as execSync8 } from "child_process";
6930
6948
  import path19 from "path";
6931
6949
  import os12 from "os";
6932
6950
  function getKeyDir() {
@@ -6943,13 +6961,13 @@ function linuxSecretAvailable() {
6943
6961
  if (process.platform !== "linux") return false;
6944
6962
  if (linuxSecretAvailability !== null) return linuxSecretAvailability;
6945
6963
  try {
6946
- execSync7("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
6964
+ execSync8("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
6947
6965
  } catch {
6948
6966
  linuxSecretAvailability = false;
6949
6967
  return false;
6950
6968
  }
6951
6969
  try {
6952
- execSync7("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
6970
+ execSync8("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
6953
6971
  linuxSecretAvailability = true;
6954
6972
  } catch {
6955
6973
  linuxSecretAvailability = false;
@@ -6973,7 +6991,7 @@ function macKeychainGet(service = SERVICE) {
6973
6991
  if (!nativeKeychainAllowed()) return null;
6974
6992
  if (process.platform !== "darwin") return null;
6975
6993
  try {
6976
- return execSync7(
6994
+ return execSync8(
6977
6995
  `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
6978
6996
  { encoding: "utf-8", timeout: 5e3 }
6979
6997
  ).trim();
@@ -6986,13 +7004,13 @@ function macKeychainSet(value, service = SERVICE) {
6986
7004
  if (process.platform !== "darwin") return false;
6987
7005
  try {
6988
7006
  try {
6989
- execSync7(
7007
+ execSync8(
6990
7008
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
6991
7009
  { timeout: 5e3 }
6992
7010
  );
6993
7011
  } catch {
6994
7012
  }
6995
- execSync7(
7013
+ execSync8(
6996
7014
  `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
6997
7015
  { timeout: 5e3 }
6998
7016
  );
@@ -7005,7 +7023,7 @@ function macKeychainDelete(service = SERVICE) {
7005
7023
  if (!nativeKeychainAllowed()) return false;
7006
7024
  if (process.platform !== "darwin") return false;
7007
7025
  try {
7008
- execSync7(
7026
+ execSync8(
7009
7027
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
7010
7028
  { timeout: 5e3 }
7011
7029
  );
@@ -7017,7 +7035,7 @@ function macKeychainDelete(service = SERVICE) {
7017
7035
  function linuxSecretGet(service = SERVICE) {
7018
7036
  if (!linuxSecretAvailable()) return null;
7019
7037
  try {
7020
- return execSync7(
7038
+ return execSync8(
7021
7039
  `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
7022
7040
  { encoding: "utf-8", timeout: 5e3 }
7023
7041
  ).trim();
@@ -7028,7 +7046,7 @@ function linuxSecretGet(service = SERVICE) {
7028
7046
  function linuxSecretSet(value, service = SERVICE) {
7029
7047
  if (!linuxSecretAvailable()) return false;
7030
7048
  try {
7031
- execSync7(
7049
+ execSync8(
7032
7050
  `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
7033
7051
  { timeout: 5e3 }
7034
7052
  );
@@ -7041,7 +7059,7 @@ function linuxSecretDelete(service = SERVICE) {
7041
7059
  if (!nativeKeychainAllowed()) return false;
7042
7060
  if (process.platform !== "linux") return false;
7043
7061
  try {
7044
- execSync7(
7062
+ execSync8(
7045
7063
  `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
7046
7064
  { timeout: 5e3 }
7047
7065
  );
@@ -9437,8 +9455,8 @@ async function main() {
9437
9455
  const agentId = folderArg.startsWith("exe/") ? folderArg.slice(4) : folderArg;
9438
9456
  let tmuxSession;
9439
9457
  try {
9440
- const { execSync: execSync8 } = await import("child_process");
9441
- const out = execSync8("tmux display-message -p '#{session_name}' 2>/dev/null", {
9458
+ const { execSync: execSync9 } = await import("child_process");
9459
+ const out = execSync9("tmux display-message -p '#{session_name}' 2>/dev/null", {
9442
9460
  encoding: "utf8",
9443
9461
  timeout: 1e3
9444
9462
  }).trim();
package/dist/bin/setup.js CHANGED
@@ -846,7 +846,7 @@ var init_daemon_auth = __esm({
846
846
  // src/lib/exe-daemon-client.ts
847
847
  import net from "net";
848
848
  import os3 from "os";
849
- import { spawn } from "child_process";
849
+ import { spawn, execSync as execSync2 } from "child_process";
850
850
  import { randomUUID } from "crypto";
851
851
  import { existsSync as existsSync6, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync as statSync2 } from "fs";
852
852
  import path5 from "path";
@@ -876,6 +876,14 @@ function handleData(chunk) {
876
876
  }
877
877
  }
878
878
  }
879
+ function isZombie(pid) {
880
+ try {
881
+ const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
882
+ return state.startsWith("Z");
883
+ } catch {
884
+ return false;
885
+ }
886
+ }
879
887
  function cleanupStaleFiles() {
880
888
  if (existsSync6(PID_PATH)) {
881
889
  try {
@@ -883,7 +891,11 @@ function cleanupStaleFiles() {
883
891
  if (pid > 0) {
884
892
  try {
885
893
  process.kill(pid, 0);
886
- return;
894
+ if (!isZombie(pid)) {
895
+ return;
896
+ }
897
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
898
+ `);
887
899
  } catch {
888
900
  }
889
901
  }
@@ -911,8 +923,8 @@ function findPackageRoot() {
911
923
  function getAvailableMemoryGB() {
912
924
  if (process.platform === "darwin") {
913
925
  try {
914
- const { execSync: execSync4 } = __require("child_process");
915
- const vmstat = execSync4("vm_stat", { encoding: "utf8" });
926
+ const { execSync: execSync5 } = __require("child_process");
927
+ const vmstat = execSync5("vm_stat", { encoding: "utf8" });
916
928
  const pageSize = 16384;
917
929
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
918
930
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -2069,7 +2081,7 @@ __export(employees_exports, {
2069
2081
  });
2070
2082
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir4 } from "fs/promises";
2071
2083
  import { existsSync as existsSync9, symlinkSync, readlinkSync, readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "fs";
2072
- import { execSync as execSync2 } from "child_process";
2084
+ import { execSync as execSync3 } from "child_process";
2073
2085
  import path8 from "path";
2074
2086
  import os5 from "os";
2075
2087
  function normalizeRole(role) {
@@ -2245,7 +2257,7 @@ async function normalizeRosterCase(rosterPath) {
2245
2257
  }
2246
2258
  function findExeBin() {
2247
2259
  try {
2248
- return execSync2(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
2260
+ return execSync3(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
2249
2261
  } catch {
2250
2262
  return null;
2251
2263
  }
@@ -4453,6 +4465,12 @@ async function disposeDatabase() {
4453
4465
  clearInterval(_walCheckpointTimer);
4454
4466
  _walCheckpointTimer = null;
4455
4467
  }
4468
+ if (_client) {
4469
+ try {
4470
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
4471
+ } catch {
4472
+ }
4473
+ }
4456
4474
  if (_daemonClient) {
4457
4475
  _daemonClient.close();
4458
4476
  _daemonClient = null;
@@ -7907,7 +7925,7 @@ import {
7907
7925
  readdirSync as readdirSync4,
7908
7926
  unlinkSync as unlinkSync7
7909
7927
  } from "fs";
7910
- import { execSync as execSync3 } from "child_process";
7928
+ import { execSync as execSync4 } from "child_process";
7911
7929
  import path16 from "path";
7912
7930
  import { homedir as homedir3 } from "os";
7913
7931
  function generateSessionWrappers(packageRoot, homeDir) {
@@ -8004,12 +8022,12 @@ function writeWrapper(wrapperPath, content) {
8004
8022
  }
8005
8023
  function resolveGlobalBinDir() {
8006
8024
  try {
8007
- const exeOsPath = execSync3("command -v exe-os", { encoding: "utf8", timeout: 3e3 }).trim().split("\n")[0];
8025
+ const exeOsPath = execSync4("command -v exe-os", { encoding: "utf8", timeout: 3e3 }).trim().split("\n")[0];
8008
8026
  if (exeOsPath) return path16.dirname(exeOsPath);
8009
8027
  } catch {
8010
8028
  }
8011
8029
  try {
8012
- const prefix = execSync3("npm prefix -g", { encoding: "utf8", timeout: 3e3 }).trim();
8030
+ const prefix = execSync4("npm prefix -g", { encoding: "utf8", timeout: 3e3 }).trim();
8013
8031
  if (prefix) return path16.join(prefix, "bin");
8014
8032
  } catch {
8015
8033
  }
@@ -8203,8 +8221,8 @@ function ask(rl, prompt) {
8203
8221
  function getAvailableMemoryGB2() {
8204
8222
  if (process.platform === "darwin") {
8205
8223
  try {
8206
- const { execSync: execSync4 } = __require("child_process");
8207
- const vmstat = execSync4("vm_stat", { encoding: "utf8" });
8224
+ const { execSync: execSync5 } = __require("child_process");
8225
+ const vmstat = execSync5("vm_stat", { encoding: "utf8" });
8208
8226
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
8209
8227
  const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 16384;
8210
8228
  const free = vmstat.match(/Pages free:\s+(\d+)/);