@askexenow/exe-os 0.9.30 → 0.9.32

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 (64) hide show
  1. package/dist/bin/backfill-conversations.js +135 -7
  2. package/dist/bin/backfill-responses.js +135 -7
  3. package/dist/bin/backfill-vectors.js +135 -7
  4. package/dist/bin/cleanup-stale-review-tasks.js +139 -11
  5. package/dist/bin/cli.js +812 -486
  6. package/dist/bin/exe-assign.js +135 -7
  7. package/dist/bin/exe-boot.js +422 -113
  8. package/dist/bin/exe-cloud.js +160 -9
  9. package/dist/bin/exe-dispatch.js +136 -8
  10. package/dist/bin/exe-doctor.js +255 -13
  11. package/dist/bin/exe-export-behaviors.js +136 -8
  12. package/dist/bin/exe-forget.js +136 -8
  13. package/dist/bin/exe-gateway.js +171 -24
  14. package/dist/bin/exe-heartbeat.js +141 -13
  15. package/dist/bin/exe-kill.js +140 -12
  16. package/dist/bin/exe-launch-agent.js +143 -15
  17. package/dist/bin/exe-link.js +357 -48
  18. package/dist/bin/exe-pending-messages.js +136 -8
  19. package/dist/bin/exe-pending-notifications.js +136 -8
  20. package/dist/bin/exe-pending-reviews.js +138 -10
  21. package/dist/bin/exe-review.js +136 -8
  22. package/dist/bin/exe-search.js +155 -20
  23. package/dist/bin/exe-session-cleanup.js +166 -38
  24. package/dist/bin/exe-start-codex.js +142 -14
  25. package/dist/bin/exe-start-opencode.js +140 -12
  26. package/dist/bin/exe-status.js +148 -20
  27. package/dist/bin/exe-team.js +136 -8
  28. package/dist/bin/git-sweep.js +138 -10
  29. package/dist/bin/graph-backfill.js +135 -7
  30. package/dist/bin/graph-export.js +136 -8
  31. package/dist/bin/intercom-check.js +153 -25
  32. package/dist/bin/scan-tasks.js +138 -10
  33. package/dist/bin/setup.js +447 -121
  34. package/dist/bin/shard-migrate.js +135 -7
  35. package/dist/gateway/index.js +151 -23
  36. package/dist/hooks/bug-report-worker.js +151 -23
  37. package/dist/hooks/codex-stop-task-finalizer.js +145 -17
  38. package/dist/hooks/commit-complete.js +138 -10
  39. package/dist/hooks/error-recall.js +159 -24
  40. package/dist/hooks/ingest.js +142 -14
  41. package/dist/hooks/instructions-loaded.js +136 -8
  42. package/dist/hooks/notification.js +136 -8
  43. package/dist/hooks/post-compact.js +136 -8
  44. package/dist/hooks/post-tool-combined.js +159 -24
  45. package/dist/hooks/pre-compact.js +136 -8
  46. package/dist/hooks/pre-tool-use.js +144 -16
  47. package/dist/hooks/prompt-submit.js +195 -55
  48. package/dist/hooks/session-end.js +141 -13
  49. package/dist/hooks/session-start.js +165 -30
  50. package/dist/hooks/stop.js +136 -8
  51. package/dist/hooks/subagent-stop.js +136 -8
  52. package/dist/hooks/summary-worker.js +374 -65
  53. package/dist/index.js +136 -8
  54. package/dist/lib/cloud-sync.js +355 -46
  55. package/dist/lib/consolidation.js +1 -0
  56. package/dist/lib/exe-daemon.js +469 -127
  57. package/dist/lib/hybrid-search.js +155 -20
  58. package/dist/lib/keychain.js +191 -7
  59. package/dist/lib/schedules.js +138 -10
  60. package/dist/lib/store.js +135 -7
  61. package/dist/mcp/server.js +706 -213
  62. package/dist/runtime/index.js +136 -8
  63. package/dist/tui/App.js +208 -31
  64. package/package.json +1 -1
@@ -1618,8 +1618,8 @@ function findPackageRoot() {
1618
1618
  function getAvailableMemoryGB() {
1619
1619
  if (process.platform === "darwin") {
1620
1620
  try {
1621
- const { execSync: execSync9 } = __require("child_process");
1622
- const vmstat = execSync9("vm_stat", { encoding: "utf8" });
1621
+ const { execSync: execSync10 } = __require("child_process");
1622
+ const vmstat = execSync10("vm_stat", { encoding: "utf8" });
1623
1623
  const pageSize = 16384;
1624
1624
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1625
1625
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -6529,6 +6529,7 @@ var init_task_scope = __esm({
6529
6529
  // src/lib/keychain.ts
6530
6530
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
6531
6531
  import { existsSync as existsSync15 } from "fs";
6532
+ import { execSync as execSync8 } from "child_process";
6532
6533
  import path18 from "path";
6533
6534
  import os11 from "os";
6534
6535
  function getKeyDir() {
@@ -6537,6 +6538,59 @@ function getKeyDir() {
6537
6538
  function getKeyPath() {
6538
6539
  return path18.join(getKeyDir(), "master.key");
6539
6540
  }
6541
+ function macKeychainGet() {
6542
+ if (process.platform !== "darwin") return null;
6543
+ try {
6544
+ return execSync8(
6545
+ `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
6546
+ { encoding: "utf-8", timeout: 5e3 }
6547
+ ).trim();
6548
+ } catch {
6549
+ return null;
6550
+ }
6551
+ }
6552
+ function macKeychainSet(value) {
6553
+ if (process.platform !== "darwin") return false;
6554
+ try {
6555
+ try {
6556
+ execSync8(
6557
+ `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
6558
+ { timeout: 5e3 }
6559
+ );
6560
+ } catch {
6561
+ }
6562
+ execSync8(
6563
+ `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
6564
+ { timeout: 5e3 }
6565
+ );
6566
+ return true;
6567
+ } catch {
6568
+ return false;
6569
+ }
6570
+ }
6571
+ function linuxSecretGet() {
6572
+ if (process.platform !== "linux") return null;
6573
+ try {
6574
+ return execSync8(
6575
+ `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
6576
+ { encoding: "utf-8", timeout: 5e3 }
6577
+ ).trim();
6578
+ } catch {
6579
+ return null;
6580
+ }
6581
+ }
6582
+ function linuxSecretSet(value) {
6583
+ if (process.platform !== "linux") return false;
6584
+ try {
6585
+ execSync8(
6586
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
6587
+ { timeout: 5e3 }
6588
+ );
6589
+ return true;
6590
+ } catch {
6591
+ return false;
6592
+ }
6593
+ }
6540
6594
  async function tryKeytar() {
6541
6595
  try {
6542
6596
  return await import("keytar");
@@ -6544,13 +6598,63 @@ async function tryKeytar() {
6544
6598
  return null;
6545
6599
  }
6546
6600
  }
6601
+ function deriveMachineKey() {
6602
+ try {
6603
+ const crypto7 = __require("crypto");
6604
+ const material = [
6605
+ os11.hostname(),
6606
+ os11.userInfo().username,
6607
+ os11.arch(),
6608
+ os11.platform(),
6609
+ // Machine ID on Linux (stable across reboots)
6610
+ process.platform === "linux" ? readMachineId() : ""
6611
+ ].join("|");
6612
+ return crypto7.createHash("sha256").update(material).digest();
6613
+ } catch {
6614
+ return null;
6615
+ }
6616
+ }
6617
+ function readMachineId() {
6618
+ try {
6619
+ const { readFileSync: readFileSync13 } = __require("fs");
6620
+ return readFileSync13("/etc/machine-id", "utf-8").trim();
6621
+ } catch {
6622
+ return "";
6623
+ }
6624
+ }
6625
+ function decryptWithMachineKey(encrypted, machineKey) {
6626
+ if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
6627
+ try {
6628
+ const crypto7 = __require("crypto");
6629
+ const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
6630
+ if (parts.length !== 3) return null;
6631
+ const [ivB64, tagB64, cipherB64] = parts;
6632
+ const iv = Buffer.from(ivB64, "base64");
6633
+ const authTag = Buffer.from(tagB64, "base64");
6634
+ const decipher = crypto7.createDecipheriv("aes-256-gcm", machineKey, iv);
6635
+ decipher.setAuthTag(authTag);
6636
+ let decrypted = decipher.update(cipherB64, "base64", "utf-8");
6637
+ decrypted += decipher.final("utf-8");
6638
+ return decrypted;
6639
+ } catch {
6640
+ return null;
6641
+ }
6642
+ }
6547
6643
  async function getMasterKey() {
6644
+ const nativeValue = macKeychainGet() ?? linuxSecretGet();
6645
+ if (nativeValue) {
6646
+ return Buffer.from(nativeValue, "base64");
6647
+ }
6548
6648
  const keytar = await tryKeytar();
6549
6649
  if (keytar) {
6550
6650
  try {
6551
- const stored = await keytar.getPassword(SERVICE, ACCOUNT);
6552
- if (stored) {
6553
- return Buffer.from(stored, "base64");
6651
+ const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
6652
+ if (keytarValue) {
6653
+ const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
6654
+ if (migrated) {
6655
+ process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
6656
+ }
6657
+ return Buffer.from(keytarValue, "base64");
6554
6658
  }
6555
6659
  } catch {
6556
6660
  }
@@ -6564,8 +6668,31 @@ async function getMasterKey() {
6564
6668
  return null;
6565
6669
  }
6566
6670
  try {
6567
- const content = await readFile4(keyPath, "utf-8");
6568
- return Buffer.from(content.trim(), "base64");
6671
+ const content = (await readFile4(keyPath, "utf-8")).trim();
6672
+ let b64Value;
6673
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
6674
+ const machineKey = deriveMachineKey();
6675
+ if (!machineKey) {
6676
+ process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
6677
+ return null;
6678
+ }
6679
+ const decrypted = decryptWithMachineKey(content, machineKey);
6680
+ if (!decrypted) {
6681
+ process.stderr.write(
6682
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
6683
+ );
6684
+ return null;
6685
+ }
6686
+ b64Value = decrypted;
6687
+ } else {
6688
+ b64Value = content;
6689
+ }
6690
+ const key = Buffer.from(b64Value, "base64");
6691
+ const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
6692
+ if (migrated) {
6693
+ process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
6694
+ }
6695
+ return key;
6569
6696
  } catch (err) {
6570
6697
  process.stderr.write(
6571
6698
  `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
@@ -6574,12 +6701,13 @@ async function getMasterKey() {
6574
6701
  return null;
6575
6702
  }
6576
6703
  }
6577
- var SERVICE, ACCOUNT;
6704
+ var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
6578
6705
  var init_keychain = __esm({
6579
6706
  "src/lib/keychain.ts"() {
6580
6707
  "use strict";
6581
6708
  SERVICE = "exe-mem";
6582
6709
  ACCOUNT = "master-key";
6710
+ ENCRYPTED_PREFIX = "enc:";
6583
6711
  }
6584
6712
  });
6585
6713
 
@@ -7828,7 +7956,7 @@ var init_fast_db_init = __esm({
7828
7956
  });
7829
7957
 
7830
7958
  // src/adapters/claude/hooks/commit-complete.ts
7831
- import { execSync as execSync8 } from "child_process";
7959
+ import { execSync as execSync9 } from "child_process";
7832
7960
 
7833
7961
  // src/lib/git-task-sweep.ts
7834
7962
  init_task_scope();
@@ -7906,7 +8034,7 @@ function parseGitCommitOutput(output) {
7906
8034
  }
7907
8035
  function getChangedFiles(hash) {
7908
8036
  try {
7909
- const output = execSync8(
8037
+ const output = execSync9(
7910
8038
  `git diff-tree --no-commit-id --name-only -r ${hash}`,
7911
8039
  { encoding: "utf8", timeout: 5e3 }
7912
8040
  );
@@ -1086,8 +1086,8 @@ function findPackageRoot() {
1086
1086
  function getAvailableMemoryGB() {
1087
1087
  if (process.platform === "darwin") {
1088
1088
  try {
1089
- const { execSync: execSync6 } = __require("child_process");
1090
- const vmstat = execSync6("vm_stat", { encoding: "utf8" });
1089
+ const { execSync: execSync7 } = __require("child_process");
1090
+ const vmstat = execSync7("vm_stat", { encoding: "utf8" });
1091
1091
  const pageSize = 16384;
1092
1092
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1093
1093
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -2771,6 +2771,7 @@ var init_database = __esm({
2771
2771
  // src/lib/keychain.ts
2772
2772
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2773
2773
  import { existsSync as existsSync6 } from "fs";
2774
+ import { execSync as execSync2 } from "child_process";
2774
2775
  import path6 from "path";
2775
2776
  import os5 from "os";
2776
2777
  function getKeyDir() {
@@ -2779,6 +2780,59 @@ function getKeyDir() {
2779
2780
  function getKeyPath() {
2780
2781
  return path6.join(getKeyDir(), "master.key");
2781
2782
  }
2783
+ function macKeychainGet() {
2784
+ if (process.platform !== "darwin") return null;
2785
+ try {
2786
+ return execSync2(
2787
+ `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
2788
+ { encoding: "utf-8", timeout: 5e3 }
2789
+ ).trim();
2790
+ } catch {
2791
+ return null;
2792
+ }
2793
+ }
2794
+ function macKeychainSet(value) {
2795
+ if (process.platform !== "darwin") return false;
2796
+ try {
2797
+ try {
2798
+ execSync2(
2799
+ `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
2800
+ { timeout: 5e3 }
2801
+ );
2802
+ } catch {
2803
+ }
2804
+ execSync2(
2805
+ `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
2806
+ { timeout: 5e3 }
2807
+ );
2808
+ return true;
2809
+ } catch {
2810
+ return false;
2811
+ }
2812
+ }
2813
+ function linuxSecretGet() {
2814
+ if (process.platform !== "linux") return null;
2815
+ try {
2816
+ return execSync2(
2817
+ `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
2818
+ { encoding: "utf-8", timeout: 5e3 }
2819
+ ).trim();
2820
+ } catch {
2821
+ return null;
2822
+ }
2823
+ }
2824
+ function linuxSecretSet(value) {
2825
+ if (process.platform !== "linux") return false;
2826
+ try {
2827
+ execSync2(
2828
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
2829
+ { timeout: 5e3 }
2830
+ );
2831
+ return true;
2832
+ } catch {
2833
+ return false;
2834
+ }
2835
+ }
2782
2836
  async function tryKeytar() {
2783
2837
  try {
2784
2838
  return await import("keytar");
@@ -2786,13 +2840,63 @@ async function tryKeytar() {
2786
2840
  return null;
2787
2841
  }
2788
2842
  }
2843
+ function deriveMachineKey() {
2844
+ try {
2845
+ const crypto4 = __require("crypto");
2846
+ const material = [
2847
+ os5.hostname(),
2848
+ os5.userInfo().username,
2849
+ os5.arch(),
2850
+ os5.platform(),
2851
+ // Machine ID on Linux (stable across reboots)
2852
+ process.platform === "linux" ? readMachineId() : ""
2853
+ ].join("|");
2854
+ return crypto4.createHash("sha256").update(material).digest();
2855
+ } catch {
2856
+ return null;
2857
+ }
2858
+ }
2859
+ function readMachineId() {
2860
+ try {
2861
+ const { readFileSync: readFileSync7 } = __require("fs");
2862
+ return readFileSync7("/etc/machine-id", "utf-8").trim();
2863
+ } catch {
2864
+ return "";
2865
+ }
2866
+ }
2867
+ function decryptWithMachineKey(encrypted, machineKey) {
2868
+ if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
2869
+ try {
2870
+ const crypto4 = __require("crypto");
2871
+ const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
2872
+ if (parts.length !== 3) return null;
2873
+ const [ivB64, tagB64, cipherB64] = parts;
2874
+ const iv = Buffer.from(ivB64, "base64");
2875
+ const authTag = Buffer.from(tagB64, "base64");
2876
+ const decipher = crypto4.createDecipheriv("aes-256-gcm", machineKey, iv);
2877
+ decipher.setAuthTag(authTag);
2878
+ let decrypted = decipher.update(cipherB64, "base64", "utf-8");
2879
+ decrypted += decipher.final("utf-8");
2880
+ return decrypted;
2881
+ } catch {
2882
+ return null;
2883
+ }
2884
+ }
2789
2885
  async function getMasterKey() {
2886
+ const nativeValue = macKeychainGet() ?? linuxSecretGet();
2887
+ if (nativeValue) {
2888
+ return Buffer.from(nativeValue, "base64");
2889
+ }
2790
2890
  const keytar = await tryKeytar();
2791
2891
  if (keytar) {
2792
2892
  try {
2793
- const stored = await keytar.getPassword(SERVICE, ACCOUNT);
2794
- if (stored) {
2795
- return Buffer.from(stored, "base64");
2893
+ const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
2894
+ if (keytarValue) {
2895
+ const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
2896
+ if (migrated) {
2897
+ process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
2898
+ }
2899
+ return Buffer.from(keytarValue, "base64");
2796
2900
  }
2797
2901
  } catch {
2798
2902
  }
@@ -2806,8 +2910,31 @@ async function getMasterKey() {
2806
2910
  return null;
2807
2911
  }
2808
2912
  try {
2809
- const content = await readFile3(keyPath, "utf-8");
2810
- return Buffer.from(content.trim(), "base64");
2913
+ const content = (await readFile3(keyPath, "utf-8")).trim();
2914
+ let b64Value;
2915
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
2916
+ const machineKey = deriveMachineKey();
2917
+ if (!machineKey) {
2918
+ process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
2919
+ return null;
2920
+ }
2921
+ const decrypted = decryptWithMachineKey(content, machineKey);
2922
+ if (!decrypted) {
2923
+ process.stderr.write(
2924
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
2925
+ );
2926
+ return null;
2927
+ }
2928
+ b64Value = decrypted;
2929
+ } else {
2930
+ b64Value = content;
2931
+ }
2932
+ const key = Buffer.from(b64Value, "base64");
2933
+ const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
2934
+ if (migrated) {
2935
+ process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
2936
+ }
2937
+ return key;
2811
2938
  } catch (err) {
2812
2939
  process.stderr.write(
2813
2940
  `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
@@ -2816,12 +2943,13 @@ async function getMasterKey() {
2816
2943
  return null;
2817
2944
  }
2818
2945
  }
2819
- var SERVICE, ACCOUNT;
2946
+ var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
2820
2947
  var init_keychain = __esm({
2821
2948
  "src/lib/keychain.ts"() {
2822
2949
  "use strict";
2823
2950
  SERVICE = "exe-mem";
2824
2951
  ACCOUNT = "master-key";
2952
+ ENCRYPTED_PREFIX = "enc:";
2825
2953
  }
2826
2954
  });
2827
2955
 
@@ -4344,7 +4472,7 @@ __export(project_name_exports, {
4344
4472
  _resetCache: () => _resetCache,
4345
4473
  getProjectName: () => getProjectName
4346
4474
  });
4347
- import { execSync as execSync2 } from "child_process";
4475
+ import { execSync as execSync3 } from "child_process";
4348
4476
  import path9 from "path";
4349
4477
  function getProjectName(cwd) {
4350
4478
  const dir = cwd ?? process.cwd();
@@ -4352,7 +4480,7 @@ function getProjectName(cwd) {
4352
4480
  try {
4353
4481
  let repoRoot;
4354
4482
  try {
4355
- const gitCommonDir = execSync2("git rev-parse --path-format=absolute --git-common-dir", {
4483
+ const gitCommonDir = execSync3("git rev-parse --path-format=absolute --git-common-dir", {
4356
4484
  cwd: dir,
4357
4485
  encoding: "utf8",
4358
4486
  timeout: 2e3,
@@ -4360,7 +4488,7 @@ function getProjectName(cwd) {
4360
4488
  }).trim();
4361
4489
  repoRoot = path9.dirname(gitCommonDir);
4362
4490
  } catch {
4363
- repoRoot = execSync2("git rev-parse --show-toplevel", {
4491
+ repoRoot = execSync3("git rev-parse --show-toplevel", {
4364
4492
  cwd: dir,
4365
4493
  encoding: "utf8",
4366
4494
  timeout: 2e3,
@@ -4394,14 +4522,14 @@ var file_grep_exports = {};
4394
4522
  __export(file_grep_exports, {
4395
4523
  grepProjectFiles: () => grepProjectFiles
4396
4524
  });
4397
- import { execSync as execSync3 } from "child_process";
4525
+ import { execSync as execSync4 } from "child_process";
4398
4526
  import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync2, existsSync as existsSync9 } from "fs";
4399
4527
  import path10 from "path";
4400
4528
  import crypto3 from "crypto";
4401
4529
  function hasRipgrep() {
4402
4530
  if (_hasRg === null) {
4403
4531
  try {
4404
- execSync3("rg --version", { stdio: "ignore", timeout: 2e3 });
4532
+ execSync4("rg --version", { stdio: "ignore", timeout: 2e3 });
4405
4533
  _hasRg = true;
4406
4534
  } catch {
4407
4535
  _hasRg = false;
@@ -4467,7 +4595,7 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
4467
4595
  const globs = (patterns ?? DEFAULT_PATTERNS).map((p) => `--glob '${p}'`).join(" ");
4468
4596
  const excludes = EXCLUDE_DIRS.map((d) => `--glob '!${d}'`).join(" ");
4469
4597
  const cmd = `rg -i -c --hidden --no-config --no-ignore '${pattern.replace(/'/g, "\\'")}' . ${globs} ${excludes} --max-filesize ${MAX_FILE_SIZE} 2>/dev/null || true`;
4470
- const output = execSync3(cmd, {
4598
+ const output = execSync4(cmd, {
4471
4599
  cwd: projectRoot,
4472
4600
  encoding: "utf8",
4473
4601
  timeout: 3e3,
@@ -4482,12 +4610,12 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
4482
4610
  const matchCount = parseInt(line.slice(colonIdx + 1));
4483
4611
  if (isNaN(matchCount) || matchCount === 0) continue;
4484
4612
  try {
4485
- const firstMatch = execSync3(
4613
+ const firstMatch = execSync4(
4486
4614
  `rg -i -n --hidden '${pattern.replace(/'/g, "\\'")}' '${filePath}' --max-count 1 2>/dev/null | head -1`,
4487
4615
  { cwd: projectRoot, encoding: "utf8", timeout: 1e3 }
4488
4616
  ).trim();
4489
4617
  const lineNum = parseInt(firstMatch.split(":")[0] ?? "1");
4490
- const totalLines = execSync3(`wc -l < '${filePath}'`, {
4618
+ const totalLines = execSync4(`wc -l < '${filePath}'`, {
4491
4619
  cwd: projectRoot,
4492
4620
  encoding: "utf8",
4493
4621
  timeout: 1e3
@@ -5116,10 +5244,17 @@ async function applyEntityBoost(results, query, client) {
5116
5244
  if (ENTITY_BOOST_WEIGHT === 0 || results.length === 0) {
5117
5245
  return emptyResult;
5118
5246
  }
5119
- console.time("entity-boost");
5247
+ const debugStart = process.env.EXE_DEBUG_HOOKS ? performance.now() : 0;
5248
+ const debugEnd = () => {
5249
+ if (!process.env.EXE_DEBUG_HOOKS) return;
5250
+ process.stderr.write(
5251
+ `[entity-boost] ${(performance.now() - debugStart).toFixed(3)}ms
5252
+ `
5253
+ );
5254
+ };
5120
5255
  const entities = await matchEntities(query, client);
5121
5256
  if (entities.length === 0) {
5122
- console.timeEnd("entity-boost");
5257
+ debugEnd();
5123
5258
  return emptyResult;
5124
5259
  }
5125
5260
  const boostMap = /* @__PURE__ */ new Map();
@@ -5141,7 +5276,7 @@ async function applyEntityBoost(results, query, client) {
5141
5276
  await traverseAndScore(entities, client, boostMap, resultIds, graphContextMap);
5142
5277
  await applyHyperedgeBoost(entities, client, boostMap, resultIds);
5143
5278
  if (boostMap.size === 0) {
5144
- console.timeEnd("entity-boost");
5279
+ debugEnd();
5145
5280
  return emptyResult;
5146
5281
  }
5147
5282
  const scored = results.map((r, i) => ({
@@ -5152,7 +5287,7 @@ async function applyEntityBoost(results, query, client) {
5152
5287
  scored.sort(
5153
5288
  (a, b) => b.baseScore + b.entityBoost - (a.baseScore + a.entityBoost)
5154
5289
  );
5155
- console.timeEnd("entity-boost");
5290
+ debugEnd();
5156
5291
  return {
5157
5292
  results: scored.map((s) => s.record),
5158
5293
  graphContext: graphContextMap
@@ -5894,11 +6029,11 @@ init_database();
5894
6029
  // src/lib/active-agent.ts
5895
6030
  init_config();
5896
6031
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, unlinkSync as unlinkSync3, readdirSync as readdirSync3 } from "fs";
5897
- import { execSync as execSync5 } from "child_process";
6032
+ import { execSync as execSync6 } from "child_process";
5898
6033
  import path11 from "path";
5899
6034
 
5900
6035
  // src/lib/session-key.ts
5901
- import { execSync as execSync4 } from "child_process";
6036
+ import { execSync as execSync5 } from "child_process";
5902
6037
  var _cached2 = null;
5903
6038
  var _cachedRuntime = null;
5904
6039
  var RUNTIME_COMMANDS = {
@@ -5924,7 +6059,7 @@ function resolveRuntimeProcess() {
5924
6059
  let pid = process.ppid;
5925
6060
  for (let i = 0; i < 10; i++) {
5926
6061
  try {
5927
- const info = execSync4(`ps -p ${pid} -o ppid=,comm=`, {
6062
+ const info = execSync5(`ps -p ${pid} -o ppid=,comm=`, {
5928
6063
  encoding: "utf8",
5929
6064
  timeout: 2e3
5930
6065
  }).trim();
@@ -6037,7 +6172,7 @@ function getActiveAgent() {
6037
6172
  } catch {
6038
6173
  }
6039
6174
  try {
6040
- const sessionName = execSync5(
6175
+ const sessionName = execSync6(
6041
6176
  "tmux display-message -p '#{session_name}' 2>/dev/null",
6042
6177
  { encoding: "utf8", timeout: 2e3 }
6043
6178
  ).trim();