@adhdev/daemon-core 0.9.82-rc.333 → 0.9.82-rc.334

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.
package/dist/index.js CHANGED
@@ -316,10 +316,10 @@ function readInjected(value) {
316
316
  }
317
317
  function getDaemonBuildInfo() {
318
318
  if (cached) return cached;
319
- const commit = readInjected(true ? "5d9635b2a6476691469ecfe32b26a17e13484b2b" : void 0) ?? "unknown";
320
- const commitShort = readInjected(true ? "5d9635b2" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
321
- const version = readInjected(true ? "0.9.82-rc.333" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
322
- const builtAt = readInjected(true ? "2026-06-20T02:23:56.856Z" : void 0);
319
+ const commit = readInjected(true ? "9e5ae5d2814077a6bf9e982b17066ca2051da97b" : void 0) ?? "unknown";
320
+ const commitShort = readInjected(true ? "9e5ae5d2" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
321
+ const version = readInjected(true ? "0.9.82-rc.334" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
322
+ const builtAt = readInjected(true ? "2026-06-20T03:55:49.426Z" : void 0);
323
323
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
324
324
  return cached;
325
325
  }
@@ -3260,6 +3260,297 @@ var init_mesh_ledger = __esm({
3260
3260
  }
3261
3261
  });
3262
3262
 
3263
+ // src/logging/async-batch-writer.ts
3264
+ var fs3, AsyncBatchWriter;
3265
+ var init_async_batch_writer = __esm({
3266
+ "src/logging/async-batch-writer.ts"() {
3267
+ "use strict";
3268
+ fs3 = __toESM(require("fs"));
3269
+ AsyncBatchWriter = class {
3270
+ // Maps filePath -> string buffer
3271
+ static buffers = /* @__PURE__ */ new Map();
3272
+ static writePromises = /* @__PURE__ */ new Map();
3273
+ static flushTimer = null;
3274
+ /**
3275
+ * Queues data to be written to a file asynchronously in a batch.
3276
+ */
3277
+ static write(filePath, data) {
3278
+ let buf = this.buffers.get(filePath);
3279
+ if (!buf) {
3280
+ buf = [];
3281
+ this.buffers.set(filePath, buf);
3282
+ }
3283
+ buf.push(data);
3284
+ if (!this.flushTimer) {
3285
+ this.flushTimer = setTimeout(() => {
3286
+ this.flushTimer = null;
3287
+ this.flushAll();
3288
+ }, 50);
3289
+ }
3290
+ }
3291
+ static async flushAll() {
3292
+ const entries = Array.from(this.buffers.entries());
3293
+ this.buffers.clear();
3294
+ for (const [filePath, buffer] of entries) {
3295
+ const dataToWrite = buffer.join("");
3296
+ const doWrite = async () => {
3297
+ try {
3298
+ const prevPromise = this.writePromises.get(filePath);
3299
+ if (prevPromise) await prevPromise;
3300
+ await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
3301
+ } catch {
3302
+ }
3303
+ };
3304
+ const writePromise = doWrite();
3305
+ this.writePromises.set(filePath, writePromise);
3306
+ writePromise.finally(() => {
3307
+ if (this.writePromises.get(filePath) === writePromise) {
3308
+ this.writePromises.delete(filePath);
3309
+ }
3310
+ });
3311
+ }
3312
+ }
3313
+ };
3314
+ }
3315
+ });
3316
+
3317
+ // src/logging/logger.ts
3318
+ var logger_exports = {};
3319
+ __export(logger_exports, {
3320
+ LOG: () => LOG,
3321
+ LOG_DIR_PATH: () => LOG_DIR_PATH,
3322
+ LOG_PATH: () => LOG_PATH,
3323
+ daemonLog: () => daemonLog,
3324
+ getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
3325
+ getDaemonLogDir: () => getDaemonLogDir,
3326
+ getLogBufferSize: () => getLogBufferSize,
3327
+ getLogLevel: () => getLogLevel,
3328
+ getLogPath: () => getLogPath,
3329
+ getRecentLogs: () => getRecentLogs,
3330
+ installGlobalInterceptor: () => installGlobalInterceptor,
3331
+ setLogLevel: () => setLogLevel
3332
+ });
3333
+ function setLogLevel(level) {
3334
+ currentLevel = level;
3335
+ daemonLog("Logger", `Log level set to: ${level}`, "info");
3336
+ }
3337
+ function getLogLevel() {
3338
+ return currentLevel;
3339
+ }
3340
+ function getDateStr() {
3341
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3342
+ }
3343
+ function getDaemonLogDir() {
3344
+ return LOG_DIR;
3345
+ }
3346
+ function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
3347
+ return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
3348
+ }
3349
+ function checkDateRotation() {
3350
+ const today = getDateStr();
3351
+ if (today !== currentDate) {
3352
+ currentDate = today;
3353
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
3354
+ cleanOldLogs();
3355
+ }
3356
+ }
3357
+ function cleanOldLogs() {
3358
+ try {
3359
+ const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
3360
+ const cutoff = /* @__PURE__ */ new Date();
3361
+ cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
3362
+ const cutoffStr = cutoff.toISOString().slice(0, 10);
3363
+ for (const file of files) {
3364
+ const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
3365
+ if (dateMatch && dateMatch[1] < cutoffStr) {
3366
+ try {
3367
+ fs4.unlinkSync(path9.join(LOG_DIR, file));
3368
+ } catch {
3369
+ }
3370
+ }
3371
+ }
3372
+ } catch {
3373
+ }
3374
+ }
3375
+ function rotateSizeIfNeeded() {
3376
+ try {
3377
+ const stat2 = fs4.statSync(currentLogFile);
3378
+ if (stat2.size > MAX_LOG_SIZE) {
3379
+ const backup = currentLogFile.replace(".log", ".1.log");
3380
+ try {
3381
+ fs4.unlinkSync(backup);
3382
+ } catch {
3383
+ }
3384
+ fs4.renameSync(currentLogFile, backup);
3385
+ }
3386
+ } catch {
3387
+ }
3388
+ }
3389
+ function writeToFile(line) {
3390
+ try {
3391
+ if (++writeCount % 1e3 === 0) {
3392
+ checkDateRotation();
3393
+ rotateSizeIfNeeded();
3394
+ }
3395
+ AsyncBatchWriter.write(currentLogFile, line + "\n");
3396
+ } catch {
3397
+ }
3398
+ }
3399
+ function getRecentLogs(count = 50, minLevel = "info") {
3400
+ const minNum = LEVEL_NUM[minLevel];
3401
+ const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
3402
+ return filtered.slice(-count);
3403
+ }
3404
+ function getLogBufferSize() {
3405
+ return ringBuffer.length;
3406
+ }
3407
+ function ts() {
3408
+ return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
3409
+ }
3410
+ function fullTs() {
3411
+ return (/* @__PURE__ */ new Date()).toISOString();
3412
+ }
3413
+ function daemonLog(category, msg, level = "info") {
3414
+ const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
3415
+ const label = LEVEL_LABEL[level];
3416
+ const line = `[${ts()}] [${label}] [${category}] ${msg}`;
3417
+ if (!shouldOutput) return;
3418
+ writeToFile(line);
3419
+ ringBuffer.push({ ts: Date.now(), level, category, message: msg });
3420
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3421
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3422
+ }
3423
+ origConsoleLog(line);
3424
+ }
3425
+ function installGlobalInterceptor() {
3426
+ if (interceptorInstalled) return;
3427
+ interceptorInstalled = true;
3428
+ const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
3429
+ const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
3430
+ console.log = (...args) => {
3431
+ origConsoleLog(...args);
3432
+ try {
3433
+ const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
3434
+ const clean = stripAnsi4(msg);
3435
+ if (isDaemonLogLine(clean)) return;
3436
+ const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
3437
+ writeToFile(line);
3438
+ const catMatch = clean.match(/\[([^\]]+)\]/);
3439
+ ringBuffer.push({
3440
+ ts: Date.now(),
3441
+ level: "info",
3442
+ category: catMatch?.[1] || "System",
3443
+ message: clean
3444
+ });
3445
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3446
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3447
+ }
3448
+ } catch {
3449
+ }
3450
+ };
3451
+ console.error = (...args) => {
3452
+ origConsoleError(...args);
3453
+ try {
3454
+ const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
3455
+ const clean = stripAnsi4(msg);
3456
+ if (isDaemonLogLine(clean)) return;
3457
+ const line = `[${fullTs()}] [ERROR] ${clean}`;
3458
+ writeToFile(line);
3459
+ ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
3460
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3461
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3462
+ }
3463
+ } catch {
3464
+ }
3465
+ };
3466
+ console.warn = (...args) => {
3467
+ origConsoleWarn(...args);
3468
+ try {
3469
+ const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
3470
+ const clean = stripAnsi4(msg);
3471
+ if (isDaemonLogLine(clean)) return;
3472
+ const line = `[${fullTs()}] [WARN] ${clean}`;
3473
+ writeToFile(line);
3474
+ ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
3475
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3476
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3477
+ }
3478
+ } catch {
3479
+ }
3480
+ };
3481
+ writeToFile(`
3482
+ === ADHDev Daemon started at ${fullTs()} ===`);
3483
+ writeToFile(`Log file: ${currentLogFile}`);
3484
+ writeToFile(`Log level: ${currentLevel}`);
3485
+ }
3486
+ function getLogPath() {
3487
+ return currentLogFile;
3488
+ }
3489
+ var fs4, path9, os3, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
3490
+ var init_logger = __esm({
3491
+ "src/logging/logger.ts"() {
3492
+ "use strict";
3493
+ fs4 = __toESM(require("fs"));
3494
+ path9 = __toESM(require("path"));
3495
+ os3 = __toESM(require("os"));
3496
+ init_async_batch_writer();
3497
+ LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
3498
+ LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
3499
+ currentLevel = "info";
3500
+ LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os3.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os3.homedir(), "Library", "Logs", "adhdev") : path9.join(os3.homedir(), ".local", "share", "adhdev", "logs");
3501
+ MAX_LOG_SIZE = 5 * 1024 * 1024;
3502
+ MAX_LOG_DAYS = 7;
3503
+ try {
3504
+ fs4.mkdirSync(LOG_DIR, { recursive: true });
3505
+ } catch {
3506
+ }
3507
+ currentDate = getDateStr();
3508
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
3509
+ cleanOldLogs();
3510
+ try {
3511
+ const oldLog = path9.join(LOG_DIR, "daemon.log");
3512
+ if (fs4.existsSync(oldLog)) {
3513
+ const stat2 = fs4.statSync(oldLog);
3514
+ const oldDate = stat2.mtime.toISOString().slice(0, 10);
3515
+ fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
3516
+ }
3517
+ const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
3518
+ if (fs4.existsSync(oldLogBackup)) {
3519
+ fs4.unlinkSync(oldLogBackup);
3520
+ }
3521
+ } catch {
3522
+ }
3523
+ writeCount = 0;
3524
+ RING_BUFFER_SIZE = 200;
3525
+ ringBuffer = [];
3526
+ origConsoleLog = console.log.bind(console);
3527
+ origConsoleError = console.error.bind(console);
3528
+ origConsoleWarn = console.warn.bind(console);
3529
+ LOG = {
3530
+ debug: (category, msg) => daemonLog(category, msg, "debug"),
3531
+ info: (category, msg) => daemonLog(category, msg, "info"),
3532
+ warn: (category, msg) => daemonLog(category, msg, "warn"),
3533
+ error: (category, msg) => daemonLog(category, msg, "error"),
3534
+ /**
3535
+ * Create a scoped logger for a specific component.
3536
+ * Category is baked in so callers only pass the message.
3537
+ */
3538
+ forComponent(category) {
3539
+ return {
3540
+ debug: (msg) => daemonLog(category, msg, "debug"),
3541
+ info: (msg) => daemonLog(category, msg, "info"),
3542
+ warn: (msg) => daemonLog(category, msg, "warn"),
3543
+ error: (msg) => daemonLog(category, msg, "error"),
3544
+ asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
3545
+ };
3546
+ }
3547
+ };
3548
+ interceptorInstalled = false;
3549
+ LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
3550
+ LOG_DIR_PATH = LOG_DIR;
3551
+ }
3552
+ });
3553
+
3263
3554
  // src/mesh/mesh-work-queue.ts
3264
3555
  var mesh_work_queue_exports = {};
3265
3556
  __export(mesh_work_queue_exports, {
@@ -3724,11 +4015,18 @@ function requeueTask(meshId, taskId, opts) {
3724
4015
  }
3725
4016
  function updateSessionTaskStatus(meshId, sessionId, status, opts) {
3726
4017
  return withQueueLock(meshId, () => {
4018
+ const store = MeshRuntimeStore.getInstance();
3727
4019
  const occurredAtIso = opts?.occurredAt ? new Date(opts.occurredAt).toISOString() : void 0;
3728
- const entry = MeshRuntimeStore.getInstance().findAssignedBySession(meshId, sessionId, occurredAtIso);
3729
- if (!entry) return null;
4020
+ const entry = store.findAssignedBySession(meshId, sessionId, occurredAtIso, opts?.taskId);
4021
+ if (!entry) {
4022
+ const assignedRows = store.getActiveAssignmentDetails(meshId).filter((r) => r.sessionId === sessionId);
4023
+ if (assignedRows.length > 0) {
4024
+ LOG.warn("MeshQueue", `No assigned queue row matched completion for mesh ${meshId} session ${sessionId} (taskId=${opts?.taskId ?? "none"}, occurredAt=${occurredAtIso ?? "none"}); ${assignedRows.length} assigned row(s) exist: ${assignedRows.map((r) => r.id).join(",")}`);
4025
+ }
4026
+ return null;
4027
+ }
3730
4028
  entry.status = status;
3731
- MeshRuntimeStore.getInstance().updateQueueEntry(entry);
4029
+ store.updateQueueEntry(entry);
3732
4030
  if (DEPENDENCY_FAILURE_TERMINALS.has(status)) propagateDependencyFailure(meshId, entry.id);
3733
4031
  return entry;
3734
4032
  });
@@ -3837,6 +4135,7 @@ var init_mesh_work_queue = __esm({
3837
4135
  init_repo_mesh_types();
3838
4136
  init_mesh_runtime_store();
3839
4137
  init_mesh_config();
4138
+ init_logger();
3840
4139
  ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
3841
4140
  HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
3842
4141
  MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
@@ -4495,12 +4794,51 @@ var init_mesh_runtime_store = __esm({
4495
4794
  return { id, nodeId: r.assigned_node_id ?? void 0, sessionId: r.assigned_session_id ?? void 0, message };
4496
4795
  });
4497
4796
  }
4498
- findAssignedBySession(meshId, sessionId, occurredAtIso) {
4797
+ /**
4798
+ * Resolve the `assigned` queue row a completion event belongs to.
4799
+ *
4800
+ * Clock-skew safety (C2): a completion event's `occurredAtIso` carries the
4801
+ * REMOTE WORKER's clock, while `updated_at` carries the COORDINATOR's clock
4802
+ * (set at assignment and re-bumped on every mutation). For a remote node,
4803
+ * coordinator-clock > worker-clock skew used to make an `updated_at <= occurredAt`
4804
+ * filter return nothing, stranding the finished task as `assigned` forever.
4805
+ *
4806
+ * We therefore NEVER filter completion-matching on the mutable `updated_at`:
4807
+ * 1. If `taskId` is given, match the exact `assigned` row by id (no time filter).
4808
+ * 2. Otherwise a session holds at most one `assigned` task — match it without a
4809
+ * time filter. If several exist (shouldn't normally), disambiguate by the
4810
+ * IMMUTABLE `dispatchTimestamp`: latest `dispatchTimestamp <= occurredAt`,
4811
+ * and if skew makes ALL of them later than `occurredAt`, fall back to the
4812
+ * most-recent `dispatchTimestamp` rather than returning null.
4813
+ */
4814
+ findAssignedBySession(meshId, sessionId, occurredAtIso, taskId) {
4499
4815
  this.ensureLegacyQueueMigrated(meshId);
4500
- const sql = occurredAtIso ? `SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned' AND updated_at <= ? ORDER BY updated_at DESC LIMIT 1` : `SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned' ORDER BY updated_at DESC LIMIT 1`;
4501
- const args = occurredAtIso ? [meshId, sessionId, occurredAtIso] : [meshId, sessionId];
4502
- const row = this.db.prepare(sql).get(...args);
4503
- return row ? JSON.parse(row.payload) : null;
4816
+ if (taskId) {
4817
+ const row = this.db.prepare(
4818
+ `SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned' AND id = ? LIMIT 1`
4819
+ ).get(meshId, sessionId, taskId);
4820
+ if (row) return JSON.parse(row.payload);
4821
+ }
4822
+ const rows = this.db.prepare(
4823
+ `SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned'`
4824
+ ).all(meshId, sessionId);
4825
+ if (rows.length === 0) return null;
4826
+ const entries = rows.map((r) => {
4827
+ try {
4828
+ return JSON.parse(r.payload);
4829
+ } catch {
4830
+ return null;
4831
+ }
4832
+ }).filter((e) => e !== null);
4833
+ if (entries.length === 0) return null;
4834
+ if (entries.length === 1) return entries[0];
4835
+ const orderKey = (e) => e.dispatchTimestamp ?? e.updatedAt ?? "";
4836
+ const byDispatchDesc = [...entries].sort((a, b) => orderKey(b).localeCompare(orderKey(a)));
4837
+ if (occurredAtIso) {
4838
+ const atOrBefore = byDispatchDesc.find((e) => orderKey(e) <= occurredAtIso);
4839
+ if (atOrBefore) return atOrBefore;
4840
+ }
4841
+ return byDispatchDesc[0];
4504
4842
  }
4505
4843
  toRow(entry) {
4506
4844
  return {
@@ -5756,297 +6094,6 @@ var init_mesh_review_inbox = __esm({
5756
6094
  }
5757
6095
  });
5758
6096
 
5759
- // src/logging/async-batch-writer.ts
5760
- var fs3, AsyncBatchWriter;
5761
- var init_async_batch_writer = __esm({
5762
- "src/logging/async-batch-writer.ts"() {
5763
- "use strict";
5764
- fs3 = __toESM(require("fs"));
5765
- AsyncBatchWriter = class {
5766
- // Maps filePath -> string buffer
5767
- static buffers = /* @__PURE__ */ new Map();
5768
- static writePromises = /* @__PURE__ */ new Map();
5769
- static flushTimer = null;
5770
- /**
5771
- * Queues data to be written to a file asynchronously in a batch.
5772
- */
5773
- static write(filePath, data) {
5774
- let buf = this.buffers.get(filePath);
5775
- if (!buf) {
5776
- buf = [];
5777
- this.buffers.set(filePath, buf);
5778
- }
5779
- buf.push(data);
5780
- if (!this.flushTimer) {
5781
- this.flushTimer = setTimeout(() => {
5782
- this.flushTimer = null;
5783
- this.flushAll();
5784
- }, 50);
5785
- }
5786
- }
5787
- static async flushAll() {
5788
- const entries = Array.from(this.buffers.entries());
5789
- this.buffers.clear();
5790
- for (const [filePath, buffer] of entries) {
5791
- const dataToWrite = buffer.join("");
5792
- const doWrite = async () => {
5793
- try {
5794
- const prevPromise = this.writePromises.get(filePath);
5795
- if (prevPromise) await prevPromise;
5796
- await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
5797
- } catch {
5798
- }
5799
- };
5800
- const writePromise = doWrite();
5801
- this.writePromises.set(filePath, writePromise);
5802
- writePromise.finally(() => {
5803
- if (this.writePromises.get(filePath) === writePromise) {
5804
- this.writePromises.delete(filePath);
5805
- }
5806
- });
5807
- }
5808
- }
5809
- };
5810
- }
5811
- });
5812
-
5813
- // src/logging/logger.ts
5814
- var logger_exports = {};
5815
- __export(logger_exports, {
5816
- LOG: () => LOG,
5817
- LOG_DIR_PATH: () => LOG_DIR_PATH,
5818
- LOG_PATH: () => LOG_PATH,
5819
- daemonLog: () => daemonLog,
5820
- getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
5821
- getDaemonLogDir: () => getDaemonLogDir,
5822
- getLogBufferSize: () => getLogBufferSize,
5823
- getLogLevel: () => getLogLevel,
5824
- getLogPath: () => getLogPath,
5825
- getRecentLogs: () => getRecentLogs,
5826
- installGlobalInterceptor: () => installGlobalInterceptor,
5827
- setLogLevel: () => setLogLevel
5828
- });
5829
- function setLogLevel(level) {
5830
- currentLevel = level;
5831
- daemonLog("Logger", `Log level set to: ${level}`, "info");
5832
- }
5833
- function getLogLevel() {
5834
- return currentLevel;
5835
- }
5836
- function getDateStr() {
5837
- return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5838
- }
5839
- function getDaemonLogDir() {
5840
- return LOG_DIR;
5841
- }
5842
- function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
5843
- return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
5844
- }
5845
- function checkDateRotation() {
5846
- const today = getDateStr();
5847
- if (today !== currentDate) {
5848
- currentDate = today;
5849
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
5850
- cleanOldLogs();
5851
- }
5852
- }
5853
- function cleanOldLogs() {
5854
- try {
5855
- const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
5856
- const cutoff = /* @__PURE__ */ new Date();
5857
- cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
5858
- const cutoffStr = cutoff.toISOString().slice(0, 10);
5859
- for (const file of files) {
5860
- const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
5861
- if (dateMatch && dateMatch[1] < cutoffStr) {
5862
- try {
5863
- fs4.unlinkSync(path9.join(LOG_DIR, file));
5864
- } catch {
5865
- }
5866
- }
5867
- }
5868
- } catch {
5869
- }
5870
- }
5871
- function rotateSizeIfNeeded() {
5872
- try {
5873
- const stat2 = fs4.statSync(currentLogFile);
5874
- if (stat2.size > MAX_LOG_SIZE) {
5875
- const backup = currentLogFile.replace(".log", ".1.log");
5876
- try {
5877
- fs4.unlinkSync(backup);
5878
- } catch {
5879
- }
5880
- fs4.renameSync(currentLogFile, backup);
5881
- }
5882
- } catch {
5883
- }
5884
- }
5885
- function writeToFile(line) {
5886
- try {
5887
- if (++writeCount % 1e3 === 0) {
5888
- checkDateRotation();
5889
- rotateSizeIfNeeded();
5890
- }
5891
- AsyncBatchWriter.write(currentLogFile, line + "\n");
5892
- } catch {
5893
- }
5894
- }
5895
- function getRecentLogs(count = 50, minLevel = "info") {
5896
- const minNum = LEVEL_NUM[minLevel];
5897
- const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
5898
- return filtered.slice(-count);
5899
- }
5900
- function getLogBufferSize() {
5901
- return ringBuffer.length;
5902
- }
5903
- function ts() {
5904
- return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
5905
- }
5906
- function fullTs() {
5907
- return (/* @__PURE__ */ new Date()).toISOString();
5908
- }
5909
- function daemonLog(category, msg, level = "info") {
5910
- const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
5911
- const label = LEVEL_LABEL[level];
5912
- const line = `[${ts()}] [${label}] [${category}] ${msg}`;
5913
- if (!shouldOutput) return;
5914
- writeToFile(line);
5915
- ringBuffer.push({ ts: Date.now(), level, category, message: msg });
5916
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5917
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5918
- }
5919
- origConsoleLog(line);
5920
- }
5921
- function installGlobalInterceptor() {
5922
- if (interceptorInstalled) return;
5923
- interceptorInstalled = true;
5924
- const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
5925
- const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
5926
- console.log = (...args) => {
5927
- origConsoleLog(...args);
5928
- try {
5929
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
5930
- const clean = stripAnsi4(msg);
5931
- if (isDaemonLogLine(clean)) return;
5932
- const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
5933
- writeToFile(line);
5934
- const catMatch = clean.match(/\[([^\]]+)\]/);
5935
- ringBuffer.push({
5936
- ts: Date.now(),
5937
- level: "info",
5938
- category: catMatch?.[1] || "System",
5939
- message: clean
5940
- });
5941
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5942
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5943
- }
5944
- } catch {
5945
- }
5946
- };
5947
- console.error = (...args) => {
5948
- origConsoleError(...args);
5949
- try {
5950
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
5951
- const clean = stripAnsi4(msg);
5952
- if (isDaemonLogLine(clean)) return;
5953
- const line = `[${fullTs()}] [ERROR] ${clean}`;
5954
- writeToFile(line);
5955
- ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
5956
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5957
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5958
- }
5959
- } catch {
5960
- }
5961
- };
5962
- console.warn = (...args) => {
5963
- origConsoleWarn(...args);
5964
- try {
5965
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
5966
- const clean = stripAnsi4(msg);
5967
- if (isDaemonLogLine(clean)) return;
5968
- const line = `[${fullTs()}] [WARN] ${clean}`;
5969
- writeToFile(line);
5970
- ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
5971
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5972
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5973
- }
5974
- } catch {
5975
- }
5976
- };
5977
- writeToFile(`
5978
- === ADHDev Daemon started at ${fullTs()} ===`);
5979
- writeToFile(`Log file: ${currentLogFile}`);
5980
- writeToFile(`Log level: ${currentLevel}`);
5981
- }
5982
- function getLogPath() {
5983
- return currentLogFile;
5984
- }
5985
- var fs4, path9, os3, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
5986
- var init_logger = __esm({
5987
- "src/logging/logger.ts"() {
5988
- "use strict";
5989
- fs4 = __toESM(require("fs"));
5990
- path9 = __toESM(require("path"));
5991
- os3 = __toESM(require("os"));
5992
- init_async_batch_writer();
5993
- LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
5994
- LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
5995
- currentLevel = "info";
5996
- LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os3.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os3.homedir(), "Library", "Logs", "adhdev") : path9.join(os3.homedir(), ".local", "share", "adhdev", "logs");
5997
- MAX_LOG_SIZE = 5 * 1024 * 1024;
5998
- MAX_LOG_DAYS = 7;
5999
- try {
6000
- fs4.mkdirSync(LOG_DIR, { recursive: true });
6001
- } catch {
6002
- }
6003
- currentDate = getDateStr();
6004
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
6005
- cleanOldLogs();
6006
- try {
6007
- const oldLog = path9.join(LOG_DIR, "daemon.log");
6008
- if (fs4.existsSync(oldLog)) {
6009
- const stat2 = fs4.statSync(oldLog);
6010
- const oldDate = stat2.mtime.toISOString().slice(0, 10);
6011
- fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
6012
- }
6013
- const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
6014
- if (fs4.existsSync(oldLogBackup)) {
6015
- fs4.unlinkSync(oldLogBackup);
6016
- }
6017
- } catch {
6018
- }
6019
- writeCount = 0;
6020
- RING_BUFFER_SIZE = 200;
6021
- ringBuffer = [];
6022
- origConsoleLog = console.log.bind(console);
6023
- origConsoleError = console.error.bind(console);
6024
- origConsoleWarn = console.warn.bind(console);
6025
- LOG = {
6026
- debug: (category, msg) => daemonLog(category, msg, "debug"),
6027
- info: (category, msg) => daemonLog(category, msg, "info"),
6028
- warn: (category, msg) => daemonLog(category, msg, "warn"),
6029
- error: (category, msg) => daemonLog(category, msg, "error"),
6030
- /**
6031
- * Create a scoped logger for a specific component.
6032
- * Category is baked in so callers only pass the message.
6033
- */
6034
- forComponent(category) {
6035
- return {
6036
- debug: (msg) => daemonLog(category, msg, "debug"),
6037
- info: (msg) => daemonLog(category, msg, "info"),
6038
- warn: (msg) => daemonLog(category, msg, "warn"),
6039
- error: (msg) => daemonLog(category, msg, "error"),
6040
- asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
6041
- };
6042
- }
6043
- };
6044
- interceptorInstalled = false;
6045
- LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
6046
- LOG_DIR_PATH = LOG_DIR;
6047
- }
6048
- });
6049
-
6050
6097
  // src/commands/mesh-coordinator.ts
6051
6098
  var mesh_coordinator_exports = {};
6052
6099
  __export(mesh_coordinator_exports, {
@@ -6448,6 +6495,59 @@ var init_mesh_coordinator = __esm({
6448
6495
  }
6449
6496
  });
6450
6497
 
6498
+ // src/cli-adapters/resolve-executable.ts
6499
+ function resolveWin32GlobalBin(trimmed) {
6500
+ if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
6501
+ return null;
6502
+ }
6503
+ const extraDirs = [];
6504
+ if (process.env.APPDATA) extraDirs.push(path10.join(process.env.APPDATA, "npm"));
6505
+ try {
6506
+ extraDirs.push(path10.dirname(process.execPath));
6507
+ } catch {
6508
+ }
6509
+ for (const dir of extraDirs) {
6510
+ if (!dir) continue;
6511
+ for (const ext of WIN_EXEC_EXT) {
6512
+ const full = path10.join(dir, trimmed + ext);
6513
+ if ((0, import_fs8.existsSync)(full)) return full;
6514
+ }
6515
+ }
6516
+ return null;
6517
+ }
6518
+ function resolveWin32Executable(command) {
6519
+ if (process.platform !== "win32") return command;
6520
+ const trimmed = (command || "").trim();
6521
+ if (!trimmed) return command;
6522
+ if (path10.isAbsolute(trimmed) && (0, import_fs8.existsSync)(trimmed)) return trimmed;
6523
+ try {
6524
+ const out = (0, import_child_process.execFileSync)("where", [trimmed], {
6525
+ encoding: "utf8",
6526
+ windowsHide: true
6527
+ }).trim();
6528
+ if (out) {
6529
+ const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
6530
+ const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
6531
+ return direct || matches[0] || command;
6532
+ }
6533
+ } catch {
6534
+ }
6535
+ const globalBin = resolveWin32GlobalBin(trimmed);
6536
+ if (globalBin) return globalBin;
6537
+ return command;
6538
+ }
6539
+ var import_child_process, import_fs8, path10, DIRECT_EXEC_EXT, WIN_EXEC_EXT;
6540
+ var init_resolve_executable = __esm({
6541
+ "src/cli-adapters/resolve-executable.ts"() {
6542
+ "use strict";
6543
+ import_child_process = require("child_process");
6544
+ import_fs8 = require("fs");
6545
+ path10 = __toESM(require("path"));
6546
+ DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
6547
+ WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
6548
+ }
6549
+ });
6550
+
6451
6551
  // src/mesh/mesh-fast-forward.ts
6452
6552
  async function fastForwardMeshNode(args) {
6453
6553
  const workspace = typeof args.workspace === "string" ? args.workspace.trim() : "";
@@ -7971,9 +8071,9 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
7971
8071
  const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
7972
8072
  const events = [];
7973
8073
  for (const path42 of paths) {
7974
- if (!(0, import_fs9.existsSync)(path42)) continue;
8074
+ if (!(0, import_fs10.existsSync)(path42)) continue;
7975
8075
  try {
7976
- const raw = (0, import_fs9.readFileSync)(path42, "utf-8");
8076
+ const raw = (0, import_fs10.readFileSync)(path42, "utf-8");
7977
8077
  const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
7978
8078
  try {
7979
8079
  return [JSON.parse(line)];
@@ -8048,11 +8148,11 @@ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
8048
8148
  }
8049
8149
  function trimPendingEventsIfNeeded(path42) {
8050
8150
  try {
8051
- if (!(0, import_fs9.existsSync)(path42)) return;
8052
- if ((0, import_fs9.statSync)(path42).size <= MAX_PENDING_EVENTS_BYTES) return;
8053
- const lines = (0, import_fs9.readFileSync)(path42, "utf-8").split("\n").filter(Boolean);
8151
+ if (!(0, import_fs10.existsSync)(path42)) return;
8152
+ if ((0, import_fs10.statSync)(path42).size <= MAX_PENDING_EVENTS_BYTES) return;
8153
+ const lines = (0, import_fs10.readFileSync)(path42, "utf-8").split("\n").filter(Boolean);
8054
8154
  if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
8055
- (0, import_fs9.writeFileSync)(path42, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
8155
+ (0, import_fs10.writeFileSync)(path42, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
8056
8156
  } catch {
8057
8157
  }
8058
8158
  }
@@ -8081,7 +8181,7 @@ function queuePendingMeshCoordinatorEvent(event) {
8081
8181
  }
8082
8182
  const path42 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
8083
8183
  trimPendingEventsIfNeeded(path42);
8084
- (0, import_fs9.appendFileSync)(path42, JSON.stringify(event) + "\n", "utf-8");
8184
+ (0, import_fs10.appendFileSync)(path42, JSON.stringify(event) + "\n", "utf-8");
8085
8185
  return true;
8086
8186
  } catch (e) {
8087
8187
  LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
@@ -8091,20 +8191,20 @@ function queuePendingMeshCoordinatorEvent(event) {
8091
8191
  function atomicDrainFile(path42) {
8092
8192
  const tmpPath = `${path42}.draining`;
8093
8193
  try {
8094
- (0, import_fs9.renameSync)(path42, tmpPath);
8194
+ (0, import_fs10.renameSync)(path42, tmpPath);
8095
8195
  } catch {
8096
8196
  return null;
8097
8197
  }
8098
8198
  try {
8099
- const content = (0, import_fs9.readFileSync)(tmpPath, "utf-8");
8199
+ const content = (0, import_fs10.readFileSync)(tmpPath, "utf-8");
8100
8200
  try {
8101
- (0, import_fs9.unlinkSync)(tmpPath);
8201
+ (0, import_fs10.unlinkSync)(tmpPath);
8102
8202
  } catch {
8103
8203
  }
8104
8204
  return content;
8105
8205
  } catch {
8106
8206
  try {
8107
- (0, import_fs9.unlinkSync)(tmpPath);
8207
+ (0, import_fs10.unlinkSync)(tmpPath);
8108
8208
  } catch {
8109
8209
  }
8110
8210
  return null;
@@ -8113,16 +8213,16 @@ function atomicDrainFile(path42) {
8113
8213
  function selectiveDrainFile(path42, predicate) {
8114
8214
  const tmpPath = `${path42}.draining`;
8115
8215
  try {
8116
- (0, import_fs9.renameSync)(path42, tmpPath);
8216
+ (0, import_fs10.renameSync)(path42, tmpPath);
8117
8217
  } catch {
8118
8218
  return [];
8119
8219
  }
8120
8220
  let content;
8121
8221
  try {
8122
- content = (0, import_fs9.readFileSync)(tmpPath, "utf-8");
8222
+ content = (0, import_fs10.readFileSync)(tmpPath, "utf-8");
8123
8223
  } catch {
8124
8224
  try {
8125
- (0, import_fs9.unlinkSync)(tmpPath);
8225
+ (0, import_fs10.unlinkSync)(tmpPath);
8126
8226
  } catch {
8127
8227
  }
8128
8228
  return [];
@@ -8145,12 +8245,12 @@ function selectiveDrainFile(path42, predicate) {
8145
8245
  }
8146
8246
  try {
8147
8247
  if (keptLines.length > 0) {
8148
- (0, import_fs9.writeFileSync)(path42, keptLines.join("\n") + "\n", "utf-8");
8248
+ (0, import_fs10.writeFileSync)(path42, keptLines.join("\n") + "\n", "utf-8");
8149
8249
  }
8150
- (0, import_fs9.unlinkSync)(tmpPath);
8250
+ (0, import_fs10.unlinkSync)(tmpPath);
8151
8251
  } catch {
8152
8252
  try {
8153
- if ((0, import_fs9.existsSync)(tmpPath) && !(0, import_fs9.existsSync)(path42)) (0, import_fs9.renameSync)(tmpPath, path42);
8253
+ if ((0, import_fs10.existsSync)(tmpPath) && !(0, import_fs10.existsSync)(path42)) (0, import_fs10.renameSync)(tmpPath, path42);
8154
8254
  } catch {
8155
8255
  }
8156
8256
  return [];
@@ -8244,17 +8344,17 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
8244
8344
  }
8245
8345
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
8246
8346
  for (const path42 of paths) {
8247
- if ((0, import_fs9.existsSync)(path42)) try {
8248
- (0, import_fs9.unlinkSync)(path42);
8347
+ if ((0, import_fs10.existsSync)(path42)) try {
8348
+ (0, import_fs10.unlinkSync)(path42);
8249
8349
  } catch {
8250
8350
  }
8251
8351
  }
8252
8352
  }
8253
- var import_fs9, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
8353
+ var import_fs10, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
8254
8354
  var init_mesh_events_pending = __esm({
8255
8355
  "src/mesh/mesh-events-pending.ts"() {
8256
8356
  "use strict";
8257
- import_fs9 = require("fs");
8357
+ import_fs10 = require("fs");
8258
8358
  import_path9 = require("path");
8259
8359
  import_crypto7 = require("crypto");
8260
8360
  init_logger();
@@ -8749,24 +8849,24 @@ function buildCliScreenSnapshot(text) {
8749
8849
  function findBinary(name) {
8750
8850
  const trimmed = String(name || "").trim();
8751
8851
  if (!trimmed) return trimmed;
8752
- const expanded = trimmed.startsWith("~") ? path10.join(os5.homedir(), trimmed.slice(1)) : trimmed;
8753
- if (path10.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
8754
- return path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
8852
+ const expanded = trimmed.startsWith("~") ? path11.join(os5.homedir(), trimmed.slice(1)) : trimmed;
8853
+ if (path11.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
8854
+ return path11.isAbsolute(expanded) ? expanded : path11.resolve(expanded);
8755
8855
  }
8756
8856
  const isWin = os5.platform() === "win32";
8757
- const paths = (process.env.PATH || "").split(path10.delimiter);
8857
+ const paths = (process.env.PATH || "").split(path11.delimiter);
8758
8858
  const extraDirs = [];
8759
8859
  if (isWin) {
8760
- if (process.env.APPDATA) extraDirs.push(path10.join(process.env.APPDATA, "npm"));
8860
+ if (process.env.APPDATA) extraDirs.push(path11.join(process.env.APPDATA, "npm"));
8761
8861
  try {
8762
- extraDirs.push(path10.dirname(process.execPath));
8862
+ extraDirs.push(path11.dirname(process.execPath));
8763
8863
  } catch {
8764
8864
  }
8765
8865
  } else {
8766
- extraDirs.push(path10.join(os5.homedir(), ".npm-global", "bin"));
8866
+ extraDirs.push(path11.join(os5.homedir(), ".npm-global", "bin"));
8767
8867
  extraDirs.push("/usr/local/bin", "/opt/homebrew/bin");
8768
8868
  try {
8769
- extraDirs.push(path10.dirname(process.execPath));
8869
+ extraDirs.push(path11.dirname(process.execPath));
8770
8870
  } catch {
8771
8871
  }
8772
8872
  }
@@ -8775,7 +8875,7 @@ function findBinary(name) {
8775
8875
  for (const p of searchDirs) {
8776
8876
  if (!p) continue;
8777
8877
  for (const ext of exes) {
8778
- const fullPath = path10.join(p, trimmed + ext);
8878
+ const fullPath = path11.join(p, trimmed + ext);
8779
8879
  try {
8780
8880
  const fs32 = require("fs");
8781
8881
  if (fs32.existsSync(fullPath)) {
@@ -8791,7 +8891,7 @@ function findBinary(name) {
8791
8891
  return isWin ? `${trimmed}.cmd` : trimmed;
8792
8892
  }
8793
8893
  function isScriptBinary(binaryPath) {
8794
- if (!path10.isAbsolute(binaryPath)) return false;
8894
+ if (!path11.isAbsolute(binaryPath)) return false;
8795
8895
  try {
8796
8896
  const fs32 = require("fs");
8797
8897
  const resolved = fs32.realpathSync(binaryPath);
@@ -8807,7 +8907,7 @@ function isScriptBinary(binaryPath) {
8807
8907
  }
8808
8908
  }
8809
8909
  function looksLikeMachOOrElf(filePath) {
8810
- if (!path10.isAbsolute(filePath)) return false;
8910
+ if (!path11.isAbsolute(filePath)) return false;
8811
8911
  try {
8812
8912
  const fs32 = require("fs");
8813
8913
  const resolved = fs32.realpathSync(filePath);
@@ -8896,12 +8996,12 @@ function normalizeCliProviderForRuntime(raw) {
8896
8996
  }
8897
8997
  };
8898
8998
  }
8899
- var os5, path10, TerminalTranscriptAccumulator, buildCliSpawnEnv;
8999
+ var os5, path11, TerminalTranscriptAccumulator, buildCliSpawnEnv;
8900
9000
  var init_provider_cli_shared = __esm({
8901
9001
  "src/cli-adapters/provider-cli-shared.ts"() {
8902
9002
  "use strict";
8903
9003
  os5 = __toESM(require("os"));
8904
- path10 = __toESM(require("path"));
9004
+ path11 = __toESM(require("path"));
8905
9005
  init_spawn_env();
8906
9006
  TerminalTranscriptAccumulator = class {
8907
9007
  lines = [[]];
@@ -9075,19 +9175,19 @@ function shellQuote(value) {
9075
9175
  function expandHome(value) {
9076
9176
  const trimmed = value.trim();
9077
9177
  if (!trimmed.startsWith("~")) return trimmed;
9078
- return path11.join(os6.homedir(), trimmed.slice(1));
9178
+ return path12.join(os6.homedir(), trimmed.slice(1));
9079
9179
  }
9080
9180
  function isExplicitCommandPath(command) {
9081
9181
  const trimmed = command.trim();
9082
- return path11.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
9182
+ return path12.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
9083
9183
  }
9084
9184
  function resolveCommandPath(command) {
9085
9185
  const trimmed = command.trim();
9086
9186
  if (!trimmed) return null;
9087
9187
  if (isExplicitCommandPath(trimmed)) {
9088
9188
  const expanded = expandHome(trimmed);
9089
- const candidate = path11.isAbsolute(expanded) ? expanded : path11.resolve(expanded);
9090
- return (0, import_fs10.existsSync)(candidate) ? candidate : null;
9189
+ const candidate = path12.isAbsolute(expanded) ? expanded : path12.resolve(expanded);
9190
+ return (0, import_fs11.existsSync)(candidate) ? candidate : null;
9091
9191
  }
9092
9192
  return null;
9093
9193
  }
@@ -9097,12 +9197,12 @@ async function resolveDetectionPath(command, whichCmd) {
9097
9197
  const whichResult = await execAsync(`${whichCmd} ${shellQuote(command)}`);
9098
9198
  if (whichResult) return whichResult.split("\n")[0];
9099
9199
  const resolved = findBinary(command);
9100
- if (path11.isAbsolute(resolved) && (0, import_fs10.existsSync)(resolved)) return resolved;
9200
+ if (path12.isAbsolute(resolved) && (0, import_fs11.existsSync)(resolved)) return resolved;
9101
9201
  return null;
9102
9202
  }
9103
9203
  function execAsync(cmd, timeoutMs = 5e3) {
9104
9204
  return new Promise((resolve24) => {
9105
- const child = (0, import_child_process.exec)(cmd, {
9205
+ const child = (0, import_child_process2.exec)(cmd, {
9106
9206
  encoding: "utf-8",
9107
9207
  timeout: timeoutMs,
9108
9208
  ...process.platform === "win32" ? { windowsHide: true } : {}
@@ -9192,14 +9292,14 @@ async function detectCLI(cliId, providerLoader, options) {
9192
9292
  const all = await detectCLIs(providerLoader, options);
9193
9293
  return all.find((c) => c.id === resolvedId && c.installed) || null;
9194
9294
  }
9195
- var import_child_process, os6, path11, import_fs10;
9295
+ var import_child_process2, os6, path12, import_fs11;
9196
9296
  var init_cli_detector = __esm({
9197
9297
  "src/detection/cli-detector.ts"() {
9198
9298
  "use strict";
9199
- import_child_process = require("child_process");
9299
+ import_child_process2 = require("child_process");
9200
9300
  os6 = __toESM(require("os"));
9201
- path11 = __toESM(require("path"));
9202
- import_fs10 = require("fs");
9301
+ path12 = __toESM(require("path"));
9302
+ import_fs11 = require("fs");
9203
9303
  init_provider_cli_shared();
9204
9304
  }
9205
9305
  });
@@ -10234,7 +10334,7 @@ async function maybeAutoFastForwardIdleNode(components, args) {
10234
10334
  const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
10235
10335
  const workspace = readNonEmptyString2(node?.workspace);
10236
10336
  if (!workspace) return;
10237
- if (!(0, import_fs11.existsSync)(workspace)) return;
10337
+ if (!(0, import_fs12.existsSync)(workspace)) return;
10238
10338
  const policy = resolveAutoFastForwardPolicy(mesh);
10239
10339
  if (!policy.enabled) return;
10240
10340
  if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
@@ -10433,8 +10533,10 @@ function injectMeshSystemMessage(components, args) {
10433
10533
  }
10434
10534
  }
10435
10535
  function markSessionTerminal(sessionId, outcome, occurredAtMs) {
10536
+ const eventTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
10436
10537
  const task = updateSessionTaskStatus(args.meshId, sessionId, outcome, {
10437
- occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0
10538
+ occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
10539
+ taskId: eventTaskId
10438
10540
  });
10439
10541
  updateDirectDispatchStatus(args.meshId, sessionId, outcome);
10440
10542
  markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
@@ -10845,11 +10947,11 @@ function setupMeshEventForwarding(components) {
10845
10947
  });
10846
10948
  });
10847
10949
  }
10848
- var import_fs11, REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, MESH_FORCE_INJECT_EVENTS;
10950
+ var import_fs12, REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, MESH_FORCE_INJECT_EVENTS;
10849
10951
  var init_mesh_events_coordinator = __esm({
10850
10952
  "src/mesh/mesh-events-coordinator.ts"() {
10851
10953
  "use strict";
10852
- import_fs11 = require("fs");
10954
+ import_fs12 = require("fs");
10853
10955
  init_config();
10854
10956
  init_mesh_config();
10855
10957
  init_cli_detector();
@@ -12731,16 +12833,16 @@ __export(external_sources_exports, {
12731
12833
  sourcesProviding: () => sourcesProviding
12732
12834
  });
12733
12835
  function adhdevDir() {
12734
- return path17.join(os11.homedir(), ".adhdev");
12836
+ return path18.join(os11.homedir(), ".adhdev");
12735
12837
  }
12736
12838
  function externalRoot() {
12737
- return path17.join(adhdevDir(), "external");
12839
+ return path18.join(adhdevDir(), "external");
12738
12840
  }
12739
12841
  function sourcesFilePath() {
12740
- return path17.join(adhdevDir(), SOURCES_FILENAME);
12842
+ return path18.join(adhdevDir(), SOURCES_FILENAME);
12741
12843
  }
12742
12844
  function activeFilePath() {
12743
- return path17.join(adhdevDir(), ACTIVE_FILENAME);
12845
+ return path18.join(adhdevDir(), ACTIVE_FILENAME);
12744
12846
  }
12745
12847
  function ensureAdhdevDir() {
12746
12848
  const d = adhdevDir();
@@ -12807,7 +12909,7 @@ function inventoryExternalSources() {
12807
12909
  for (const sourceEntry of entries) {
12808
12910
  if (!sourceEntry.isDirectory()) continue;
12809
12911
  const sourceName = sourceEntry.name;
12810
- const sourceDir = path17.join(root, sourceName);
12912
+ const sourceDir = path18.join(root, sourceName);
12811
12913
  const providers = {};
12812
12914
  let categoryEntries;
12813
12915
  try {
@@ -12818,7 +12920,7 @@ function inventoryExternalSources() {
12818
12920
  for (const categoryEntry of categoryEntries) {
12819
12921
  if (!categoryEntry.isDirectory()) continue;
12820
12922
  const category = categoryEntry.name;
12821
- const categoryDir = path17.join(sourceDir, category);
12923
+ const categoryDir = path18.join(sourceDir, category);
12822
12924
  let typeEntries;
12823
12925
  try {
12824
12926
  typeEntries = fs9.readdirSync(categoryDir, { withFileTypes: true });
@@ -12828,9 +12930,9 @@ function inventoryExternalSources() {
12828
12930
  const types = [];
12829
12931
  for (const typeEntry of typeEntries) {
12830
12932
  if (!typeEntry.isDirectory()) continue;
12831
- const typeDir = path17.join(categoryDir, typeEntry.name);
12832
- const hasV1 = fs9.existsSync(path17.join(typeDir, "provider.v1.json"));
12833
- const hasV0 = fs9.existsSync(path17.join(typeDir, "provider.json"));
12933
+ const typeDir = path18.join(categoryDir, typeEntry.name);
12934
+ const hasV1 = fs9.existsSync(path18.join(typeDir, "provider.v1.json"));
12935
+ const hasV0 = fs9.existsSync(path18.join(typeDir, "provider.json"));
12834
12936
  if (hasV1 || hasV0) types.push(typeEntry.name);
12835
12937
  }
12836
12938
  if (types.length > 0) providers[category] = types;
@@ -12853,13 +12955,13 @@ function resolveActiveSource(category, type, activeFile) {
12853
12955
  }
12854
12956
  return { source: candidates[0], ambiguous: true, candidates };
12855
12957
  }
12856
- var fs9, os11, path17, SOURCES_FILENAME, ACTIVE_FILENAME;
12958
+ var fs9, os11, path18, SOURCES_FILENAME, ACTIVE_FILENAME;
12857
12959
  var init_external_sources = __esm({
12858
12960
  "src/providers/external-sources.ts"() {
12859
12961
  "use strict";
12860
12962
  fs9 = __toESM(require("fs"));
12861
12963
  os11 = __toESM(require("os"));
12862
- path17 = __toESM(require("path"));
12964
+ path18 = __toESM(require("path"));
12863
12965
  SOURCES_FILENAME = "providers-sources.json";
12864
12966
  ACTIVE_FILENAME = "providers-active.json";
12865
12967
  }
@@ -13037,59 +13139,6 @@ var init_terminal_screen = __esm({
13037
13139
  }
13038
13140
  });
13039
13141
 
13040
- // src/cli-adapters/resolve-executable.ts
13041
- function resolveWin32GlobalBin(trimmed) {
13042
- if (path18.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
13043
- return null;
13044
- }
13045
- const extraDirs = [];
13046
- if (process.env.APPDATA) extraDirs.push(path18.join(process.env.APPDATA, "npm"));
13047
- try {
13048
- extraDirs.push(path18.dirname(process.execPath));
13049
- } catch {
13050
- }
13051
- for (const dir of extraDirs) {
13052
- if (!dir) continue;
13053
- for (const ext of WIN_EXEC_EXT) {
13054
- const full = path18.join(dir, trimmed + ext);
13055
- if ((0, import_fs14.existsSync)(full)) return full;
13056
- }
13057
- }
13058
- return null;
13059
- }
13060
- function resolveWin32Executable(command) {
13061
- if (process.platform !== "win32") return command;
13062
- const trimmed = (command || "").trim();
13063
- if (!trimmed) return command;
13064
- if (path18.isAbsolute(trimmed) && (0, import_fs14.existsSync)(trimmed)) return trimmed;
13065
- try {
13066
- const out = (0, import_child_process4.execFileSync)("where", [trimmed], {
13067
- encoding: "utf8",
13068
- windowsHide: true
13069
- }).trim();
13070
- if (out) {
13071
- const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
13072
- const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path18.extname(m).toLowerCase()));
13073
- return direct || matches[0] || command;
13074
- }
13075
- } catch {
13076
- }
13077
- const globalBin = resolveWin32GlobalBin(trimmed);
13078
- if (globalBin) return globalBin;
13079
- return command;
13080
- }
13081
- var import_child_process4, import_fs14, path18, DIRECT_EXEC_EXT, WIN_EXEC_EXT;
13082
- var init_resolve_executable = __esm({
13083
- "src/cli-adapters/resolve-executable.ts"() {
13084
- "use strict";
13085
- import_child_process4 = require("child_process");
13086
- import_fs14 = require("fs");
13087
- path18 = __toESM(require("path"));
13088
- DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
13089
- WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
13090
- }
13091
- });
13092
-
13093
13142
  // src/cli-adapters/pty-transport.ts
13094
13143
  var pty_transport_exports = {};
13095
13144
  __export(pty_transport_exports, {
@@ -19793,13 +19842,20 @@ var MESH_REFINE_CONFIG_SCHEMA = {
19793
19842
  function isMeshConfigRecord(value) {
19794
19843
  return !!value && typeof value === "object" && !Array.isArray(value);
19795
19844
  }
19845
+ var SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
19846
+ var SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
19847
+ var SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
19796
19848
  function tokenizeCommandString(command) {
19797
19849
  const trimmed = command.trim();
19798
19850
  if (!trimmed) return null;
19799
- if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
19851
+ if (SHELL_METACHAR_RE.test(trimmed)) return null;
19800
19852
  const tokens = trimmed.split(/\s+/).filter(Boolean);
19801
19853
  if (!tokens.length) return null;
19802
- if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
19854
+ const isWin32 = process.platform === "win32";
19855
+ for (let i = 0; i < tokens.length; i++) {
19856
+ const re = isWin32 && i === 0 ? SAFE_WIN32_EXEC_TOKEN_RE : SAFE_TOKEN_RE;
19857
+ if (!re.test(tokens[i])) return null;
19858
+ }
19803
19859
  return tokens;
19804
19860
  }
19805
19861
  function validateCategory(value) {
@@ -20009,12 +20065,13 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
20009
20065
  }
20010
20066
 
20011
20067
  // src/mesh/worktree-bootstrap-config.ts
20012
- var import_fs8 = require("fs");
20068
+ var import_fs9 = require("fs");
20013
20069
  var import_path8 = require("path");
20014
20070
  var import_node_child_process3 = require("child_process");
20015
20071
  var import_node_crypto2 = require("crypto");
20016
20072
  var import_node_util3 = require("util");
20017
20073
  var yaml3 = __toESM(require("js-yaml"));
20074
+ init_resolve_executable();
20018
20075
  var MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
20019
20076
  ".adhdev/worktree_bootstrap.json",
20020
20077
  ".adhdev/worktree_bootstrap.yaml",
@@ -20102,9 +20159,9 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
20102
20159
  }
20103
20160
  for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
20104
20161
  const configPath = (0, import_path8.join)(workspace, relative5);
20105
- if (!(0, import_fs8.existsSync)(configPath)) continue;
20162
+ if (!(0, import_fs9.existsSync)(configPath)) continue;
20106
20163
  try {
20107
- const parsed = parseConfigText3(configPath, (0, import_fs8.readFileSync)(configPath, "utf-8"));
20164
+ const parsed = parseConfigText3(configPath, (0, import_fs9.readFileSync)(configPath, "utf-8"));
20108
20165
  const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
20109
20166
  if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
20110
20167
  return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
@@ -20119,7 +20176,7 @@ function computeStaleInputsDigest(workspace, staleInputs) {
20119
20176
  for (const relative5 of staleInputs ?? []) {
20120
20177
  const filePath = (0, import_path8.join)(workspace, relative5);
20121
20178
  try {
20122
- digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs8.readFileSync)(filePath)).digest("hex");
20179
+ digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs9.readFileSync)(filePath)).digest("hex");
20123
20180
  } catch {
20124
20181
  digest[relative5] = "absent";
20125
20182
  }
@@ -20189,10 +20246,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
20189
20246
  staleInputs: loaded.config.staleInputs
20190
20247
  };
20191
20248
  const staleInputPaths = loaded.config.staleInputs ?? [];
20192
- const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs8.existsSync)((0, import_path8.join)(workspace, p)));
20249
+ const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs9.existsSync)((0, import_path8.join)(workspace, p)));
20193
20250
  for (const command of validation.commands) {
20194
20251
  if (initiallyAbsent.length > 0) {
20195
- const appearedNow = initiallyAbsent.filter((p) => (0, import_fs8.existsSync)((0, import_path8.join)(workspace, p)));
20252
+ const appearedNow = initiallyAbsent.filter((p) => (0, import_fs9.existsSync)((0, import_path8.join)(workspace, p)));
20196
20253
  if (appearedNow.length > 0) {
20197
20254
  state.status = "stale";
20198
20255
  state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -20203,8 +20260,9 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
20203
20260
  const cwd = command.cwd ? (0, import_path8.resolve)(workspace, command.cwd) : workspace;
20204
20261
  const startedAt = Date.now();
20205
20262
  state.lastCommand = command.displayCommand;
20263
+ const resolvedCommand = resolveWin32Executable(command.command);
20206
20264
  try {
20207
- const result = await execFileAsync4(command.command, command.args, {
20265
+ const result = await execFileAsync4(resolvedCommand, command.args, {
20208
20266
  cwd,
20209
20267
  encoding: "utf8",
20210
20268
  timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
@@ -20439,7 +20497,7 @@ var P2pRelayFailureError = class extends Error {
20439
20497
  };
20440
20498
 
20441
20499
  // src/config/state-store.ts
20442
- var import_fs12 = require("fs");
20500
+ var import_fs13 = require("fs");
20443
20501
  var import_path10 = require("path");
20444
20502
  init_config();
20445
20503
  var DEFAULT_STATE = {
@@ -20490,11 +20548,11 @@ function normalizeState(raw) {
20490
20548
  }
20491
20549
  function loadState() {
20492
20550
  const statePath = getStatePath();
20493
- if (!(0, import_fs12.existsSync)(statePath)) {
20551
+ if (!(0, import_fs13.existsSync)(statePath)) {
20494
20552
  return { ...DEFAULT_STATE };
20495
20553
  }
20496
20554
  try {
20497
- const raw = (0, import_fs12.readFileSync)(statePath, "utf-8");
20555
+ const raw = (0, import_fs13.readFileSync)(statePath, "utf-8");
20498
20556
  return normalizeState(JSON.parse(raw));
20499
20557
  } catch {
20500
20558
  return { ...DEFAULT_STATE };
@@ -20503,28 +20561,28 @@ function loadState() {
20503
20561
  function saveState(state) {
20504
20562
  const statePath = getStatePath();
20505
20563
  const normalized = normalizeState(state);
20506
- (0, import_fs12.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
20564
+ (0, import_fs13.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
20507
20565
  }
20508
20566
  function resetState() {
20509
20567
  saveState({ ...DEFAULT_STATE });
20510
20568
  }
20511
20569
 
20512
20570
  // src/detection/ide-detector.ts
20513
- var import_child_process2 = require("child_process");
20571
+ var import_child_process3 = require("child_process");
20514
20572
  var import_util = require("util");
20515
- var import_fs13 = require("fs");
20573
+ var import_fs14 = require("fs");
20516
20574
  var import_os2 = require("os");
20517
- var path13 = __toESM(require("path"));
20575
+ var path14 = __toESM(require("path"));
20518
20576
 
20519
20577
  // src/detection/win32-ide-version.ts
20520
20578
  var fs5 = __toESM(require("fs"));
20521
- var path12 = __toESM(require("path"));
20579
+ var path13 = __toESM(require("path"));
20522
20580
  function manifestCandidates(exeDir) {
20523
20581
  return [
20524
- path12.join(exeDir, "resources", "app", "product.json"),
20525
- path12.join(exeDir, "resources", "app", "package.json"),
20582
+ path13.join(exeDir, "resources", "app", "product.json"),
20583
+ path13.join(exeDir, "resources", "app", "package.json"),
20526
20584
  // Some packagings keep product.json one level up.
20527
- path12.join(exeDir, "product.json")
20585
+ path13.join(exeDir, "product.json")
20528
20586
  ];
20529
20587
  }
20530
20588
  function parseVersionFromManifest(raw) {
@@ -20542,9 +20600,9 @@ function readWin32IdeVersionFromDisk(exePath) {
20542
20600
  if (!exePath) return null;
20543
20601
  let exeDir;
20544
20602
  try {
20545
- exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path12.dirname(exePath);
20603
+ exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path13.dirname(exePath);
20546
20604
  } catch {
20547
- exeDir = path12.dirname(exePath);
20605
+ exeDir = path13.dirname(exePath);
20548
20606
  }
20549
20607
  for (const candidate of manifestCandidates(exeDir)) {
20550
20608
  try {
@@ -20558,7 +20616,7 @@ function readWin32IdeVersionFromDisk(exePath) {
20558
20616
  }
20559
20617
  function isKnownWin32GuiExe(binPath, win32ProcessNames) {
20560
20618
  if (!binPath) return false;
20561
- const base = path12.win32.basename(binPath).toLowerCase();
20619
+ const base = path13.win32.basename(binPath).toLowerCase();
20562
20620
  if (!base.endsWith(".exe")) return false;
20563
20621
  for (const names of Object.values(win32ProcessNames)) {
20564
20622
  for (const name of names) {
@@ -20571,7 +20629,7 @@ function isKnownWin32GuiExe(binPath, win32ProcessNames) {
20571
20629
  }
20572
20630
 
20573
20631
  // src/detection/ide-detector.ts
20574
- var execAsync2 = (0, import_util.promisify)(import_child_process2.exec);
20632
+ var execAsync2 = (0, import_util.promisify)(import_child_process3.exec);
20575
20633
  var BUILTIN_IDE_DEFINITIONS = [];
20576
20634
  var registeredIDEs = /* @__PURE__ */ new Map();
20577
20635
  function registerIDEDefinition(def) {
@@ -20590,10 +20648,10 @@ function getMergedDefinitions() {
20590
20648
  function findCliCommand(command) {
20591
20649
  const trimmed = String(command || "").trim();
20592
20650
  if (!trimmed) return null;
20593
- if (path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
20594
- const candidate = trimmed.startsWith("~") ? path13.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
20595
- const resolved = path13.isAbsolute(candidate) ? candidate : path13.resolve(candidate);
20596
- return (0, import_fs13.existsSync)(resolved) ? resolved : null;
20651
+ if (path14.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
20652
+ const candidate = trimmed.startsWith("~") ? path14.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
20653
+ const resolved = path14.isAbsolute(candidate) ? candidate : path14.resolve(candidate);
20654
+ return (0, import_fs14.existsSync)(resolved) ? resolved : null;
20597
20655
  }
20598
20656
  const isWin = (0, import_os2.platform)() === "win32";
20599
20657
  const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
@@ -20601,10 +20659,10 @@ function findCliCommand(command) {
20601
20659
  for (const p of paths) {
20602
20660
  if (!p) continue;
20603
20661
  for (const ext of exes) {
20604
- const fullPath = path13.join(p, trimmed + ext);
20662
+ const fullPath = path14.join(p, trimmed + ext);
20605
20663
  try {
20606
- if ((0, import_fs13.existsSync)(fullPath)) {
20607
- const stat2 = (0, import_fs13.statSync)(fullPath);
20664
+ if ((0, import_fs14.existsSync)(fullPath)) {
20665
+ const stat2 = (0, import_fs14.statSync)(fullPath);
20608
20666
  if (stat2.isFile() && (isWin || stat2.mode & 73)) {
20609
20667
  return fullPath;
20610
20668
  }
@@ -20618,13 +20676,13 @@ function findCliCommand(command) {
20618
20676
  function checkPathExists(paths) {
20619
20677
  const home = (0, import_os2.homedir)();
20620
20678
  for (const p of paths) {
20621
- const normalized = p.startsWith("~") ? path13.join(home, p.slice(1)) : p;
20679
+ const normalized = p.startsWith("~") ? path14.join(home, p.slice(1)) : p;
20622
20680
  if (normalized.includes("*")) {
20623
20681
  const username = home.split(/[\\/]/).pop() || "";
20624
20682
  const resolved = normalized.replace("*", username);
20625
- if ((0, import_fs13.existsSync)(resolved)) return resolved;
20683
+ if ((0, import_fs14.existsSync)(resolved)) return resolved;
20626
20684
  } else {
20627
- if ((0, import_fs13.existsSync)(normalized)) return normalized;
20685
+ if ((0, import_fs14.existsSync)(normalized)) return normalized;
20628
20686
  }
20629
20687
  }
20630
20688
  return null;
@@ -20638,7 +20696,7 @@ async function detectIDEs(providerLoader) {
20638
20696
  let resolvedCli = cliPath;
20639
20697
  if (!resolvedCli && appPath && os30 === "darwin") {
20640
20698
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
20641
- if ((0, import_fs13.existsSync)(bundledCli)) resolvedCli = bundledCli;
20699
+ if ((0, import_fs14.existsSync)(bundledCli)) resolvedCli = bundledCli;
20642
20700
  }
20643
20701
  if (!resolvedCli && appPath && os30 === "win32") {
20644
20702
  const { dirname: dirname17 } = await import("path");
@@ -20651,7 +20709,7 @@ async function detectIDEs(providerLoader) {
20651
20709
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
20652
20710
  ];
20653
20711
  for (const c of candidates) {
20654
- if ((0, import_fs13.existsSync)(c)) {
20712
+ if ((0, import_fs14.existsSync)(c)) {
20655
20713
  resolvedCli = c;
20656
20714
  break;
20657
20715
  }
@@ -20678,9 +20736,9 @@ init_cli_detector();
20678
20736
 
20679
20737
  // src/system/host-memory.ts
20680
20738
  var os7 = __toESM(require("os"));
20681
- var import_child_process3 = require("child_process");
20739
+ var import_child_process4 = require("child_process");
20682
20740
  var import_util2 = require("util");
20683
- var execAsync3 = (0, import_util2.promisify)(import_child_process3.exec);
20741
+ var execAsync3 = (0, import_util2.promisify)(import_child_process4.exec);
20684
20742
  var cachedDarwinAvail = null;
20685
20743
  var darwinMemoryInterval = null;
20686
20744
  async function updateDarwinMemoryCache() {
@@ -22509,10 +22567,10 @@ ${cleanBody}`;
22509
22567
 
22510
22568
  // src/config/chat-history.ts
22511
22569
  var fs6 = __toESM(require("fs"));
22512
- var path14 = __toESM(require("path"));
22570
+ var path15 = __toESM(require("path"));
22513
22571
  var os8 = __toESM(require("os"));
22514
22572
  init_chat_message_normalization();
22515
- var HISTORY_DIR = path14.join(os8.homedir(), ".adhdev", "history");
22573
+ var HISTORY_DIR = path15.join(os8.homedir(), ".adhdev", "history");
22516
22574
  var RETAIN_DAYS = 30;
22517
22575
  var SAVED_HISTORY_INDEX_VERSION = 1;
22518
22576
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -22698,7 +22756,7 @@ function extractSavedHistorySessionIdFromFile(file) {
22698
22756
  function buildSavedHistoryFileSignatureMap(dir, files) {
22699
22757
  return new Map(files.map((file) => {
22700
22758
  try {
22701
- const stat2 = fs6.statSync(path14.join(dir, file));
22759
+ const stat2 = fs6.statSync(path15.join(dir, file));
22702
22760
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
22703
22761
  } catch {
22704
22762
  return [file, `${file}:missing`];
@@ -22709,7 +22767,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
22709
22767
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
22710
22768
  }
22711
22769
  function getSavedHistoryIndexFilePath(dir) {
22712
- return path14.join(dir, SAVED_HISTORY_INDEX_FILE);
22770
+ return path15.join(dir, SAVED_HISTORY_INDEX_FILE);
22713
22771
  }
22714
22772
  function getSavedHistoryIndexLockPath(dir) {
22715
22773
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -22811,7 +22869,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
22811
22869
  }
22812
22870
  for (const file of Array.from(currentEntries.keys())) {
22813
22871
  if (incomingFiles.has(file)) continue;
22814
- if (!fs6.existsSync(path14.join(dir, file))) {
22872
+ if (!fs6.existsSync(path15.join(dir, file))) {
22815
22873
  currentEntries.delete(file);
22816
22874
  }
22817
22875
  }
@@ -22837,7 +22895,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
22837
22895
  const indexStat = fs6.statSync(getSavedHistoryIndexFilePath(dir));
22838
22896
  const files = listHistoryFiles(dir);
22839
22897
  for (const file of files) {
22840
- const stat2 = fs6.statSync(path14.join(dir, file));
22898
+ const stat2 = fs6.statSync(path15.join(dir, file));
22841
22899
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
22842
22900
  }
22843
22901
  return false;
@@ -22847,14 +22905,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
22847
22905
  }
22848
22906
  function buildSavedHistoryFileSignature(dir, file) {
22849
22907
  try {
22850
- const stat2 = fs6.statSync(path14.join(dir, file));
22908
+ const stat2 = fs6.statSync(path15.join(dir, file));
22851
22909
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
22852
22910
  } catch {
22853
22911
  return `${file}:missing`;
22854
22912
  }
22855
22913
  }
22856
22914
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
22857
- const filePath = path14.join(dir, file);
22915
+ const filePath = path15.join(dir, file);
22858
22916
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
22859
22917
  const currentEntry = entries.get(file) || null;
22860
22918
  const nextSummary = updater(currentEntry?.summary || null);
@@ -22927,7 +22985,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
22927
22985
  function computeSavedHistoryFileSummary(dir, file) {
22928
22986
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
22929
22987
  if (!historySessionId) return null;
22930
- const filePath = path14.join(dir, file);
22988
+ const filePath = path15.join(dir, file);
22931
22989
  const content = fs6.readFileSync(filePath, "utf-8");
22932
22990
  const lines = content.split("\n").filter(Boolean);
22933
22991
  let messageCount = 0;
@@ -23014,7 +23072,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
23014
23072
  const summaryBySessionId = /* @__PURE__ */ new Map();
23015
23073
  const nextPersistedEntries = /* @__PURE__ */ new Map();
23016
23074
  for (const file of files.slice().sort()) {
23017
- const filePath = path14.join(dir, file);
23075
+ const filePath = path15.join(dir, file);
23018
23076
  const signature = fileSignatures.get(file) || `${file}:missing`;
23019
23077
  const cached3 = savedHistoryFileSummaryCache.get(filePath);
23020
23078
  const persisted = persistedEntries.get(file);
@@ -23134,12 +23192,12 @@ var ChatHistoryWriter = class {
23134
23192
  });
23135
23193
  }
23136
23194
  if (newMessages.length === 0) return;
23137
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23195
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23138
23196
  fs6.mkdirSync(dir, { recursive: true });
23139
23197
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
23140
23198
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
23141
23199
  const fileName = `${filePrefix}${date}.jsonl`;
23142
- const filePath = path14.join(dir, fileName);
23200
+ const filePath = path15.join(dir, fileName);
23143
23201
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
23144
23202
  fs6.appendFileSync(filePath, lines, "utf-8");
23145
23203
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -23230,11 +23288,11 @@ var ChatHistoryWriter = class {
23230
23288
  const ws = String(workspace || "").trim();
23231
23289
  if (!id || !ws) return;
23232
23290
  try {
23233
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23291
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23234
23292
  fs6.mkdirSync(dir, { recursive: true });
23235
23293
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
23236
23294
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
23237
- const filePath = path14.join(dir, fileName);
23295
+ const filePath = path15.join(dir, fileName);
23238
23296
  const record = {
23239
23297
  ts: (/* @__PURE__ */ new Date()).toISOString(),
23240
23298
  receivedAt: Date.now(),
@@ -23280,14 +23338,14 @@ var ChatHistoryWriter = class {
23280
23338
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
23281
23339
  this.lastSeenCounts.delete(fromDedupKey);
23282
23340
  }
23283
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23341
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23284
23342
  if (!fs6.existsSync(dir)) return;
23285
23343
  const fromPrefix = `${this.sanitize(fromId)}_`;
23286
23344
  const toPrefix = `${this.sanitize(toId)}_`;
23287
23345
  const files = fs6.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
23288
23346
  for (const file of files) {
23289
- const sourcePath = path14.join(dir, file);
23290
- const targetPath = path14.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
23347
+ const sourcePath = path15.join(dir, file);
23348
+ const targetPath = path15.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
23291
23349
  const sourceLines = fs6.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
23292
23350
  const rewritten = sourceLines.map((line) => {
23293
23351
  try {
@@ -23321,13 +23379,13 @@ var ChatHistoryWriter = class {
23321
23379
  const sessionId = String(historySessionId || "").trim();
23322
23380
  if (!sessionId) return;
23323
23381
  try {
23324
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23382
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23325
23383
  if (!fs6.existsSync(dir)) return;
23326
23384
  const prefix = `${this.sanitize(sessionId)}_`;
23327
23385
  const files = fs6.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
23328
23386
  const seen = /* @__PURE__ */ new Set();
23329
23387
  for (const file of files) {
23330
- const filePath = path14.join(dir, file);
23388
+ const filePath = path15.join(dir, file);
23331
23389
  const lines = fs6.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
23332
23390
  const next = [];
23333
23391
  for (const line of lines) {
@@ -23381,11 +23439,11 @@ var ChatHistoryWriter = class {
23381
23439
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
23382
23440
  const agentDirs = fs6.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
23383
23441
  for (const dir of agentDirs) {
23384
- const dirPath = path14.join(HISTORY_DIR, dir.name);
23442
+ const dirPath = path15.join(HISTORY_DIR, dir.name);
23385
23443
  const files = fs6.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
23386
23444
  let removedAny = false;
23387
23445
  for (const file of files) {
23388
- const filePath = path14.join(dirPath, file);
23446
+ const filePath = path15.join(dirPath, file);
23389
23447
  const stat2 = fs6.statSync(filePath);
23390
23448
  if (stat2.mtimeMs < cutoff) {
23391
23449
  fs6.unlinkSync(filePath);
@@ -23588,7 +23646,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
23588
23646
  const seen = /* @__PURE__ */ new Set();
23589
23647
  let readAllFiles = true;
23590
23648
  for (let f = 0; f < files.length; f++) {
23591
- const filePath = path14.join(dir, files[f]);
23649
+ const filePath = path15.join(dir, files[f]);
23592
23650
  const remaining = Math.max(0, needed - collected.length);
23593
23651
  const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
23594
23652
  const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
@@ -23621,7 +23679,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
23621
23679
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
23622
23680
  try {
23623
23681
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
23624
- const dir = path14.join(HISTORY_DIR, sanitized);
23682
+ const dir = path15.join(HISTORY_DIR, sanitized);
23625
23683
  if (!fs6.existsSync(dir)) return { messages: [], hasMore: false };
23626
23684
  const files = listHistoryFiles(dir, historySessionId);
23627
23685
  const bounded = isBoundedTailRequest(limit, offset, excludeRecentCount);
@@ -23644,7 +23702,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
23644
23702
  const allMessages = [];
23645
23703
  const seen = /* @__PURE__ */ new Set();
23646
23704
  for (const file of files) {
23647
- const filePath = path14.join(dir, file);
23705
+ const filePath = path15.join(dir, file);
23648
23706
  const content = fs6.readFileSync(filePath, "utf-8");
23649
23707
  const lines = content.trim().split("\n").filter(Boolean);
23650
23708
  for (let i = 0; i < lines.length; i++) {
@@ -23668,7 +23726,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
23668
23726
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
23669
23727
  try {
23670
23728
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
23671
- const dir = path14.join(HISTORY_DIR, sanitized);
23729
+ const dir = path15.join(HISTORY_DIR, sanitized);
23672
23730
  if (!fs6.existsSync(dir)) {
23673
23731
  savedHistorySessionCache.delete(sanitized);
23674
23732
  return { sessions: [], hasMore: false };
@@ -23729,11 +23787,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
23729
23787
  }
23730
23788
  function readExistingSessionStartRecord(agentType, historySessionId) {
23731
23789
  try {
23732
- const dir = path14.join(HISTORY_DIR, agentType);
23790
+ const dir = path15.join(HISTORY_DIR, agentType);
23733
23791
  if (!fs6.existsSync(dir)) return null;
23734
23792
  const files = listHistoryFiles(dir, historySessionId).sort();
23735
23793
  for (const file of files) {
23736
- const lines = fs6.readFileSync(path14.join(dir, file), "utf-8").split("\n").filter(Boolean);
23794
+ const lines = fs6.readFileSync(path15.join(dir, file), "utf-8").split("\n").filter(Boolean);
23737
23795
  for (const line of lines) {
23738
23796
  try {
23739
23797
  const parsed = JSON.parse(line);
@@ -23753,16 +23811,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
23753
23811
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
23754
23812
  if (records.length === 0) return false;
23755
23813
  try {
23756
- const dir = path14.join(HISTORY_DIR, agentType);
23814
+ const dir = path15.join(HISTORY_DIR, agentType);
23757
23815
  fs6.mkdirSync(dir, { recursive: true });
23758
23816
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
23759
23817
  for (const file of fs6.readdirSync(dir)) {
23760
23818
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
23761
- fs6.unlinkSync(path14.join(dir, file));
23819
+ fs6.unlinkSync(path15.join(dir, file));
23762
23820
  }
23763
23821
  }
23764
23822
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
23765
- const filePath = path14.join(dir, `${prefix}${targetDate}.jsonl`);
23823
+ const filePath = path15.join(dir, `${prefix}${targetDate}.jsonl`);
23766
23824
  fs6.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
23767
23825
  `, "utf-8");
23768
23826
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -26367,7 +26425,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
26367
26425
  // src/commands/chat-commands.ts
26368
26426
  var fs7 = __toESM(require("fs"));
26369
26427
  var os9 = __toESM(require("os"));
26370
- var path15 = __toESM(require("path"));
26428
+ var path16 = __toESM(require("path"));
26371
26429
  var import_node_crypto3 = require("crypto");
26372
26430
  init_contracts();
26373
26431
  init_logger();
@@ -27418,7 +27476,7 @@ function readExactRuntimeMirrorMessages(args) {
27418
27476
  function normalizeComparableWorkspace(value) {
27419
27477
  const text = typeof value === "string" ? value.trim() : "";
27420
27478
  if (!text) return "";
27421
- return path15.resolve(text);
27479
+ return path16.resolve(text);
27422
27480
  }
27423
27481
  function isCurrentRuntimePtySafelyAttributed(args) {
27424
27482
  if (args.adapter.cliType !== "codex-cli") return false;
@@ -27903,7 +27961,7 @@ function buildDebugBundleText(bundle) {
27903
27961
  }
27904
27962
  function getChatDebugBundleDir() {
27905
27963
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
27906
- return override || path15.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
27964
+ return override || path16.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
27907
27965
  }
27908
27966
  function safeBundleIdSegment(value, fallback) {
27909
27967
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -27960,7 +28018,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
27960
28018
  const bundleId = createChatDebugBundleId(targetSessionId);
27961
28019
  const dir = getChatDebugBundleDir();
27962
28020
  fs7.mkdirSync(dir, { recursive: true });
27963
- const savedPath = path15.join(dir, `${bundleId}.json`);
28021
+ const savedPath = path16.join(dir, `${bundleId}.json`);
27964
28022
  const json = `${JSON.stringify(bundle, null, 2)}
27965
28023
  `;
27966
28024
  fs7.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -29524,7 +29582,7 @@ async function handleResolveAction(h, args) {
29524
29582
 
29525
29583
  // src/commands/cdp-commands.ts
29526
29584
  var fs8 = __toESM(require("fs"));
29527
- var path16 = __toESM(require("path"));
29585
+ var path17 = __toESM(require("path"));
29528
29586
  var os10 = __toESM(require("os"));
29529
29587
  var KEY_TO_VK = {
29530
29588
  Backspace: 8,
@@ -29781,25 +29839,25 @@ function resolveSafePath(requestedPath) {
29781
29839
  const inputPath = rawPath || ".";
29782
29840
  const home = os10.homedir();
29783
29841
  if (inputPath.startsWith("~")) {
29784
- return path16.resolve(path16.join(home, inputPath.slice(1)));
29842
+ return path17.resolve(path17.join(home, inputPath.slice(1)));
29785
29843
  }
29786
29844
  if (process.platform === "win32") {
29787
29845
  const normalized = normalizeWindowsRequestedPath(inputPath);
29788
- if (path16.win32.isAbsolute(normalized)) {
29789
- return path16.win32.normalize(normalized);
29846
+ if (path17.win32.isAbsolute(normalized)) {
29847
+ return path17.win32.normalize(normalized);
29790
29848
  }
29791
- return path16.win32.resolve(normalized);
29849
+ return path17.win32.resolve(normalized);
29792
29850
  }
29793
- if (path16.isAbsolute(inputPath)) {
29794
- return path16.normalize(inputPath);
29851
+ if (path17.isAbsolute(inputPath)) {
29852
+ return path17.normalize(inputPath);
29795
29853
  }
29796
- return path16.resolve(inputPath);
29854
+ return path17.resolve(inputPath);
29797
29855
  }
29798
29856
  function listDirectoryEntriesSafe(dirPath) {
29799
29857
  const entries = fs8.readdirSync(dirPath, { withFileTypes: true });
29800
29858
  const files = [];
29801
29859
  for (const entry of entries) {
29802
- const entryPath = path16.join(dirPath, entry.name);
29860
+ const entryPath = path17.join(dirPath, entry.name);
29803
29861
  try {
29804
29862
  if (entry.isDirectory()) {
29805
29863
  files.push({ name: entry.name, type: "directory" });
@@ -29853,7 +29911,7 @@ async function handleFileRead(h, args) {
29853
29911
  async function handleFileWrite(h, args) {
29854
29912
  try {
29855
29913
  const filePath = resolveSafePath(args?.path);
29856
- fs8.mkdirSync(path16.dirname(filePath), { recursive: true });
29914
+ fs8.mkdirSync(path17.dirname(filePath), { recursive: true });
29857
29915
  fs8.writeFileSync(filePath, args?.content || "", "utf-8");
29858
29916
  return { success: true, path: filePath };
29859
29917
  } catch (e) {
@@ -43661,6 +43719,7 @@ var import_os3 = require("os");
43661
43719
  var import_path12 = require("path");
43662
43720
  var fs26 = __toESM(require("fs"));
43663
43721
  var import_node_child_process6 = require("child_process");
43722
+ init_resolve_executable();
43664
43723
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
43665
43724
  var CHANNEL_SERVER_URL = {
43666
43725
  stable: "https://api.adhf.dev",
@@ -44759,6 +44818,18 @@ function truncateValidationOutput(value) {
44759
44818
  return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
44760
44819
  [truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
44761
44820
  }
44821
+ function isSpawnResolutionError(error) {
44822
+ if (!error) return false;
44823
+ if (error.code === "ENOENT" && typeof error.syscall === "string" && error.syscall.startsWith("spawn")) return true;
44824
+ return error.code === "ENOENT" && (error.syscall === void 0 || String(error.syscall).startsWith("spawn"));
44825
+ }
44826
+ function describeSpawnError(error, command, spawnResolutionFailed) {
44827
+ if (spawnResolutionFailed) {
44828
+ const hint = process.platform === "win32" ? " On Windows, npm-family commands (npm/npx/tsc/vitest) are .cmd shims that the bare-command spawn search does not resolve; configure an absolute path or ensure the command is on PATH." : "";
44829
+ return `Could not resolve executable "${command}" (spawn ENOENT).${hint}`;
44830
+ }
44831
+ return String(error?.message || error);
44832
+ }
44762
44833
  function recordMeshRefineStage(stages, stage, status, startedAt, details) {
44763
44834
  stages.push({
44764
44835
  stage,
@@ -45660,8 +45731,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45660
45731
  const startedAt = Date.now();
45661
45732
  const cwd = candidate.cwd ? (0, import_path12.resolve)(workspace, candidate.cwd) : workspace;
45662
45733
  const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
45734
+ const resolvedCommand = resolveWin32Executable(candidate.command);
45663
45735
  try {
45664
- const result = await execFileAsync4(candidate.command, candidate.args, {
45736
+ const result = await execFileAsync4(resolvedCommand, candidate.args, {
45665
45737
  cwd,
45666
45738
  encoding: "utf8",
45667
45739
  timeout,
@@ -45670,16 +45742,17 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45670
45742
  });
45671
45743
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
45672
45744
  } catch (error) {
45745
+ const spawnResolutionFailed = isSpawnResolutionError(error);
45673
45746
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
45674
45747
  exitCode: typeof error?.code === "number" ? error.code : null,
45675
45748
  signal: typeof error?.signal === "string" ? error.signal : null,
45676
45749
  timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
45677
- failureKind: "dependency_bootstrap_failed"
45750
+ ...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : { failureKind: "dependency_bootstrap_failed" }
45678
45751
  }));
45679
- summary.bootstrap = { stage: "failed", error: String(error?.message || error) };
45752
+ summary.bootstrap = { stage: "failed", error: describeSpawnError(error, candidate.command, spawnResolutionFailed) };
45680
45753
  summary.status = "failed";
45681
- summary.failureKind = "dependency_bootstrap_failed";
45682
- summary.failureCode = "dependency_bootstrap_failed";
45754
+ summary.failureKind = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
45755
+ summary.failureCode = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
45683
45756
  return summary;
45684
45757
  }
45685
45758
  }
@@ -45702,8 +45775,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45702
45775
  summary.failureCode = "missing_dependencies";
45703
45776
  return summary;
45704
45777
  }
45778
+ const resolvedCommand = resolveWin32Executable(candidate.command);
45705
45779
  try {
45706
- const result = await execFileAsync4(candidate.command, candidate.args, {
45780
+ const result = await execFileAsync4(resolvedCommand, candidate.args, {
45707
45781
  cwd,
45708
45782
  encoding: "utf8",
45709
45783
  timeout,
@@ -45712,16 +45786,21 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45712
45786
  });
45713
45787
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
45714
45788
  } catch (error) {
45789
+ const spawnResolutionFailed = isSpawnResolutionError(error);
45715
45790
  const stderr = truncateValidationOutput(error?.stderr || error?.message);
45716
- const missingDependencyFailure = /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
45791
+ const missingDependencyFailure = !spawnResolutionFailed && /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
45717
45792
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
45718
45793
  exitCode: typeof error?.code === "number" ? error.code : null,
45719
45794
  signal: typeof error?.signal === "string" ? error.signal : null,
45720
45795
  timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
45721
- ...missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
45796
+ ...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
45722
45797
  }));
45723
45798
  summary.status = "failed";
45724
- if (missingDependencyFailure) {
45799
+ if (spawnResolutionFailed) {
45800
+ summary.failureKind = "spawn_resolution_failed";
45801
+ summary.failureCode = "spawn_resolution_failed";
45802
+ summary.spawnResolutionError = describeSpawnError(error, candidate.command, true);
45803
+ } else if (missingDependencyFailure) {
45725
45804
  summary.failureKind = "missing_dependencies";
45726
45805
  summary.failureCode = "missing_dependencies";
45727
45806
  }
@@ -46982,7 +47061,7 @@ var DaemonCommandRouter = class {
46982
47061
  if (validationSummary.status === "failed") {
46983
47062
  const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
46984
47063
  const buildValidationFailedError = () => {
46985
- const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
47064
+ const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : validationSummary.failureCode === "spawn_resolution_failed" ? validationSummary.spawnResolutionError || "Refinery validation command could not be spawned (executable not found); merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
46986
47065
  if (!firstFailedCmd) return base;
46987
47066
  const cmdName = typeof firstFailedCmd.displayCommand === "string" ? firstFailedCmd.displayCommand : typeof firstFailedCmd.command === "string" ? [firstFailedCmd.command, ...Array.isArray(firstFailedCmd.args) ? firstFailedCmd.args : []].join(" ").trim() : typeof firstFailedCmd.cmd === "string" ? firstFailedCmd.cmd : "";
46988
47067
  const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");