@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
@@ -1337,8 +1337,8 @@ function findPackageRoot() {
1337
1337
  function getAvailableMemoryGB() {
1338
1338
  if (process.platform === "darwin") {
1339
1339
  try {
1340
- const { execSync: execSync5 } = __require("child_process");
1341
- const vmstat = execSync5("vm_stat", { encoding: "utf8" });
1340
+ const { execSync: execSync6 } = __require("child_process");
1341
+ const vmstat = execSync6("vm_stat", { encoding: "utf8" });
1342
1342
  const pageSize = 16384;
1343
1343
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1344
1344
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3202,6 +3202,7 @@ var init_task_scope = __esm({
3202
3202
  // src/lib/keychain.ts
3203
3203
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3204
3204
  import { existsSync as existsSync11 } from "fs";
3205
+ import { execSync as execSync5 } from "child_process";
3205
3206
  import path13 from "path";
3206
3207
  import os9 from "os";
3207
3208
  function getKeyDir() {
@@ -3210,6 +3211,59 @@ function getKeyDir() {
3210
3211
  function getKeyPath() {
3211
3212
  return path13.join(getKeyDir(), "master.key");
3212
3213
  }
3214
+ function macKeychainGet() {
3215
+ if (process.platform !== "darwin") return null;
3216
+ try {
3217
+ return execSync5(
3218
+ `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
3219
+ { encoding: "utf-8", timeout: 5e3 }
3220
+ ).trim();
3221
+ } catch {
3222
+ return null;
3223
+ }
3224
+ }
3225
+ function macKeychainSet(value) {
3226
+ if (process.platform !== "darwin") return false;
3227
+ try {
3228
+ try {
3229
+ execSync5(
3230
+ `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
3231
+ { timeout: 5e3 }
3232
+ );
3233
+ } catch {
3234
+ }
3235
+ execSync5(
3236
+ `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
3237
+ { timeout: 5e3 }
3238
+ );
3239
+ return true;
3240
+ } catch {
3241
+ return false;
3242
+ }
3243
+ }
3244
+ function linuxSecretGet() {
3245
+ if (process.platform !== "linux") return null;
3246
+ try {
3247
+ return execSync5(
3248
+ `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
3249
+ { encoding: "utf-8", timeout: 5e3 }
3250
+ ).trim();
3251
+ } catch {
3252
+ return null;
3253
+ }
3254
+ }
3255
+ function linuxSecretSet(value) {
3256
+ if (process.platform !== "linux") return false;
3257
+ try {
3258
+ execSync5(
3259
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
3260
+ { timeout: 5e3 }
3261
+ );
3262
+ return true;
3263
+ } catch {
3264
+ return false;
3265
+ }
3266
+ }
3213
3267
  async function tryKeytar() {
3214
3268
  try {
3215
3269
  return await import("keytar");
@@ -3217,13 +3271,63 @@ async function tryKeytar() {
3217
3271
  return null;
3218
3272
  }
3219
3273
  }
3274
+ function deriveMachineKey() {
3275
+ try {
3276
+ const crypto2 = __require("crypto");
3277
+ const material = [
3278
+ os9.hostname(),
3279
+ os9.userInfo().username,
3280
+ os9.arch(),
3281
+ os9.platform(),
3282
+ // Machine ID on Linux (stable across reboots)
3283
+ process.platform === "linux" ? readMachineId() : ""
3284
+ ].join("|");
3285
+ return crypto2.createHash("sha256").update(material).digest();
3286
+ } catch {
3287
+ return null;
3288
+ }
3289
+ }
3290
+ function readMachineId() {
3291
+ try {
3292
+ const { readFileSync: readFileSync11 } = __require("fs");
3293
+ return readFileSync11("/etc/machine-id", "utf-8").trim();
3294
+ } catch {
3295
+ return "";
3296
+ }
3297
+ }
3298
+ function decryptWithMachineKey(encrypted, machineKey) {
3299
+ if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3300
+ try {
3301
+ const crypto2 = __require("crypto");
3302
+ const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3303
+ if (parts.length !== 3) return null;
3304
+ const [ivB64, tagB64, cipherB64] = parts;
3305
+ const iv = Buffer.from(ivB64, "base64");
3306
+ const authTag = Buffer.from(tagB64, "base64");
3307
+ const decipher = crypto2.createDecipheriv("aes-256-gcm", machineKey, iv);
3308
+ decipher.setAuthTag(authTag);
3309
+ let decrypted = decipher.update(cipherB64, "base64", "utf-8");
3310
+ decrypted += decipher.final("utf-8");
3311
+ return decrypted;
3312
+ } catch {
3313
+ return null;
3314
+ }
3315
+ }
3220
3316
  async function getMasterKey() {
3317
+ const nativeValue = macKeychainGet() ?? linuxSecretGet();
3318
+ if (nativeValue) {
3319
+ return Buffer.from(nativeValue, "base64");
3320
+ }
3221
3321
  const keytar = await tryKeytar();
3222
3322
  if (keytar) {
3223
3323
  try {
3224
- const stored = await keytar.getPassword(SERVICE, ACCOUNT);
3225
- if (stored) {
3226
- return Buffer.from(stored, "base64");
3324
+ const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
3325
+ if (keytarValue) {
3326
+ const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
3327
+ if (migrated) {
3328
+ process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
3329
+ }
3330
+ return Buffer.from(keytarValue, "base64");
3227
3331
  }
3228
3332
  } catch {
3229
3333
  }
@@ -3237,8 +3341,31 @@ async function getMasterKey() {
3237
3341
  return null;
3238
3342
  }
3239
3343
  try {
3240
- const content = await readFile3(keyPath, "utf-8");
3241
- return Buffer.from(content.trim(), "base64");
3344
+ const content = (await readFile3(keyPath, "utf-8")).trim();
3345
+ let b64Value;
3346
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
3347
+ const machineKey = deriveMachineKey();
3348
+ if (!machineKey) {
3349
+ process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
3350
+ return null;
3351
+ }
3352
+ const decrypted = decryptWithMachineKey(content, machineKey);
3353
+ if (!decrypted) {
3354
+ process.stderr.write(
3355
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
3356
+ );
3357
+ return null;
3358
+ }
3359
+ b64Value = decrypted;
3360
+ } else {
3361
+ b64Value = content;
3362
+ }
3363
+ const key = Buffer.from(b64Value, "base64");
3364
+ const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
3365
+ if (migrated) {
3366
+ process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
3367
+ }
3368
+ return key;
3242
3369
  } catch (err) {
3243
3370
  process.stderr.write(
3244
3371
  `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
@@ -3247,12 +3374,13 @@ async function getMasterKey() {
3247
3374
  return null;
3248
3375
  }
3249
3376
  }
3250
- var SERVICE, ACCOUNT;
3377
+ var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
3251
3378
  var init_keychain = __esm({
3252
3379
  "src/lib/keychain.ts"() {
3253
3380
  "use strict";
3254
3381
  SERVICE = "exe-mem";
3255
3382
  ACCOUNT = "master-key";
3383
+ ENCRYPTED_PREFIX = "enc:";
3256
3384
  }
3257
3385
  });
3258
3386
 
@@ -1261,8 +1261,8 @@ function findPackageRoot() {
1261
1261
  function getAvailableMemoryGB() {
1262
1262
  if (process.platform === "darwin") {
1263
1263
  try {
1264
- const { execSync: execSync6 } = __require("child_process");
1265
- const vmstat = execSync6("vm_stat", { encoding: "utf8" });
1264
+ const { execSync: execSync7 } = __require("child_process");
1265
+ const vmstat = execSync7("vm_stat", { encoding: "utf8" });
1266
1266
  const pageSize = 16384;
1267
1267
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1268
1268
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -2946,6 +2946,7 @@ var init_database = __esm({
2946
2946
  // src/lib/keychain.ts
2947
2947
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
2948
2948
  import { existsSync as existsSync6 } from "fs";
2949
+ import { execSync as execSync2 } from "child_process";
2949
2950
  import path6 from "path";
2950
2951
  import os5 from "os";
2951
2952
  function getKeyDir() {
@@ -2954,6 +2955,59 @@ function getKeyDir() {
2954
2955
  function getKeyPath() {
2955
2956
  return path6.join(getKeyDir(), "master.key");
2956
2957
  }
2958
+ function macKeychainGet() {
2959
+ if (process.platform !== "darwin") return null;
2960
+ try {
2961
+ return execSync2(
2962
+ `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
2963
+ { encoding: "utf-8", timeout: 5e3 }
2964
+ ).trim();
2965
+ } catch {
2966
+ return null;
2967
+ }
2968
+ }
2969
+ function macKeychainSet(value) {
2970
+ if (process.platform !== "darwin") return false;
2971
+ try {
2972
+ try {
2973
+ execSync2(
2974
+ `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
2975
+ { timeout: 5e3 }
2976
+ );
2977
+ } catch {
2978
+ }
2979
+ execSync2(
2980
+ `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
2981
+ { timeout: 5e3 }
2982
+ );
2983
+ return true;
2984
+ } catch {
2985
+ return false;
2986
+ }
2987
+ }
2988
+ function linuxSecretGet() {
2989
+ if (process.platform !== "linux") return null;
2990
+ try {
2991
+ return execSync2(
2992
+ `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
2993
+ { encoding: "utf-8", timeout: 5e3 }
2994
+ ).trim();
2995
+ } catch {
2996
+ return null;
2997
+ }
2998
+ }
2999
+ function linuxSecretSet(value) {
3000
+ if (process.platform !== "linux") return false;
3001
+ try {
3002
+ execSync2(
3003
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
3004
+ { timeout: 5e3 }
3005
+ );
3006
+ return true;
3007
+ } catch {
3008
+ return false;
3009
+ }
3010
+ }
2957
3011
  async function tryKeytar() {
2958
3012
  try {
2959
3013
  return await import("keytar");
@@ -2961,13 +3015,63 @@ async function tryKeytar() {
2961
3015
  return null;
2962
3016
  }
2963
3017
  }
3018
+ function deriveMachineKey() {
3019
+ try {
3020
+ const crypto4 = __require("crypto");
3021
+ const material = [
3022
+ os5.hostname(),
3023
+ os5.userInfo().username,
3024
+ os5.arch(),
3025
+ os5.platform(),
3026
+ // Machine ID on Linux (stable across reboots)
3027
+ process.platform === "linux" ? readMachineId() : ""
3028
+ ].join("|");
3029
+ return crypto4.createHash("sha256").update(material).digest();
3030
+ } catch {
3031
+ return null;
3032
+ }
3033
+ }
3034
+ function readMachineId() {
3035
+ try {
3036
+ const { readFileSync: readFileSync8 } = __require("fs");
3037
+ return readFileSync8("/etc/machine-id", "utf-8").trim();
3038
+ } catch {
3039
+ return "";
3040
+ }
3041
+ }
3042
+ function decryptWithMachineKey(encrypted, machineKey) {
3043
+ if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3044
+ try {
3045
+ const crypto4 = __require("crypto");
3046
+ const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3047
+ if (parts.length !== 3) return null;
3048
+ const [ivB64, tagB64, cipherB64] = parts;
3049
+ const iv = Buffer.from(ivB64, "base64");
3050
+ const authTag = Buffer.from(tagB64, "base64");
3051
+ const decipher = crypto4.createDecipheriv("aes-256-gcm", machineKey, iv);
3052
+ decipher.setAuthTag(authTag);
3053
+ let decrypted = decipher.update(cipherB64, "base64", "utf-8");
3054
+ decrypted += decipher.final("utf-8");
3055
+ return decrypted;
3056
+ } catch {
3057
+ return null;
3058
+ }
3059
+ }
2964
3060
  async function getMasterKey() {
3061
+ const nativeValue = macKeychainGet() ?? linuxSecretGet();
3062
+ if (nativeValue) {
3063
+ return Buffer.from(nativeValue, "base64");
3064
+ }
2965
3065
  const keytar = await tryKeytar();
2966
3066
  if (keytar) {
2967
3067
  try {
2968
- const stored = await keytar.getPassword(SERVICE, ACCOUNT);
2969
- if (stored) {
2970
- return Buffer.from(stored, "base64");
3068
+ const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
3069
+ if (keytarValue) {
3070
+ const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
3071
+ if (migrated) {
3072
+ process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
3073
+ }
3074
+ return Buffer.from(keytarValue, "base64");
2971
3075
  }
2972
3076
  } catch {
2973
3077
  }
@@ -2981,8 +3085,31 @@ async function getMasterKey() {
2981
3085
  return null;
2982
3086
  }
2983
3087
  try {
2984
- const content = await readFile3(keyPath, "utf-8");
2985
- return Buffer.from(content.trim(), "base64");
3088
+ const content = (await readFile3(keyPath, "utf-8")).trim();
3089
+ let b64Value;
3090
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
3091
+ const machineKey = deriveMachineKey();
3092
+ if (!machineKey) {
3093
+ process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
3094
+ return null;
3095
+ }
3096
+ const decrypted = decryptWithMachineKey(content, machineKey);
3097
+ if (!decrypted) {
3098
+ process.stderr.write(
3099
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
3100
+ );
3101
+ return null;
3102
+ }
3103
+ b64Value = decrypted;
3104
+ } else {
3105
+ b64Value = content;
3106
+ }
3107
+ const key = Buffer.from(b64Value, "base64");
3108
+ const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
3109
+ if (migrated) {
3110
+ process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
3111
+ }
3112
+ return key;
2986
3113
  } catch (err) {
2987
3114
  process.stderr.write(
2988
3115
  `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
@@ -2991,12 +3118,13 @@ async function getMasterKey() {
2991
3118
  return null;
2992
3119
  }
2993
3120
  }
2994
- var SERVICE, ACCOUNT;
3121
+ var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
2995
3122
  var init_keychain = __esm({
2996
3123
  "src/lib/keychain.ts"() {
2997
3124
  "use strict";
2998
3125
  SERVICE = "exe-mem";
2999
3126
  ACCOUNT = "master-key";
3127
+ ENCRYPTED_PREFIX = "enc:";
3000
3128
  }
3001
3129
  });
3002
3130
 
@@ -4519,7 +4647,7 @@ __export(project_name_exports, {
4519
4647
  _resetCache: () => _resetCache,
4520
4648
  getProjectName: () => getProjectName
4521
4649
  });
4522
- import { execSync as execSync2 } from "child_process";
4650
+ import { execSync as execSync3 } from "child_process";
4523
4651
  import path9 from "path";
4524
4652
  function getProjectName(cwd) {
4525
4653
  const dir = cwd ?? process.cwd();
@@ -4527,7 +4655,7 @@ function getProjectName(cwd) {
4527
4655
  try {
4528
4656
  let repoRoot;
4529
4657
  try {
4530
- const gitCommonDir = execSync2("git rev-parse --path-format=absolute --git-common-dir", {
4658
+ const gitCommonDir = execSync3("git rev-parse --path-format=absolute --git-common-dir", {
4531
4659
  cwd: dir,
4532
4660
  encoding: "utf8",
4533
4661
  timeout: 2e3,
@@ -4535,7 +4663,7 @@ function getProjectName(cwd) {
4535
4663
  }).trim();
4536
4664
  repoRoot = path9.dirname(gitCommonDir);
4537
4665
  } catch {
4538
- repoRoot = execSync2("git rev-parse --show-toplevel", {
4666
+ repoRoot = execSync3("git rev-parse --show-toplevel", {
4539
4667
  cwd: dir,
4540
4668
  encoding: "utf8",
4541
4669
  timeout: 2e3,
@@ -4569,14 +4697,14 @@ var file_grep_exports = {};
4569
4697
  __export(file_grep_exports, {
4570
4698
  grepProjectFiles: () => grepProjectFiles
4571
4699
  });
4572
- import { execSync as execSync3 } from "child_process";
4700
+ import { execSync as execSync4 } from "child_process";
4573
4701
  import { readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync2, existsSync as existsSync9 } from "fs";
4574
4702
  import path10 from "path";
4575
4703
  import crypto3 from "crypto";
4576
4704
  function hasRipgrep() {
4577
4705
  if (_hasRg === null) {
4578
4706
  try {
4579
- execSync3("rg --version", { stdio: "ignore", timeout: 2e3 });
4707
+ execSync4("rg --version", { stdio: "ignore", timeout: 2e3 });
4580
4708
  _hasRg = true;
4581
4709
  } catch {
4582
4710
  _hasRg = false;
@@ -4642,7 +4770,7 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
4642
4770
  const globs = (patterns ?? DEFAULT_PATTERNS).map((p) => `--glob '${p}'`).join(" ");
4643
4771
  const excludes = EXCLUDE_DIRS.map((d) => `--glob '!${d}'`).join(" ");
4644
4772
  const cmd = `rg -i -c --hidden --no-config --no-ignore '${pattern.replace(/'/g, "\\'")}' . ${globs} ${excludes} --max-filesize ${MAX_FILE_SIZE} 2>/dev/null || true`;
4645
- const output = execSync3(cmd, {
4773
+ const output = execSync4(cmd, {
4646
4774
  cwd: projectRoot,
4647
4775
  encoding: "utf8",
4648
4776
  timeout: 3e3,
@@ -4657,12 +4785,12 @@ function grepWithRipgrep(pattern, projectRoot, patterns) {
4657
4785
  const matchCount = parseInt(line.slice(colonIdx + 1));
4658
4786
  if (isNaN(matchCount) || matchCount === 0) continue;
4659
4787
  try {
4660
- const firstMatch = execSync3(
4788
+ const firstMatch = execSync4(
4661
4789
  `rg -i -n --hidden '${pattern.replace(/'/g, "\\'")}' '${filePath}' --max-count 1 2>/dev/null | head -1`,
4662
4790
  { cwd: projectRoot, encoding: "utf8", timeout: 1e3 }
4663
4791
  ).trim();
4664
4792
  const lineNum = parseInt(firstMatch.split(":")[0] ?? "1");
4665
- const totalLines = execSync3(`wc -l < '${filePath}'`, {
4793
+ const totalLines = execSync4(`wc -l < '${filePath}'`, {
4666
4794
  cwd: projectRoot,
4667
4795
  encoding: "utf8",
4668
4796
  timeout: 1e3
@@ -5291,10 +5419,17 @@ async function applyEntityBoost(results, query, client) {
5291
5419
  if (ENTITY_BOOST_WEIGHT === 0 || results.length === 0) {
5292
5420
  return emptyResult;
5293
5421
  }
5294
- console.time("entity-boost");
5422
+ const debugStart = process.env.EXE_DEBUG_HOOKS ? performance.now() : 0;
5423
+ const debugEnd = () => {
5424
+ if (!process.env.EXE_DEBUG_HOOKS) return;
5425
+ process.stderr.write(
5426
+ `[entity-boost] ${(performance.now() - debugStart).toFixed(3)}ms
5427
+ `
5428
+ );
5429
+ };
5295
5430
  const entities = await matchEntities(query, client);
5296
5431
  if (entities.length === 0) {
5297
- console.timeEnd("entity-boost");
5432
+ debugEnd();
5298
5433
  return emptyResult;
5299
5434
  }
5300
5435
  const boostMap = /* @__PURE__ */ new Map();
@@ -5316,7 +5451,7 @@ async function applyEntityBoost(results, query, client) {
5316
5451
  await traverseAndScore(entities, client, boostMap, resultIds, graphContextMap);
5317
5452
  await applyHyperedgeBoost(entities, client, boostMap, resultIds);
5318
5453
  if (boostMap.size === 0) {
5319
- console.timeEnd("entity-boost");
5454
+ debugEnd();
5320
5455
  return emptyResult;
5321
5456
  }
5322
5457
  const scored = results.map((r, i) => ({
@@ -5327,7 +5462,7 @@ async function applyEntityBoost(results, query, client) {
5327
5462
  scored.sort(
5328
5463
  (a, b) => b.baseScore + b.entityBoost - (a.baseScore + a.entityBoost)
5329
5464
  );
5330
- console.timeEnd("entity-boost");
5465
+ debugEnd();
5331
5466
  return {
5332
5467
  results: scored.map((s) => s.record),
5333
5468
  graphContext: graphContextMap
@@ -6240,7 +6375,7 @@ var init_memory_queue_client = __esm({
6240
6375
  });
6241
6376
 
6242
6377
  // src/lib/session-key.ts
6243
- import { execSync as execSync4 } from "child_process";
6378
+ import { execSync as execSync5 } from "child_process";
6244
6379
  function normalizeCommand(command) {
6245
6380
  const trimmed = command.trim().toLowerCase();
6246
6381
  const parts = trimmed.split(/[\\/]/);
@@ -6259,7 +6394,7 @@ function resolveRuntimeProcess() {
6259
6394
  let pid = process.ppid;
6260
6395
  for (let i = 0; i < 10; i++) {
6261
6396
  try {
6262
- const info = execSync4(`ps -p ${pid} -o ppid=,comm=`, {
6397
+ const info = execSync5(`ps -p ${pid} -o ppid=,comm=`, {
6263
6398
  encoding: "utf8",
6264
6399
  timeout: 2e3
6265
6400
  }).trim();
@@ -6309,7 +6444,7 @@ var init_session_key = __esm({
6309
6444
 
6310
6445
  // src/lib/active-agent.ts
6311
6446
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
6312
- import { execSync as execSync5 } from "child_process";
6447
+ import { execSync as execSync6 } from "child_process";
6313
6448
  import path12 from "path";
6314
6449
  function isNameWithOptionalInstance(candidate, baseName) {
6315
6450
  if (candidate === baseName) return true;
@@ -6401,7 +6536,7 @@ function getActiveAgent() {
6401
6536
  } catch {
6402
6537
  }
6403
6538
  try {
6404
- const sessionName = execSync5(
6539
+ const sessionName = execSync6(
6405
6540
  "tmux display-message -p '#{session_name}' 2>/dev/null",
6406
6541
  { encoding: "utf8", timeout: 2e3 }
6407
6542
  ).trim();