@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
@@ -1045,7 +1045,7 @@ var init_daemon_auth = __esm({
1045
1045
  // src/lib/exe-daemon-client.ts
1046
1046
  import net from "net";
1047
1047
  import os4 from "os";
1048
- import { spawn } from "child_process";
1048
+ import { spawn, execSync as execSync2 } from "child_process";
1049
1049
  import { randomUUID } from "crypto";
1050
1050
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
1051
1051
  import path5 from "path";
@@ -1075,6 +1075,14 @@ function handleData(chunk) {
1075
1075
  }
1076
1076
  }
1077
1077
  }
1078
+ function isZombie(pid) {
1079
+ try {
1080
+ const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
1081
+ return state.startsWith("Z");
1082
+ } catch {
1083
+ return false;
1084
+ }
1085
+ }
1078
1086
  function cleanupStaleFiles() {
1079
1087
  if (existsSync5(PID_PATH)) {
1080
1088
  try {
@@ -1082,7 +1090,11 @@ function cleanupStaleFiles() {
1082
1090
  if (pid > 0) {
1083
1091
  try {
1084
1092
  process.kill(pid, 0);
1085
- return;
1093
+ if (!isZombie(pid)) {
1094
+ return;
1095
+ }
1096
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
1097
+ `);
1086
1098
  } catch {
1087
1099
  }
1088
1100
  }
@@ -1110,8 +1122,8 @@ function findPackageRoot() {
1110
1122
  function getAvailableMemoryGB() {
1111
1123
  if (process.platform === "darwin") {
1112
1124
  try {
1113
- const { execSync: execSync5 } = __require("child_process");
1114
- const vmstat = execSync5("vm_stat", { encoding: "utf8" });
1125
+ const { execSync: execSync6 } = __require("child_process");
1126
+ const vmstat = execSync6("vm_stat", { encoding: "utf8" });
1115
1127
  const pageSize = 16384;
1116
1128
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1117
1129
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3046,6 +3058,12 @@ async function disposeDatabase() {
3046
3058
  clearInterval(_walCheckpointTimer);
3047
3059
  _walCheckpointTimer = null;
3048
3060
  }
3061
+ if (_client) {
3062
+ try {
3063
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
3064
+ } catch {
3065
+ }
3066
+ }
3049
3067
  if (_daemonClient) {
3050
3068
  _daemonClient.close();
3051
3069
  _daemonClient = null;
@@ -3082,7 +3100,7 @@ var init_database = __esm({
3082
3100
  // src/lib/keychain.ts
3083
3101
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3084
3102
  import { existsSync as existsSync6, statSync as statSync2 } from "fs";
3085
- import { execSync as execSync2 } from "child_process";
3103
+ import { execSync as execSync3 } from "child_process";
3086
3104
  import path6 from "path";
3087
3105
  import os5 from "os";
3088
3106
  function getKeyDir() {
@@ -3099,13 +3117,13 @@ function linuxSecretAvailable() {
3099
3117
  if (process.platform !== "linux") return false;
3100
3118
  if (linuxSecretAvailability !== null) return linuxSecretAvailability;
3101
3119
  try {
3102
- execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3120
+ execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3103
3121
  } catch {
3104
3122
  linuxSecretAvailability = false;
3105
3123
  return false;
3106
3124
  }
3107
3125
  try {
3108
- execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3126
+ execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3109
3127
  linuxSecretAvailability = true;
3110
3128
  } catch {
3111
3129
  linuxSecretAvailability = false;
@@ -3129,7 +3147,7 @@ function macKeychainGet(service = SERVICE) {
3129
3147
  if (!nativeKeychainAllowed()) return null;
3130
3148
  if (process.platform !== "darwin") return null;
3131
3149
  try {
3132
- return execSync2(
3150
+ return execSync3(
3133
3151
  `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
3134
3152
  { encoding: "utf-8", timeout: 5e3 }
3135
3153
  ).trim();
@@ -3142,13 +3160,13 @@ function macKeychainSet(value, service = SERVICE) {
3142
3160
  if (process.platform !== "darwin") return false;
3143
3161
  try {
3144
3162
  try {
3145
- execSync2(
3163
+ execSync3(
3146
3164
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3147
3165
  { timeout: 5e3 }
3148
3166
  );
3149
3167
  } catch {
3150
3168
  }
3151
- execSync2(
3169
+ execSync3(
3152
3170
  `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
3153
3171
  { timeout: 5e3 }
3154
3172
  );
@@ -3161,7 +3179,7 @@ function macKeychainDelete(service = SERVICE) {
3161
3179
  if (!nativeKeychainAllowed()) return false;
3162
3180
  if (process.platform !== "darwin") return false;
3163
3181
  try {
3164
- execSync2(
3182
+ execSync3(
3165
3183
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3166
3184
  { timeout: 5e3 }
3167
3185
  );
@@ -3173,7 +3191,7 @@ function macKeychainDelete(service = SERVICE) {
3173
3191
  function linuxSecretGet(service = SERVICE) {
3174
3192
  if (!linuxSecretAvailable()) return null;
3175
3193
  try {
3176
- return execSync2(
3194
+ return execSync3(
3177
3195
  `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3178
3196
  { encoding: "utf-8", timeout: 5e3 }
3179
3197
  ).trim();
@@ -3184,7 +3202,7 @@ function linuxSecretGet(service = SERVICE) {
3184
3202
  function linuxSecretSet(value, service = SERVICE) {
3185
3203
  if (!linuxSecretAvailable()) return false;
3186
3204
  try {
3187
- execSync2(
3205
+ execSync3(
3188
3206
  `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3189
3207
  { timeout: 5e3 }
3190
3208
  );
@@ -3197,7 +3215,7 @@ function linuxSecretDelete(service = SERVICE) {
3197
3215
  if (!nativeKeychainAllowed()) return false;
3198
3216
  if (process.platform !== "linux") return false;
3199
3217
  try {
3200
- execSync2(
3218
+ execSync3(
3201
3219
  `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3202
3220
  { timeout: 5e3 }
3203
3221
  );
@@ -5665,7 +5683,7 @@ __export(project_name_exports, {
5665
5683
  _resetCache: () => _resetCache,
5666
5684
  getProjectName: () => getProjectName
5667
5685
  });
5668
- import { execSync as execSync3 } from "child_process";
5686
+ import { execSync as execSync4 } from "child_process";
5669
5687
  import path9 from "path";
5670
5688
  function getProjectName(cwd) {
5671
5689
  const dir = cwd ?? process.cwd();
@@ -5673,7 +5691,7 @@ function getProjectName(cwd) {
5673
5691
  try {
5674
5692
  let repoRoot;
5675
5693
  try {
5676
- const gitCommonDir = execSync3("git rev-parse --path-format=absolute --git-common-dir", {
5694
+ const gitCommonDir = execSync4("git rev-parse --path-format=absolute --git-common-dir", {
5677
5695
  cwd: dir,
5678
5696
  encoding: "utf8",
5679
5697
  timeout: 2e3,
@@ -5681,7 +5699,7 @@ function getProjectName(cwd) {
5681
5699
  }).trim();
5682
5700
  repoRoot = path9.dirname(gitCommonDir);
5683
5701
  } catch {
5684
- repoRoot = execSync3("git rev-parse --show-toplevel", {
5702
+ repoRoot = execSync4("git rev-parse --show-toplevel", {
5685
5703
  cwd: dir,
5686
5704
  encoding: "utf8",
5687
5705
  timeout: 2e3,
@@ -5715,14 +5733,14 @@ var file_grep_exports = {};
5715
5733
  __export(file_grep_exports, {
5716
5734
  grepProjectFiles: () => grepProjectFiles
5717
5735
  });
5718
- import { execSync as execSync4 } from "child_process";
5736
+ import { execSync as execSync5 } from "child_process";
5719
5737
  import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync4, existsSync as existsSync9 } from "fs";
5720
5738
  import path10 from "path";
5721
5739
  import crypto2 from "crypto";
5722
5740
  function hasRipgrep() {
5723
5741
  if (_hasRg === null) {
5724
5742
  try {
5725
- execSync4("rg --version", { stdio: "ignore", timeout: 2e3 });
5743
+ execSync5("rg --version", { stdio: "ignore", timeout: 2e3 });
5726
5744
  _hasRg = true;
5727
5745
  } catch {
5728
5746
  _hasRg = false;
@@ -5788,7 +5806,7 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
5788
5806
  const globs = (patterns ?? DEFAULT_PATTERNS).map((p) => `--glob '${p}'`).join(" ");
5789
5807
  const excludes = EXCLUDE_DIRS.map((d) => `--glob '!${d}'`).join(" ");
5790
5808
  const cmd = `rg -i -c --hidden --no-config --no-ignore '${pattern.replace(/'/g, "\\'")}' . ${globs} ${excludes} --max-filesize ${MAX_FILE_SIZE} 2>/dev/null || true`;
5791
- const output = execSync4(cmd, {
5809
+ const output = execSync5(cmd, {
5792
5810
  cwd: projectRoot,
5793
5811
  encoding: "utf8",
5794
5812
  timeout: 3e3,
@@ -5803,12 +5821,12 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
5803
5821
  const matchCount = parseInt(line.slice(colonIdx + 1));
5804
5822
  if (isNaN(matchCount) || matchCount === 0) continue;
5805
5823
  try {
5806
- const firstMatch = execSync4(
5824
+ const firstMatch = execSync5(
5807
5825
  `rg -i -n --hidden '${pattern.replace(/'/g, "\\'")}' '${filePath}' --max-count 1 2>/dev/null | head -1`,
5808
5826
  { cwd: projectRoot, encoding: "utf8", timeout: 1e3 }
5809
5827
  ).trim();
5810
5828
  const lineNum = parseInt(firstMatch.split(":")[0] ?? "1");
5811
- const totalLines = execSync4(`wc -l < '${filePath}'`, {
5829
+ const totalLines = execSync5(`wc -l < '${filePath}'`, {
5812
5830
  cwd: projectRoot,
5813
5831
  encoding: "utf8",
5814
5832
  timeout: 1e3
@@ -980,7 +980,7 @@ var init_daemon_auth = __esm({
980
980
  // src/lib/exe-daemon-client.ts
981
981
  import net from "net";
982
982
  import os4 from "os";
983
- import { spawn } from "child_process";
983
+ import { spawn, execSync as execSync2 } from "child_process";
984
984
  import { randomUUID } from "crypto";
985
985
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
986
986
  import path5 from "path";
@@ -1010,6 +1010,14 @@ function handleData(chunk) {
1010
1010
  }
1011
1011
  }
1012
1012
  }
1013
+ function isZombie(pid) {
1014
+ try {
1015
+ const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
1016
+ return state.startsWith("Z");
1017
+ } catch {
1018
+ return false;
1019
+ }
1020
+ }
1013
1021
  function cleanupStaleFiles() {
1014
1022
  if (existsSync5(PID_PATH)) {
1015
1023
  try {
@@ -1017,7 +1025,11 @@ function cleanupStaleFiles() {
1017
1025
  if (pid > 0) {
1018
1026
  try {
1019
1027
  process.kill(pid, 0);
1020
- return;
1028
+ if (!isZombie(pid)) {
1029
+ return;
1030
+ }
1031
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
1032
+ `);
1021
1033
  } catch {
1022
1034
  }
1023
1035
  }
@@ -1045,8 +1057,8 @@ function findPackageRoot() {
1045
1057
  function getAvailableMemoryGB() {
1046
1058
  if (process.platform === "darwin") {
1047
1059
  try {
1048
- const { execSync: execSync4 } = __require("child_process");
1049
- const vmstat = execSync4("vm_stat", { encoding: "utf8" });
1060
+ const { execSync: execSync5 } = __require("child_process");
1061
+ const vmstat = execSync5("vm_stat", { encoding: "utf8" });
1050
1062
  const pageSize = 16384;
1051
1063
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1052
1064
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -2832,6 +2844,12 @@ async function disposeDatabase() {
2832
2844
  clearInterval(_walCheckpointTimer);
2833
2845
  _walCheckpointTimer = null;
2834
2846
  }
2847
+ if (_client) {
2848
+ try {
2849
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
2850
+ } catch {
2851
+ }
2852
+ }
2835
2853
  if (_daemonClient) {
2836
2854
  _daemonClient.close();
2837
2855
  _daemonClient = null;
@@ -3556,7 +3574,7 @@ ${p.content}`).join("\n\n");
3556
3574
  // src/lib/schedules.ts
3557
3575
  init_database();
3558
3576
  import crypto2 from "crypto";
3559
- import { execSync as execSync3 } from "child_process";
3577
+ import { execSync as execSync4 } from "child_process";
3560
3578
 
3561
3579
  // src/lib/store.ts
3562
3580
  init_memory();
@@ -3565,7 +3583,7 @@ init_database();
3565
3583
  // src/lib/keychain.ts
3566
3584
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3567
3585
  import { existsSync as existsSync6, statSync as statSync2 } from "fs";
3568
- import { execSync as execSync2 } from "child_process";
3586
+ import { execSync as execSync3 } from "child_process";
3569
3587
  import path6 from "path";
3570
3588
  import os5 from "os";
3571
3589
  var SERVICE = "exe-os";
@@ -3586,13 +3604,13 @@ function linuxSecretAvailable() {
3586
3604
  if (process.platform !== "linux") return false;
3587
3605
  if (linuxSecretAvailability !== null) return linuxSecretAvailability;
3588
3606
  try {
3589
- execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3607
+ execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3590
3608
  } catch {
3591
3609
  linuxSecretAvailability = false;
3592
3610
  return false;
3593
3611
  }
3594
3612
  try {
3595
- execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3613
+ execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3596
3614
  linuxSecretAvailability = true;
3597
3615
  } catch {
3598
3616
  linuxSecretAvailability = false;
@@ -3616,7 +3634,7 @@ function macKeychainGet(service = SERVICE) {
3616
3634
  if (!nativeKeychainAllowed()) return null;
3617
3635
  if (process.platform !== "darwin") return null;
3618
3636
  try {
3619
- return execSync2(
3637
+ return execSync3(
3620
3638
  `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
3621
3639
  { encoding: "utf-8", timeout: 5e3 }
3622
3640
  ).trim();
@@ -3629,13 +3647,13 @@ function macKeychainSet(value, service = SERVICE) {
3629
3647
  if (process.platform !== "darwin") return false;
3630
3648
  try {
3631
3649
  try {
3632
- execSync2(
3650
+ execSync3(
3633
3651
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3634
3652
  { timeout: 5e3 }
3635
3653
  );
3636
3654
  } catch {
3637
3655
  }
3638
- execSync2(
3656
+ execSync3(
3639
3657
  `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
3640
3658
  { timeout: 5e3 }
3641
3659
  );
@@ -3648,7 +3666,7 @@ function macKeychainDelete(service = SERVICE) {
3648
3666
  if (!nativeKeychainAllowed()) return false;
3649
3667
  if (process.platform !== "darwin") return false;
3650
3668
  try {
3651
- execSync2(
3669
+ execSync3(
3652
3670
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3653
3671
  { timeout: 5e3 }
3654
3672
  );
@@ -3660,7 +3678,7 @@ function macKeychainDelete(service = SERVICE) {
3660
3678
  function linuxSecretGet(service = SERVICE) {
3661
3679
  if (!linuxSecretAvailable()) return null;
3662
3680
  try {
3663
- return execSync2(
3681
+ return execSync3(
3664
3682
  `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3665
3683
  { encoding: "utf-8", timeout: 5e3 }
3666
3684
  ).trim();
@@ -3671,7 +3689,7 @@ function linuxSecretGet(service = SERVICE) {
3671
3689
  function linuxSecretSet(value, service = SERVICE) {
3672
3690
  if (!linuxSecretAvailable()) return false;
3673
3691
  try {
3674
- execSync2(
3692
+ execSync3(
3675
3693
  `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3676
3694
  { timeout: 5e3 }
3677
3695
  );
@@ -3684,7 +3702,7 @@ function linuxSecretDelete(service = SERVICE) {
3684
3702
  if (!nativeKeychainAllowed()) return false;
3685
3703
  if (process.platform !== "linux") return false;
3686
3704
  try {
3687
- execSync2(
3705
+ execSync3(
3688
3706
  `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3689
3707
  { timeout: 5e3 }
3690
3708
  );
@@ -4166,7 +4184,7 @@ function addToCrontab(id, cron, prompt, projectDir) {
4166
4184
  const cwd = projectDir ? `cd ${JSON.stringify(projectDir)} && ` : "";
4167
4185
  const escapedPrompt = prompt.replace(/"/g, '\\"');
4168
4186
  const entry = `${cron} ${cwd}claude -p --dangerously-skip-permissions "${escapedPrompt}" # exe-schedule:${id}`;
4169
- execSync3(
4187
+ execSync4(
4170
4188
  `(crontab -l 2>/dev/null; echo ${JSON.stringify(entry)}) | crontab -`,
4171
4189
  { timeout: 5e3, stdio: "ignore" }
4172
4190
  );
@@ -4177,7 +4195,7 @@ function addToCrontab(id, cron, prompt, projectDir) {
4177
4195
  function removeFromCrontab(id) {
4178
4196
  if (!isValidScheduleId(id)) return;
4179
4197
  try {
4180
- execSync3(
4198
+ execSync4(
4181
4199
  `crontab -l 2>/dev/null | grep -v "exe-schedule:${id}" | crontab -`,
4182
4200
  { timeout: 5e3, stdio: "ignore" }
4183
4201
  );
@@ -368,7 +368,7 @@ var init_daemon_auth = __esm({
368
368
  // src/lib/exe-daemon-client.ts
369
369
  import net from "net";
370
370
  import os4 from "os";
371
- import { spawn } from "child_process";
371
+ import { spawn, execSync as execSync2 } from "child_process";
372
372
  import { randomUUID } from "crypto";
373
373
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
374
374
  import path5 from "path";
@@ -398,6 +398,14 @@ function handleData(chunk) {
398
398
  }
399
399
  }
400
400
  }
401
+ function isZombie(pid) {
402
+ try {
403
+ const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
404
+ return state.startsWith("Z");
405
+ } catch {
406
+ return false;
407
+ }
408
+ }
401
409
  function cleanupStaleFiles() {
402
410
  if (existsSync5(PID_PATH)) {
403
411
  try {
@@ -405,7 +413,11 @@ function cleanupStaleFiles() {
405
413
  if (pid > 0) {
406
414
  try {
407
415
  process.kill(pid, 0);
408
- return;
416
+ if (!isZombie(pid)) {
417
+ return;
418
+ }
419
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
420
+ `);
409
421
  } catch {
410
422
  }
411
423
  }
@@ -433,8 +445,8 @@ function findPackageRoot() {
433
445
  function getAvailableMemoryGB() {
434
446
  if (process.platform === "darwin") {
435
447
  try {
436
- const { execSync: execSync2 } = __require("child_process");
437
- const vmstat = execSync2("vm_stat", { encoding: "utf8" });
448
+ const { execSync: execSync3 } = __require("child_process");
449
+ const vmstat = execSync3("vm_stat", { encoding: "utf8" });
438
450
  const pageSize = 16384;
439
451
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
440
452
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
package/dist/lib/store.js CHANGED
@@ -980,7 +980,7 @@ var init_daemon_auth = __esm({
980
980
  // src/lib/exe-daemon-client.ts
981
981
  import net from "net";
982
982
  import os4 from "os";
983
- import { spawn } from "child_process";
983
+ import { spawn, execSync as execSync2 } from "child_process";
984
984
  import { randomUUID } from "crypto";
985
985
  import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
986
986
  import path5 from "path";
@@ -1010,6 +1010,14 @@ function handleData(chunk) {
1010
1010
  }
1011
1011
  }
1012
1012
  }
1013
+ function isZombie(pid) {
1014
+ try {
1015
+ const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
1016
+ return state.startsWith("Z");
1017
+ } catch {
1018
+ return false;
1019
+ }
1020
+ }
1013
1021
  function cleanupStaleFiles() {
1014
1022
  if (existsSync5(PID_PATH)) {
1015
1023
  try {
@@ -1017,7 +1025,11 @@ function cleanupStaleFiles() {
1017
1025
  if (pid > 0) {
1018
1026
  try {
1019
1027
  process.kill(pid, 0);
1020
- return;
1028
+ if (!isZombie(pid)) {
1029
+ return;
1030
+ }
1031
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
1032
+ `);
1021
1033
  } catch {
1022
1034
  }
1023
1035
  }
@@ -1045,8 +1057,8 @@ function findPackageRoot() {
1045
1057
  function getAvailableMemoryGB() {
1046
1058
  if (process.platform === "darwin") {
1047
1059
  try {
1048
- const { execSync: execSync3 } = __require("child_process");
1049
- const vmstat = execSync3("vm_stat", { encoding: "utf8" });
1060
+ const { execSync: execSync4 } = __require("child_process");
1061
+ const vmstat = execSync4("vm_stat", { encoding: "utf8" });
1050
1062
  const pageSize = 16384;
1051
1063
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1052
1064
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -2832,6 +2844,12 @@ async function disposeDatabase() {
2832
2844
  clearInterval(_walCheckpointTimer);
2833
2845
  _walCheckpointTimer = null;
2834
2846
  }
2847
+ if (_client) {
2848
+ try {
2849
+ await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
2850
+ } catch {
2851
+ }
2852
+ }
2835
2853
  if (_daemonClient) {
2836
2854
  _daemonClient.close();
2837
2855
  _daemonClient = null;
@@ -3986,7 +4004,7 @@ init_database();
3986
4004
  // src/lib/keychain.ts
3987
4005
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3988
4006
  import { existsSync as existsSync6, statSync as statSync2 } from "fs";
3989
- import { execSync as execSync2 } from "child_process";
4007
+ import { execSync as execSync3 } from "child_process";
3990
4008
  import path6 from "path";
3991
4009
  import os5 from "os";
3992
4010
  var SERVICE = "exe-os";
@@ -4007,13 +4025,13 @@ function linuxSecretAvailable() {
4007
4025
  if (process.platform !== "linux") return false;
4008
4026
  if (linuxSecretAvailability !== null) return linuxSecretAvailability;
4009
4027
  try {
4010
- execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
4028
+ execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
4011
4029
  } catch {
4012
4030
  linuxSecretAvailability = false;
4013
4031
  return false;
4014
4032
  }
4015
4033
  try {
4016
- execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
4034
+ execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
4017
4035
  linuxSecretAvailability = true;
4018
4036
  } catch {
4019
4037
  linuxSecretAvailability = false;
@@ -4037,7 +4055,7 @@ function macKeychainGet(service = SERVICE) {
4037
4055
  if (!nativeKeychainAllowed()) return null;
4038
4056
  if (process.platform !== "darwin") return null;
4039
4057
  try {
4040
- return execSync2(
4058
+ return execSync3(
4041
4059
  `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
4042
4060
  { encoding: "utf-8", timeout: 5e3 }
4043
4061
  ).trim();
@@ -4050,13 +4068,13 @@ function macKeychainSet(value, service = SERVICE) {
4050
4068
  if (process.platform !== "darwin") return false;
4051
4069
  try {
4052
4070
  try {
4053
- execSync2(
4071
+ execSync3(
4054
4072
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
4055
4073
  { timeout: 5e3 }
4056
4074
  );
4057
4075
  } catch {
4058
4076
  }
4059
- execSync2(
4077
+ execSync3(
4060
4078
  `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
4061
4079
  { timeout: 5e3 }
4062
4080
  );
@@ -4069,7 +4087,7 @@ function macKeychainDelete(service = SERVICE) {
4069
4087
  if (!nativeKeychainAllowed()) return false;
4070
4088
  if (process.platform !== "darwin") return false;
4071
4089
  try {
4072
- execSync2(
4090
+ execSync3(
4073
4091
  `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
4074
4092
  { timeout: 5e3 }
4075
4093
  );
@@ -4081,7 +4099,7 @@ function macKeychainDelete(service = SERVICE) {
4081
4099
  function linuxSecretGet(service = SERVICE) {
4082
4100
  if (!linuxSecretAvailable()) return null;
4083
4101
  try {
4084
- return execSync2(
4102
+ return execSync3(
4085
4103
  `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
4086
4104
  { encoding: "utf-8", timeout: 5e3 }
4087
4105
  ).trim();
@@ -4092,7 +4110,7 @@ function linuxSecretGet(service = SERVICE) {
4092
4110
  function linuxSecretSet(value, service = SERVICE) {
4093
4111
  if (!linuxSecretAvailable()) return false;
4094
4112
  try {
4095
- execSync2(
4113
+ execSync3(
4096
4114
  `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
4097
4115
  { timeout: 5e3 }
4098
4116
  );
@@ -4105,7 +4123,7 @@ function linuxSecretDelete(service = SERVICE) {
4105
4123
  if (!nativeKeychainAllowed()) return false;
4106
4124
  if (process.platform !== "linux") return false;
4107
4125
  try {
4108
- execSync2(
4126
+ execSync3(
4109
4127
  `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
4110
4128
  { timeout: 5e3 }
4111
4129
  );
package/dist/lib/tasks.js CHANGED
@@ -3636,7 +3636,7 @@ var init_daemon_auth = __esm({
3636
3636
  // src/lib/exe-daemon-client.ts
3637
3637
  import net from "net";
3638
3638
  import os11 from "os";
3639
- import { spawn } from "child_process";
3639
+ import { spawn, execSync as execSync7 } from "child_process";
3640
3640
  import { randomUUID as randomUUID2 } from "crypto";
3641
3641
  import { existsSync as existsSync15, unlinkSync as unlinkSync5, readFileSync as readFileSync12, openSync, closeSync, statSync } from "fs";
3642
3642
  import path17 from "path";
@@ -3666,6 +3666,14 @@ function handleData(chunk) {
3666
3666
  }
3667
3667
  }
3668
3668
  }
3669
+ function isZombie(pid) {
3670
+ try {
3671
+ const state = execSync7(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
3672
+ return state.startsWith("Z");
3673
+ } catch {
3674
+ return false;
3675
+ }
3676
+ }
3669
3677
  function cleanupStaleFiles() {
3670
3678
  if (existsSync15(PID_PATH)) {
3671
3679
  try {
@@ -3673,7 +3681,11 @@ function cleanupStaleFiles() {
3673
3681
  if (pid > 0) {
3674
3682
  try {
3675
3683
  process.kill(pid, 0);
3676
- return;
3684
+ if (!isZombie(pid)) {
3685
+ return;
3686
+ }
3687
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
3688
+ `);
3677
3689
  } catch {
3678
3690
  }
3679
3691
  }
@@ -3701,8 +3713,8 @@ function findPackageRoot() {
3701
3713
  function getAvailableMemoryGB() {
3702
3714
  if (process.platform === "darwin") {
3703
3715
  try {
3704
- const { execSync: execSync7 } = __require("child_process");
3705
- const vmstat = execSync7("vm_stat", { encoding: "utf8" });
3716
+ const { execSync: execSync8 } = __require("child_process");
3717
+ const vmstat = execSync8("vm_stat", { encoding: "utf8" });
3706
3718
  const pageSize = 16384;
3707
3719
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
3708
3720
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -2529,7 +2529,7 @@ var init_daemon_auth = __esm({
2529
2529
  // src/lib/exe-daemon-client.ts
2530
2530
  import net from "net";
2531
2531
  import os10 from "os";
2532
- import { spawn } from "child_process";
2532
+ import { spawn, execSync as execSync6 } from "child_process";
2533
2533
  import { randomUUID as randomUUID2 } from "crypto";
2534
2534
  import { existsSync as existsSync14, unlinkSync as unlinkSync4, readFileSync as readFileSync11, openSync, closeSync, statSync } from "fs";
2535
2535
  import path16 from "path";
@@ -2559,6 +2559,14 @@ function handleData(chunk) {
2559
2559
  }
2560
2560
  }
2561
2561
  }
2562
+ function isZombie(pid) {
2563
+ try {
2564
+ const state = execSync6(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
2565
+ return state.startsWith("Z");
2566
+ } catch {
2567
+ return false;
2568
+ }
2569
+ }
2562
2570
  function cleanupStaleFiles() {
2563
2571
  if (existsSync14(PID_PATH)) {
2564
2572
  try {
@@ -2566,7 +2574,11 @@ function cleanupStaleFiles() {
2566
2574
  if (pid > 0) {
2567
2575
  try {
2568
2576
  process.kill(pid, 0);
2569
- return;
2577
+ if (!isZombie(pid)) {
2578
+ return;
2579
+ }
2580
+ process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
2581
+ `);
2570
2582
  } catch {
2571
2583
  }
2572
2584
  }
@@ -2594,8 +2606,8 @@ function findPackageRoot() {
2594
2606
  function getAvailableMemoryGB() {
2595
2607
  if (process.platform === "darwin") {
2596
2608
  try {
2597
- const { execSync: execSync7 } = __require("child_process");
2598
- const vmstat = execSync7("vm_stat", { encoding: "utf8" });
2609
+ const { execSync: execSync8 } = __require("child_process");
2610
+ const vmstat = execSync8("vm_stat", { encoding: "utf8" });
2599
2611
  const pageSize = 16384;
2600
2612
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
2601
2613
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3853,7 +3865,7 @@ __export(tmux_routing_exports, {
3853
3865
  spawnEmployee: () => spawnEmployee,
3854
3866
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
3855
3867
  });
3856
- import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
3868
+ import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
3857
3869
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync15, appendFileSync, readdirSync as readdirSync3 } from "fs";
3858
3870
  import path18 from "path";
3859
3871
  import os11 from "os";
@@ -4574,7 +4586,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4574
4586
  let booted = false;
4575
4587
  for (let i = 0; i < 30; i++) {
4576
4588
  try {
4577
- execSync6("sleep 0.5");
4589
+ execSync7("sleep 0.5");
4578
4590
  } catch {
4579
4591
  }
4580
4592
  try {