@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.mjs CHANGED
@@ -311,10 +311,10 @@ function readInjected(value) {
311
311
  }
312
312
  function getDaemonBuildInfo() {
313
313
  if (cached) return cached;
314
- const commit = readInjected(true ? "5d9635b2a6476691469ecfe32b26a17e13484b2b" : void 0) ?? "unknown";
315
- const commitShort = readInjected(true ? "5d9635b2" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
316
- const version = readInjected(true ? "0.9.82-rc.333" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
317
- const builtAt = readInjected(true ? "2026-06-20T02:23:56.856Z" : void 0);
314
+ const commit = readInjected(true ? "9e5ae5d2814077a6bf9e982b17066ca2051da97b" : void 0) ?? "unknown";
315
+ const commitShort = readInjected(true ? "9e5ae5d2" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
316
+ const version = readInjected(true ? "0.9.82-rc.334" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
317
+ const builtAt = readInjected(true ? "2026-06-20T03:55:49.426Z" : void 0);
318
318
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
319
319
  return cached;
320
320
  }
@@ -3254,6 +3254,297 @@ var init_mesh_ledger = __esm({
3254
3254
  }
3255
3255
  });
3256
3256
 
3257
+ // src/logging/async-batch-writer.ts
3258
+ import * as fs3 from "fs";
3259
+ var AsyncBatchWriter;
3260
+ var init_async_batch_writer = __esm({
3261
+ "src/logging/async-batch-writer.ts"() {
3262
+ "use strict";
3263
+ AsyncBatchWriter = class {
3264
+ // Maps filePath -> string buffer
3265
+ static buffers = /* @__PURE__ */ new Map();
3266
+ static writePromises = /* @__PURE__ */ new Map();
3267
+ static flushTimer = null;
3268
+ /**
3269
+ * Queues data to be written to a file asynchronously in a batch.
3270
+ */
3271
+ static write(filePath, data) {
3272
+ let buf = this.buffers.get(filePath);
3273
+ if (!buf) {
3274
+ buf = [];
3275
+ this.buffers.set(filePath, buf);
3276
+ }
3277
+ buf.push(data);
3278
+ if (!this.flushTimer) {
3279
+ this.flushTimer = setTimeout(() => {
3280
+ this.flushTimer = null;
3281
+ this.flushAll();
3282
+ }, 50);
3283
+ }
3284
+ }
3285
+ static async flushAll() {
3286
+ const entries = Array.from(this.buffers.entries());
3287
+ this.buffers.clear();
3288
+ for (const [filePath, buffer] of entries) {
3289
+ const dataToWrite = buffer.join("");
3290
+ const doWrite = async () => {
3291
+ try {
3292
+ const prevPromise = this.writePromises.get(filePath);
3293
+ if (prevPromise) await prevPromise;
3294
+ await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
3295
+ } catch {
3296
+ }
3297
+ };
3298
+ const writePromise = doWrite();
3299
+ this.writePromises.set(filePath, writePromise);
3300
+ writePromise.finally(() => {
3301
+ if (this.writePromises.get(filePath) === writePromise) {
3302
+ this.writePromises.delete(filePath);
3303
+ }
3304
+ });
3305
+ }
3306
+ }
3307
+ };
3308
+ }
3309
+ });
3310
+
3311
+ // src/logging/logger.ts
3312
+ var logger_exports = {};
3313
+ __export(logger_exports, {
3314
+ LOG: () => LOG,
3315
+ LOG_DIR_PATH: () => LOG_DIR_PATH,
3316
+ LOG_PATH: () => LOG_PATH,
3317
+ daemonLog: () => daemonLog,
3318
+ getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
3319
+ getDaemonLogDir: () => getDaemonLogDir,
3320
+ getLogBufferSize: () => getLogBufferSize,
3321
+ getLogLevel: () => getLogLevel,
3322
+ getLogPath: () => getLogPath,
3323
+ getRecentLogs: () => getRecentLogs,
3324
+ installGlobalInterceptor: () => installGlobalInterceptor,
3325
+ setLogLevel: () => setLogLevel
3326
+ });
3327
+ import * as fs4 from "fs";
3328
+ import * as path9 from "path";
3329
+ import * as os3 from "os";
3330
+ function setLogLevel(level) {
3331
+ currentLevel = level;
3332
+ daemonLog("Logger", `Log level set to: ${level}`, "info");
3333
+ }
3334
+ function getLogLevel() {
3335
+ return currentLevel;
3336
+ }
3337
+ function getDateStr() {
3338
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3339
+ }
3340
+ function getDaemonLogDir() {
3341
+ return LOG_DIR;
3342
+ }
3343
+ function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
3344
+ return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
3345
+ }
3346
+ function checkDateRotation() {
3347
+ const today = getDateStr();
3348
+ if (today !== currentDate) {
3349
+ currentDate = today;
3350
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
3351
+ cleanOldLogs();
3352
+ }
3353
+ }
3354
+ function cleanOldLogs() {
3355
+ try {
3356
+ const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
3357
+ const cutoff = /* @__PURE__ */ new Date();
3358
+ cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
3359
+ const cutoffStr = cutoff.toISOString().slice(0, 10);
3360
+ for (const file of files) {
3361
+ const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
3362
+ if (dateMatch && dateMatch[1] < cutoffStr) {
3363
+ try {
3364
+ fs4.unlinkSync(path9.join(LOG_DIR, file));
3365
+ } catch {
3366
+ }
3367
+ }
3368
+ }
3369
+ } catch {
3370
+ }
3371
+ }
3372
+ function rotateSizeIfNeeded() {
3373
+ try {
3374
+ const stat2 = fs4.statSync(currentLogFile);
3375
+ if (stat2.size > MAX_LOG_SIZE) {
3376
+ const backup = currentLogFile.replace(".log", ".1.log");
3377
+ try {
3378
+ fs4.unlinkSync(backup);
3379
+ } catch {
3380
+ }
3381
+ fs4.renameSync(currentLogFile, backup);
3382
+ }
3383
+ } catch {
3384
+ }
3385
+ }
3386
+ function writeToFile(line) {
3387
+ try {
3388
+ if (++writeCount % 1e3 === 0) {
3389
+ checkDateRotation();
3390
+ rotateSizeIfNeeded();
3391
+ }
3392
+ AsyncBatchWriter.write(currentLogFile, line + "\n");
3393
+ } catch {
3394
+ }
3395
+ }
3396
+ function getRecentLogs(count = 50, minLevel = "info") {
3397
+ const minNum = LEVEL_NUM[minLevel];
3398
+ const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
3399
+ return filtered.slice(-count);
3400
+ }
3401
+ function getLogBufferSize() {
3402
+ return ringBuffer.length;
3403
+ }
3404
+ function ts() {
3405
+ return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
3406
+ }
3407
+ function fullTs() {
3408
+ return (/* @__PURE__ */ new Date()).toISOString();
3409
+ }
3410
+ function daemonLog(category, msg, level = "info") {
3411
+ const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
3412
+ const label = LEVEL_LABEL[level];
3413
+ const line = `[${ts()}] [${label}] [${category}] ${msg}`;
3414
+ if (!shouldOutput) return;
3415
+ writeToFile(line);
3416
+ ringBuffer.push({ ts: Date.now(), level, category, message: msg });
3417
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3418
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3419
+ }
3420
+ origConsoleLog(line);
3421
+ }
3422
+ function installGlobalInterceptor() {
3423
+ if (interceptorInstalled) return;
3424
+ interceptorInstalled = true;
3425
+ const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
3426
+ const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
3427
+ console.log = (...args) => {
3428
+ origConsoleLog(...args);
3429
+ try {
3430
+ const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
3431
+ const clean = stripAnsi4(msg);
3432
+ if (isDaemonLogLine(clean)) return;
3433
+ const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
3434
+ writeToFile(line);
3435
+ const catMatch = clean.match(/\[([^\]]+)\]/);
3436
+ ringBuffer.push({
3437
+ ts: Date.now(),
3438
+ level: "info",
3439
+ category: catMatch?.[1] || "System",
3440
+ message: clean
3441
+ });
3442
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3443
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3444
+ }
3445
+ } catch {
3446
+ }
3447
+ };
3448
+ console.error = (...args) => {
3449
+ origConsoleError(...args);
3450
+ try {
3451
+ const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
3452
+ const clean = stripAnsi4(msg);
3453
+ if (isDaemonLogLine(clean)) return;
3454
+ const line = `[${fullTs()}] [ERROR] ${clean}`;
3455
+ writeToFile(line);
3456
+ ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
3457
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3458
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3459
+ }
3460
+ } catch {
3461
+ }
3462
+ };
3463
+ console.warn = (...args) => {
3464
+ origConsoleWarn(...args);
3465
+ try {
3466
+ const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
3467
+ const clean = stripAnsi4(msg);
3468
+ if (isDaemonLogLine(clean)) return;
3469
+ const line = `[${fullTs()}] [WARN] ${clean}`;
3470
+ writeToFile(line);
3471
+ ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
3472
+ if (ringBuffer.length > RING_BUFFER_SIZE) {
3473
+ ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
3474
+ }
3475
+ } catch {
3476
+ }
3477
+ };
3478
+ writeToFile(`
3479
+ === ADHDev Daemon started at ${fullTs()} ===`);
3480
+ writeToFile(`Log file: ${currentLogFile}`);
3481
+ writeToFile(`Log level: ${currentLevel}`);
3482
+ }
3483
+ function getLogPath() {
3484
+ return currentLogFile;
3485
+ }
3486
+ var 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;
3487
+ var init_logger = __esm({
3488
+ "src/logging/logger.ts"() {
3489
+ "use strict";
3490
+ init_async_batch_writer();
3491
+ LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
3492
+ LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
3493
+ currentLevel = "info";
3494
+ 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");
3495
+ MAX_LOG_SIZE = 5 * 1024 * 1024;
3496
+ MAX_LOG_DAYS = 7;
3497
+ try {
3498
+ fs4.mkdirSync(LOG_DIR, { recursive: true });
3499
+ } catch {
3500
+ }
3501
+ currentDate = getDateStr();
3502
+ currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
3503
+ cleanOldLogs();
3504
+ try {
3505
+ const oldLog = path9.join(LOG_DIR, "daemon.log");
3506
+ if (fs4.existsSync(oldLog)) {
3507
+ const stat2 = fs4.statSync(oldLog);
3508
+ const oldDate = stat2.mtime.toISOString().slice(0, 10);
3509
+ fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
3510
+ }
3511
+ const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
3512
+ if (fs4.existsSync(oldLogBackup)) {
3513
+ fs4.unlinkSync(oldLogBackup);
3514
+ }
3515
+ } catch {
3516
+ }
3517
+ writeCount = 0;
3518
+ RING_BUFFER_SIZE = 200;
3519
+ ringBuffer = [];
3520
+ origConsoleLog = console.log.bind(console);
3521
+ origConsoleError = console.error.bind(console);
3522
+ origConsoleWarn = console.warn.bind(console);
3523
+ LOG = {
3524
+ debug: (category, msg) => daemonLog(category, msg, "debug"),
3525
+ info: (category, msg) => daemonLog(category, msg, "info"),
3526
+ warn: (category, msg) => daemonLog(category, msg, "warn"),
3527
+ error: (category, msg) => daemonLog(category, msg, "error"),
3528
+ /**
3529
+ * Create a scoped logger for a specific component.
3530
+ * Category is baked in so callers only pass the message.
3531
+ */
3532
+ forComponent(category) {
3533
+ return {
3534
+ debug: (msg) => daemonLog(category, msg, "debug"),
3535
+ info: (msg) => daemonLog(category, msg, "info"),
3536
+ warn: (msg) => daemonLog(category, msg, "warn"),
3537
+ error: (msg) => daemonLog(category, msg, "error"),
3538
+ asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
3539
+ };
3540
+ }
3541
+ };
3542
+ interceptorInstalled = false;
3543
+ LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
3544
+ LOG_DIR_PATH = LOG_DIR;
3545
+ }
3546
+ });
3547
+
3257
3548
  // src/mesh/mesh-work-queue.ts
3258
3549
  var mesh_work_queue_exports = {};
3259
3550
  __export(mesh_work_queue_exports, {
@@ -3719,11 +4010,18 @@ function requeueTask(meshId, taskId, opts) {
3719
4010
  }
3720
4011
  function updateSessionTaskStatus(meshId, sessionId, status, opts) {
3721
4012
  return withQueueLock(meshId, () => {
4013
+ const store = MeshRuntimeStore.getInstance();
3722
4014
  const occurredAtIso = opts?.occurredAt ? new Date(opts.occurredAt).toISOString() : void 0;
3723
- const entry = MeshRuntimeStore.getInstance().findAssignedBySession(meshId, sessionId, occurredAtIso);
3724
- if (!entry) return null;
4015
+ const entry = store.findAssignedBySession(meshId, sessionId, occurredAtIso, opts?.taskId);
4016
+ if (!entry) {
4017
+ const assignedRows = store.getActiveAssignmentDetails(meshId).filter((r) => r.sessionId === sessionId);
4018
+ if (assignedRows.length > 0) {
4019
+ 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(",")}`);
4020
+ }
4021
+ return null;
4022
+ }
3725
4023
  entry.status = status;
3726
- MeshRuntimeStore.getInstance().updateQueueEntry(entry);
4024
+ store.updateQueueEntry(entry);
3727
4025
  if (DEPENDENCY_FAILURE_TERMINALS.has(status)) propagateDependencyFailure(meshId, entry.id);
3728
4026
  return entry;
3729
4027
  });
@@ -3831,6 +4129,7 @@ var init_mesh_work_queue = __esm({
3831
4129
  init_repo_mesh_types();
3832
4130
  init_mesh_runtime_store();
3833
4131
  init_mesh_config();
4132
+ init_logger();
3834
4133
  ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
3835
4134
  HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
3836
4135
  MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
@@ -3887,8 +4186,8 @@ var init_mesh_work_queue = __esm({
3887
4186
  });
3888
4187
 
3889
4188
  // src/mesh/mesh-runtime-store.ts
3890
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync as renameSync2, statSync as statSync4 } from "fs";
3891
- import { dirname as dirname2, join as join8 } from "path";
4189
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync3, statSync as statSync5 } from "fs";
4190
+ import { dirname as dirname2, join as join9 } from "path";
3892
4191
  function loadDatabaseCtor() {
3893
4192
  if (DatabaseCtor) return DatabaseCtor;
3894
4193
  DatabaseCtor = loadBetterSqlite3();
@@ -3898,20 +4197,20 @@ function safeMeshId(meshId) {
3898
4197
  return meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
3899
4198
  }
3900
4199
  function legacyQueuePath(meshId) {
3901
- return join8(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
4200
+ return join9(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
3902
4201
  }
3903
4202
  function meshRuntimeStorePath() {
3904
4203
  const dir = getLedgerDir();
3905
- const nextPath = join8(dir, "mesh-runtime.db");
3906
- if (existsSync7(nextPath)) return nextPath;
3907
- const legacyPath = join8(dir, "beads.db");
3908
- if (!existsSync7(legacyPath)) return nextPath;
4204
+ const nextPath = join9(dir, "mesh-runtime.db");
4205
+ if (existsSync8(nextPath)) return nextPath;
4206
+ const legacyPath = join9(dir, "beads.db");
4207
+ if (!existsSync8(legacyPath)) return nextPath;
3909
4208
  try {
3910
- renameSync2(legacyPath, nextPath);
4209
+ renameSync3(legacyPath, nextPath);
3911
4210
  for (const suffix of ["-wal", "-shm"]) {
3912
4211
  const legacyCompanion = `${legacyPath}${suffix}`;
3913
- if (existsSync7(legacyCompanion)) {
3914
- renameSync2(legacyCompanion, `${nextPath}${suffix}`);
4212
+ if (existsSync8(legacyCompanion)) {
4213
+ renameSync3(legacyCompanion, `${nextPath}${suffix}`);
3915
4214
  }
3916
4215
  }
3917
4216
  } catch {
@@ -3937,7 +4236,7 @@ var init_mesh_runtime_store = __esm({
3937
4236
  // 50 MB
3938
4237
  constructor(dbPath) {
3939
4238
  const dir = dirname2(dbPath);
3940
- if (!existsSync7(dir)) mkdirSync4(dir, { recursive: true });
4239
+ if (!existsSync8(dir)) mkdirSync5(dir, { recursive: true });
3941
4240
  this.dbPath = dbPath;
3942
4241
  this.db = new (loadDatabaseCtor())(dbPath);
3943
4242
  this.db.pragma("journal_mode = WAL");
@@ -4192,8 +4491,8 @@ var init_mesh_runtime_store = __esm({
4192
4491
  this.walWriteCounter = 0;
4193
4492
  try {
4194
4493
  const walPath = `${this.dbPath}-wal`;
4195
- if (!existsSync7(walPath)) return;
4196
- const size = statSync4(walPath).size;
4494
+ if (!existsSync8(walPath)) return;
4495
+ const size = statSync5(walPath).size;
4197
4496
  if (size < _MeshRuntimeStore.WAL_MAX_BYTES) return;
4198
4497
  process.stderr.write(
4199
4498
  `[adhdev-mesh] WAL file ${Math.round(size / 1024 / 1024)}MB exceeds threshold; forcing checkpoint
@@ -4209,7 +4508,7 @@ var init_mesh_runtime_store = __esm({
4209
4508
  const count = this.db.prepare("SELECT COUNT(*) AS count FROM mesh_queue WHERE mesh_id = ?").get(meshId);
4210
4509
  if (count.count > 0) return;
4211
4510
  const path42 = legacyQueuePath(meshId);
4212
- if (!existsSync7(path42)) return;
4511
+ if (!existsSync8(path42)) return;
4213
4512
  try {
4214
4513
  const entries = JSON.parse(readFileSync6(path42, "utf-8"));
4215
4514
  if (!Array.isArray(entries)) return;
@@ -4489,12 +4788,51 @@ var init_mesh_runtime_store = __esm({
4489
4788
  return { id, nodeId: r.assigned_node_id ?? void 0, sessionId: r.assigned_session_id ?? void 0, message };
4490
4789
  });
4491
4790
  }
4492
- findAssignedBySession(meshId, sessionId, occurredAtIso) {
4791
+ /**
4792
+ * Resolve the `assigned` queue row a completion event belongs to.
4793
+ *
4794
+ * Clock-skew safety (C2): a completion event's `occurredAtIso` carries the
4795
+ * REMOTE WORKER's clock, while `updated_at` carries the COORDINATOR's clock
4796
+ * (set at assignment and re-bumped on every mutation). For a remote node,
4797
+ * coordinator-clock > worker-clock skew used to make an `updated_at <= occurredAt`
4798
+ * filter return nothing, stranding the finished task as `assigned` forever.
4799
+ *
4800
+ * We therefore NEVER filter completion-matching on the mutable `updated_at`:
4801
+ * 1. If `taskId` is given, match the exact `assigned` row by id (no time filter).
4802
+ * 2. Otherwise a session holds at most one `assigned` task — match it without a
4803
+ * time filter. If several exist (shouldn't normally), disambiguate by the
4804
+ * IMMUTABLE `dispatchTimestamp`: latest `dispatchTimestamp <= occurredAt`,
4805
+ * and if skew makes ALL of them later than `occurredAt`, fall back to the
4806
+ * most-recent `dispatchTimestamp` rather than returning null.
4807
+ */
4808
+ findAssignedBySession(meshId, sessionId, occurredAtIso, taskId) {
4493
4809
  this.ensureLegacyQueueMigrated(meshId);
4494
- 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`;
4495
- const args = occurredAtIso ? [meshId, sessionId, occurredAtIso] : [meshId, sessionId];
4496
- const row = this.db.prepare(sql).get(...args);
4497
- return row ? JSON.parse(row.payload) : null;
4810
+ if (taskId) {
4811
+ const row = this.db.prepare(
4812
+ `SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned' AND id = ? LIMIT 1`
4813
+ ).get(meshId, sessionId, taskId);
4814
+ if (row) return JSON.parse(row.payload);
4815
+ }
4816
+ const rows = this.db.prepare(
4817
+ `SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned'`
4818
+ ).all(meshId, sessionId);
4819
+ if (rows.length === 0) return null;
4820
+ const entries = rows.map((r) => {
4821
+ try {
4822
+ return JSON.parse(r.payload);
4823
+ } catch {
4824
+ return null;
4825
+ }
4826
+ }).filter((e) => e !== null);
4827
+ if (entries.length === 0) return null;
4828
+ if (entries.length === 1) return entries[0];
4829
+ const orderKey = (e) => e.dispatchTimestamp ?? e.updatedAt ?? "";
4830
+ const byDispatchDesc = [...entries].sort((a, b) => orderKey(b).localeCompare(orderKey(a)));
4831
+ if (occurredAtIso) {
4832
+ const atOrBefore = byDispatchDesc.find((e) => orderKey(e) <= occurredAtIso);
4833
+ if (atOrBefore) return atOrBefore;
4834
+ }
4835
+ return byDispatchDesc[0];
4498
4836
  }
4499
4837
  toRow(entry) {
4500
4838
  return {
@@ -5750,297 +6088,6 @@ var init_mesh_review_inbox = __esm({
5750
6088
  }
5751
6089
  });
5752
6090
 
5753
- // src/logging/async-batch-writer.ts
5754
- import * as fs3 from "fs";
5755
- var AsyncBatchWriter;
5756
- var init_async_batch_writer = __esm({
5757
- "src/logging/async-batch-writer.ts"() {
5758
- "use strict";
5759
- AsyncBatchWriter = class {
5760
- // Maps filePath -> string buffer
5761
- static buffers = /* @__PURE__ */ new Map();
5762
- static writePromises = /* @__PURE__ */ new Map();
5763
- static flushTimer = null;
5764
- /**
5765
- * Queues data to be written to a file asynchronously in a batch.
5766
- */
5767
- static write(filePath, data) {
5768
- let buf = this.buffers.get(filePath);
5769
- if (!buf) {
5770
- buf = [];
5771
- this.buffers.set(filePath, buf);
5772
- }
5773
- buf.push(data);
5774
- if (!this.flushTimer) {
5775
- this.flushTimer = setTimeout(() => {
5776
- this.flushTimer = null;
5777
- this.flushAll();
5778
- }, 50);
5779
- }
5780
- }
5781
- static async flushAll() {
5782
- const entries = Array.from(this.buffers.entries());
5783
- this.buffers.clear();
5784
- for (const [filePath, buffer] of entries) {
5785
- const dataToWrite = buffer.join("");
5786
- const doWrite = async () => {
5787
- try {
5788
- const prevPromise = this.writePromises.get(filePath);
5789
- if (prevPromise) await prevPromise;
5790
- await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
5791
- } catch {
5792
- }
5793
- };
5794
- const writePromise = doWrite();
5795
- this.writePromises.set(filePath, writePromise);
5796
- writePromise.finally(() => {
5797
- if (this.writePromises.get(filePath) === writePromise) {
5798
- this.writePromises.delete(filePath);
5799
- }
5800
- });
5801
- }
5802
- }
5803
- };
5804
- }
5805
- });
5806
-
5807
- // src/logging/logger.ts
5808
- var logger_exports = {};
5809
- __export(logger_exports, {
5810
- LOG: () => LOG,
5811
- LOG_DIR_PATH: () => LOG_DIR_PATH,
5812
- LOG_PATH: () => LOG_PATH,
5813
- daemonLog: () => daemonLog,
5814
- getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
5815
- getDaemonLogDir: () => getDaemonLogDir,
5816
- getLogBufferSize: () => getLogBufferSize,
5817
- getLogLevel: () => getLogLevel,
5818
- getLogPath: () => getLogPath,
5819
- getRecentLogs: () => getRecentLogs,
5820
- installGlobalInterceptor: () => installGlobalInterceptor,
5821
- setLogLevel: () => setLogLevel
5822
- });
5823
- import * as fs4 from "fs";
5824
- import * as path9 from "path";
5825
- import * as os3 from "os";
5826
- function setLogLevel(level) {
5827
- currentLevel = level;
5828
- daemonLog("Logger", `Log level set to: ${level}`, "info");
5829
- }
5830
- function getLogLevel() {
5831
- return currentLevel;
5832
- }
5833
- function getDateStr() {
5834
- return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5835
- }
5836
- function getDaemonLogDir() {
5837
- return LOG_DIR;
5838
- }
5839
- function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
5840
- return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
5841
- }
5842
- function checkDateRotation() {
5843
- const today = getDateStr();
5844
- if (today !== currentDate) {
5845
- currentDate = today;
5846
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
5847
- cleanOldLogs();
5848
- }
5849
- }
5850
- function cleanOldLogs() {
5851
- try {
5852
- const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
5853
- const cutoff = /* @__PURE__ */ new Date();
5854
- cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
5855
- const cutoffStr = cutoff.toISOString().slice(0, 10);
5856
- for (const file of files) {
5857
- const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
5858
- if (dateMatch && dateMatch[1] < cutoffStr) {
5859
- try {
5860
- fs4.unlinkSync(path9.join(LOG_DIR, file));
5861
- } catch {
5862
- }
5863
- }
5864
- }
5865
- } catch {
5866
- }
5867
- }
5868
- function rotateSizeIfNeeded() {
5869
- try {
5870
- const stat2 = fs4.statSync(currentLogFile);
5871
- if (stat2.size > MAX_LOG_SIZE) {
5872
- const backup = currentLogFile.replace(".log", ".1.log");
5873
- try {
5874
- fs4.unlinkSync(backup);
5875
- } catch {
5876
- }
5877
- fs4.renameSync(currentLogFile, backup);
5878
- }
5879
- } catch {
5880
- }
5881
- }
5882
- function writeToFile(line) {
5883
- try {
5884
- if (++writeCount % 1e3 === 0) {
5885
- checkDateRotation();
5886
- rotateSizeIfNeeded();
5887
- }
5888
- AsyncBatchWriter.write(currentLogFile, line + "\n");
5889
- } catch {
5890
- }
5891
- }
5892
- function getRecentLogs(count = 50, minLevel = "info") {
5893
- const minNum = LEVEL_NUM[minLevel];
5894
- const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
5895
- return filtered.slice(-count);
5896
- }
5897
- function getLogBufferSize() {
5898
- return ringBuffer.length;
5899
- }
5900
- function ts() {
5901
- return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
5902
- }
5903
- function fullTs() {
5904
- return (/* @__PURE__ */ new Date()).toISOString();
5905
- }
5906
- function daemonLog(category, msg, level = "info") {
5907
- const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
5908
- const label = LEVEL_LABEL[level];
5909
- const line = `[${ts()}] [${label}] [${category}] ${msg}`;
5910
- if (!shouldOutput) return;
5911
- writeToFile(line);
5912
- ringBuffer.push({ ts: Date.now(), level, category, message: msg });
5913
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5914
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5915
- }
5916
- origConsoleLog(line);
5917
- }
5918
- function installGlobalInterceptor() {
5919
- if (interceptorInstalled) return;
5920
- interceptorInstalled = true;
5921
- const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
5922
- const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
5923
- console.log = (...args) => {
5924
- origConsoleLog(...args);
5925
- try {
5926
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
5927
- const clean = stripAnsi4(msg);
5928
- if (isDaemonLogLine(clean)) return;
5929
- const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
5930
- writeToFile(line);
5931
- const catMatch = clean.match(/\[([^\]]+)\]/);
5932
- ringBuffer.push({
5933
- ts: Date.now(),
5934
- level: "info",
5935
- category: catMatch?.[1] || "System",
5936
- message: clean
5937
- });
5938
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5939
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5940
- }
5941
- } catch {
5942
- }
5943
- };
5944
- console.error = (...args) => {
5945
- origConsoleError(...args);
5946
- try {
5947
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
5948
- const clean = stripAnsi4(msg);
5949
- if (isDaemonLogLine(clean)) return;
5950
- const line = `[${fullTs()}] [ERROR] ${clean}`;
5951
- writeToFile(line);
5952
- ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
5953
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5954
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5955
- }
5956
- } catch {
5957
- }
5958
- };
5959
- console.warn = (...args) => {
5960
- origConsoleWarn(...args);
5961
- try {
5962
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
5963
- const clean = stripAnsi4(msg);
5964
- if (isDaemonLogLine(clean)) return;
5965
- const line = `[${fullTs()}] [WARN] ${clean}`;
5966
- writeToFile(line);
5967
- ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
5968
- if (ringBuffer.length > RING_BUFFER_SIZE) {
5969
- ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
5970
- }
5971
- } catch {
5972
- }
5973
- };
5974
- writeToFile(`
5975
- === ADHDev Daemon started at ${fullTs()} ===`);
5976
- writeToFile(`Log file: ${currentLogFile}`);
5977
- writeToFile(`Log level: ${currentLevel}`);
5978
- }
5979
- function getLogPath() {
5980
- return currentLogFile;
5981
- }
5982
- var 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;
5983
- var init_logger = __esm({
5984
- "src/logging/logger.ts"() {
5985
- "use strict";
5986
- init_async_batch_writer();
5987
- LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
5988
- LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
5989
- currentLevel = "info";
5990
- 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");
5991
- MAX_LOG_SIZE = 5 * 1024 * 1024;
5992
- MAX_LOG_DAYS = 7;
5993
- try {
5994
- fs4.mkdirSync(LOG_DIR, { recursive: true });
5995
- } catch {
5996
- }
5997
- currentDate = getDateStr();
5998
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
5999
- cleanOldLogs();
6000
- try {
6001
- const oldLog = path9.join(LOG_DIR, "daemon.log");
6002
- if (fs4.existsSync(oldLog)) {
6003
- const stat2 = fs4.statSync(oldLog);
6004
- const oldDate = stat2.mtime.toISOString().slice(0, 10);
6005
- fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
6006
- }
6007
- const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
6008
- if (fs4.existsSync(oldLogBackup)) {
6009
- fs4.unlinkSync(oldLogBackup);
6010
- }
6011
- } catch {
6012
- }
6013
- writeCount = 0;
6014
- RING_BUFFER_SIZE = 200;
6015
- ringBuffer = [];
6016
- origConsoleLog = console.log.bind(console);
6017
- origConsoleError = console.error.bind(console);
6018
- origConsoleWarn = console.warn.bind(console);
6019
- LOG = {
6020
- debug: (category, msg) => daemonLog(category, msg, "debug"),
6021
- info: (category, msg) => daemonLog(category, msg, "info"),
6022
- warn: (category, msg) => daemonLog(category, msg, "warn"),
6023
- error: (category, msg) => daemonLog(category, msg, "error"),
6024
- /**
6025
- * Create a scoped logger for a specific component.
6026
- * Category is baked in so callers only pass the message.
6027
- */
6028
- forComponent(category) {
6029
- return {
6030
- debug: (msg) => daemonLog(category, msg, "debug"),
6031
- info: (msg) => daemonLog(category, msg, "info"),
6032
- warn: (msg) => daemonLog(category, msg, "warn"),
6033
- error: (msg) => daemonLog(category, msg, "error"),
6034
- asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
6035
- };
6036
- }
6037
- };
6038
- interceptorInstalled = false;
6039
- LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
6040
- LOG_DIR_PATH = LOG_DIR;
6041
- }
6042
- });
6043
-
6044
6091
  // src/commands/mesh-coordinator.ts
6045
6092
  var mesh_coordinator_exports = {};
6046
6093
  __export(mesh_coordinator_exports, {
@@ -6442,6 +6489,59 @@ var init_mesh_coordinator = __esm({
6442
6489
  }
6443
6490
  });
6444
6491
 
6492
+ // src/cli-adapters/resolve-executable.ts
6493
+ import { execFileSync } from "child_process";
6494
+ import { existsSync as existsSync12 } from "fs";
6495
+ import * as path10 from "path";
6496
+ function resolveWin32GlobalBin(trimmed) {
6497
+ if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
6498
+ return null;
6499
+ }
6500
+ const extraDirs = [];
6501
+ if (process.env.APPDATA) extraDirs.push(path10.join(process.env.APPDATA, "npm"));
6502
+ try {
6503
+ extraDirs.push(path10.dirname(process.execPath));
6504
+ } catch {
6505
+ }
6506
+ for (const dir of extraDirs) {
6507
+ if (!dir) continue;
6508
+ for (const ext of WIN_EXEC_EXT) {
6509
+ const full = path10.join(dir, trimmed + ext);
6510
+ if (existsSync12(full)) return full;
6511
+ }
6512
+ }
6513
+ return null;
6514
+ }
6515
+ function resolveWin32Executable(command) {
6516
+ if (process.platform !== "win32") return command;
6517
+ const trimmed = (command || "").trim();
6518
+ if (!trimmed) return command;
6519
+ if (path10.isAbsolute(trimmed) && existsSync12(trimmed)) return trimmed;
6520
+ try {
6521
+ const out = execFileSync("where", [trimmed], {
6522
+ encoding: "utf8",
6523
+ windowsHide: true
6524
+ }).trim();
6525
+ if (out) {
6526
+ const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
6527
+ const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
6528
+ return direct || matches[0] || command;
6529
+ }
6530
+ } catch {
6531
+ }
6532
+ const globalBin = resolveWin32GlobalBin(trimmed);
6533
+ if (globalBin) return globalBin;
6534
+ return command;
6535
+ }
6536
+ var DIRECT_EXEC_EXT, WIN_EXEC_EXT;
6537
+ var init_resolve_executable = __esm({
6538
+ "src/cli-adapters/resolve-executable.ts"() {
6539
+ "use strict";
6540
+ DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
6541
+ WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
6542
+ }
6543
+ });
6544
+
6445
6545
  // src/mesh/mesh-fast-forward.ts
6446
6546
  async function fastForwardMeshNode(args) {
6447
6547
  const workspace = typeof args.workspace === "string" ? args.workspace.trim() : "";
@@ -7893,8 +7993,8 @@ var init_mesh_events_utils = __esm({
7893
7993
  });
7894
7994
 
7895
7995
  // src/mesh/mesh-events-pending.ts
7896
- import { appendFileSync as appendFileSync2, existsSync as existsSync13, readFileSync as readFileSync11, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
7897
- import { join as join14 } from "path";
7996
+ import { appendFileSync as appendFileSync2, existsSync as existsSync14, readFileSync as readFileSync11, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
7997
+ import { join as join15 } from "path";
7898
7998
  import { randomUUID as randomUUID7 } from "crypto";
7899
7999
  function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
7900
8000
  const raw = Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId != null ? [coordinatorDaemonId] : [];
@@ -7957,9 +8057,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
7957
8057
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
7958
8058
  if (coordinatorDaemonId) {
7959
8059
  const safeDaemon = coordinatorDaemonId.replace(/[^a-zA-Z0-9_-]/g, "_");
7960
- return join14(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
8060
+ return join15(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
7961
8061
  }
7962
- return join14(getLedgerDir(), `${safe}.pending-events.jsonl`);
8062
+ return join15(getLedgerDir(), `${safe}.pending-events.jsonl`);
7963
8063
  }
7964
8064
  function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
7965
8065
  if (!meshId) return [];
@@ -7968,7 +8068,7 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
7968
8068
  const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
7969
8069
  const events = [];
7970
8070
  for (const path42 of paths) {
7971
- if (!existsSync13(path42)) continue;
8071
+ if (!existsSync14(path42)) continue;
7972
8072
  try {
7973
8073
  const raw = readFileSync11(path42, "utf-8");
7974
8074
  const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
@@ -8045,7 +8145,7 @@ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
8045
8145
  }
8046
8146
  function trimPendingEventsIfNeeded(path42) {
8047
8147
  try {
8048
- if (!existsSync13(path42)) return;
8148
+ if (!existsSync14(path42)) return;
8049
8149
  if (statSync6(path42).size <= MAX_PENDING_EVENTS_BYTES) return;
8050
8150
  const lines = readFileSync11(path42, "utf-8").split("\n").filter(Boolean);
8051
8151
  if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
@@ -8147,7 +8247,7 @@ function selectiveDrainFile(path42, predicate) {
8147
8247
  unlinkSync2(tmpPath);
8148
8248
  } catch {
8149
8249
  try {
8150
- if (existsSync13(tmpPath) && !existsSync13(path42)) renameSync4(tmpPath, path42);
8250
+ if (existsSync14(tmpPath) && !existsSync14(path42)) renameSync4(tmpPath, path42);
8151
8251
  } catch {
8152
8252
  }
8153
8253
  return [];
@@ -8241,7 +8341,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
8241
8341
  }
8242
8342
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
8243
8343
  for (const path42 of paths) {
8244
- if (existsSync13(path42)) try {
8344
+ if (existsSync14(path42)) try {
8245
8345
  unlinkSync2(path42);
8246
8346
  } catch {
8247
8347
  }
@@ -8672,7 +8772,7 @@ var init_spawn_env = __esm({
8672
8772
 
8673
8773
  // src/cli-adapters/provider-cli-shared.ts
8674
8774
  import * as os5 from "os";
8675
- import * as path10 from "path";
8775
+ import * as path11 from "path";
8676
8776
  function stripAnsi(str) {
8677
8777
  return str.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
8678
8778
  }
@@ -8748,24 +8848,24 @@ function buildCliScreenSnapshot(text) {
8748
8848
  function findBinary(name) {
8749
8849
  const trimmed = String(name || "").trim();
8750
8850
  if (!trimmed) return trimmed;
8751
- const expanded = trimmed.startsWith("~") ? path10.join(os5.homedir(), trimmed.slice(1)) : trimmed;
8752
- if (path10.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
8753
- return path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
8851
+ const expanded = trimmed.startsWith("~") ? path11.join(os5.homedir(), trimmed.slice(1)) : trimmed;
8852
+ if (path11.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
8853
+ return path11.isAbsolute(expanded) ? expanded : path11.resolve(expanded);
8754
8854
  }
8755
8855
  const isWin = os5.platform() === "win32";
8756
- const paths = (process.env.PATH || "").split(path10.delimiter);
8856
+ const paths = (process.env.PATH || "").split(path11.delimiter);
8757
8857
  const extraDirs = [];
8758
8858
  if (isWin) {
8759
- if (process.env.APPDATA) extraDirs.push(path10.join(process.env.APPDATA, "npm"));
8859
+ if (process.env.APPDATA) extraDirs.push(path11.join(process.env.APPDATA, "npm"));
8760
8860
  try {
8761
- extraDirs.push(path10.dirname(process.execPath));
8861
+ extraDirs.push(path11.dirname(process.execPath));
8762
8862
  } catch {
8763
8863
  }
8764
8864
  } else {
8765
- extraDirs.push(path10.join(os5.homedir(), ".npm-global", "bin"));
8865
+ extraDirs.push(path11.join(os5.homedir(), ".npm-global", "bin"));
8766
8866
  extraDirs.push("/usr/local/bin", "/opt/homebrew/bin");
8767
8867
  try {
8768
- extraDirs.push(path10.dirname(process.execPath));
8868
+ extraDirs.push(path11.dirname(process.execPath));
8769
8869
  } catch {
8770
8870
  }
8771
8871
  }
@@ -8774,7 +8874,7 @@ function findBinary(name) {
8774
8874
  for (const p of searchDirs) {
8775
8875
  if (!p) continue;
8776
8876
  for (const ext of exes) {
8777
- const fullPath = path10.join(p, trimmed + ext);
8877
+ const fullPath = path11.join(p, trimmed + ext);
8778
8878
  try {
8779
8879
  const fs32 = __require("fs");
8780
8880
  if (fs32.existsSync(fullPath)) {
@@ -8790,7 +8890,7 @@ function findBinary(name) {
8790
8890
  return isWin ? `${trimmed}.cmd` : trimmed;
8791
8891
  }
8792
8892
  function isScriptBinary(binaryPath) {
8793
- if (!path10.isAbsolute(binaryPath)) return false;
8893
+ if (!path11.isAbsolute(binaryPath)) return false;
8794
8894
  try {
8795
8895
  const fs32 = __require("fs");
8796
8896
  const resolved = fs32.realpathSync(binaryPath);
@@ -8806,7 +8906,7 @@ function isScriptBinary(binaryPath) {
8806
8906
  }
8807
8907
  }
8808
8908
  function looksLikeMachOOrElf(filePath) {
8809
- if (!path10.isAbsolute(filePath)) return false;
8909
+ if (!path11.isAbsolute(filePath)) return false;
8810
8910
  try {
8811
8911
  const fs32 = __require("fs");
8812
8912
  const resolved = fs32.realpathSync(filePath);
@@ -9063,8 +9163,8 @@ var init_provider_cli_shared = __esm({
9063
9163
  // src/detection/cli-detector.ts
9064
9164
  import { exec } from "child_process";
9065
9165
  import * as os6 from "os";
9066
- import * as path11 from "path";
9067
- import { existsSync as existsSync14 } from "fs";
9166
+ import * as path12 from "path";
9167
+ import { existsSync as existsSync15 } from "fs";
9068
9168
  function parseVersion(raw) {
9069
9169
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
9070
9170
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
@@ -9076,19 +9176,19 @@ function shellQuote(value) {
9076
9176
  function expandHome(value) {
9077
9177
  const trimmed = value.trim();
9078
9178
  if (!trimmed.startsWith("~")) return trimmed;
9079
- return path11.join(os6.homedir(), trimmed.slice(1));
9179
+ return path12.join(os6.homedir(), trimmed.slice(1));
9080
9180
  }
9081
9181
  function isExplicitCommandPath(command) {
9082
9182
  const trimmed = command.trim();
9083
- return path11.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
9183
+ return path12.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
9084
9184
  }
9085
9185
  function resolveCommandPath(command) {
9086
9186
  const trimmed = command.trim();
9087
9187
  if (!trimmed) return null;
9088
9188
  if (isExplicitCommandPath(trimmed)) {
9089
9189
  const expanded = expandHome(trimmed);
9090
- const candidate = path11.isAbsolute(expanded) ? expanded : path11.resolve(expanded);
9091
- return existsSync14(candidate) ? candidate : null;
9190
+ const candidate = path12.isAbsolute(expanded) ? expanded : path12.resolve(expanded);
9191
+ return existsSync15(candidate) ? candidate : null;
9092
9192
  }
9093
9193
  return null;
9094
9194
  }
@@ -9098,7 +9198,7 @@ async function resolveDetectionPath(command, whichCmd) {
9098
9198
  const whichResult = await execAsync(`${whichCmd} ${shellQuote(command)}`);
9099
9199
  if (whichResult) return whichResult.split("\n")[0];
9100
9200
  const resolved = findBinary(command);
9101
- if (path11.isAbsolute(resolved) && existsSync14(resolved)) return resolved;
9201
+ if (path12.isAbsolute(resolved) && existsSync15(resolved)) return resolved;
9102
9202
  return null;
9103
9203
  }
9104
9204
  function execAsync(cmd, timeoutMs = 5e3) {
@@ -9443,7 +9543,7 @@ var init_mesh_unresolved_forward_outbox = __esm({
9443
9543
  });
9444
9544
 
9445
9545
  // src/mesh/mesh-events-coordinator.ts
9446
- import { existsSync as existsSync15 } from "fs";
9546
+ import { existsSync as existsSync16 } from "fs";
9447
9547
  function resolveCoordinatorDrainDaemonIds(components) {
9448
9548
  const ids = /* @__PURE__ */ new Set();
9449
9549
  const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
@@ -10231,7 +10331,7 @@ async function maybeAutoFastForwardIdleNode(components, args) {
10231
10331
  const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
10232
10332
  const workspace = readNonEmptyString2(node?.workspace);
10233
10333
  if (!workspace) return;
10234
- if (!existsSync15(workspace)) return;
10334
+ if (!existsSync16(workspace)) return;
10235
10335
  const policy = resolveAutoFastForwardPolicy(mesh);
10236
10336
  if (!policy.enabled) return;
10237
10337
  if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
@@ -10430,8 +10530,10 @@ function injectMeshSystemMessage(components, args) {
10430
10530
  }
10431
10531
  }
10432
10532
  function markSessionTerminal(sessionId, outcome, occurredAtMs) {
10533
+ const eventTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
10433
10534
  const task = updateSessionTaskStatus(args.meshId, sessionId, outcome, {
10434
- occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0
10535
+ occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
10536
+ taskId: eventTaskId
10435
10537
  });
10436
10538
  updateDirectDispatchStatus(args.meshId, sessionId, outcome);
10437
10539
  markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
@@ -12728,18 +12830,18 @@ __export(external_sources_exports, {
12728
12830
  });
12729
12831
  import * as fs9 from "fs";
12730
12832
  import * as os11 from "os";
12731
- import * as path17 from "path";
12833
+ import * as path18 from "path";
12732
12834
  function adhdevDir() {
12733
- return path17.join(os11.homedir(), ".adhdev");
12835
+ return path18.join(os11.homedir(), ".adhdev");
12734
12836
  }
12735
12837
  function externalRoot() {
12736
- return path17.join(adhdevDir(), "external");
12838
+ return path18.join(adhdevDir(), "external");
12737
12839
  }
12738
12840
  function sourcesFilePath() {
12739
- return path17.join(adhdevDir(), SOURCES_FILENAME);
12841
+ return path18.join(adhdevDir(), SOURCES_FILENAME);
12740
12842
  }
12741
12843
  function activeFilePath() {
12742
- return path17.join(adhdevDir(), ACTIVE_FILENAME);
12844
+ return path18.join(adhdevDir(), ACTIVE_FILENAME);
12743
12845
  }
12744
12846
  function ensureAdhdevDir() {
12745
12847
  const d = adhdevDir();
@@ -12806,7 +12908,7 @@ function inventoryExternalSources() {
12806
12908
  for (const sourceEntry of entries) {
12807
12909
  if (!sourceEntry.isDirectory()) continue;
12808
12910
  const sourceName = sourceEntry.name;
12809
- const sourceDir = path17.join(root, sourceName);
12911
+ const sourceDir = path18.join(root, sourceName);
12810
12912
  const providers = {};
12811
12913
  let categoryEntries;
12812
12914
  try {
@@ -12817,7 +12919,7 @@ function inventoryExternalSources() {
12817
12919
  for (const categoryEntry of categoryEntries) {
12818
12920
  if (!categoryEntry.isDirectory()) continue;
12819
12921
  const category = categoryEntry.name;
12820
- const categoryDir = path17.join(sourceDir, category);
12922
+ const categoryDir = path18.join(sourceDir, category);
12821
12923
  let typeEntries;
12822
12924
  try {
12823
12925
  typeEntries = fs9.readdirSync(categoryDir, { withFileTypes: true });
@@ -12827,9 +12929,9 @@ function inventoryExternalSources() {
12827
12929
  const types = [];
12828
12930
  for (const typeEntry of typeEntries) {
12829
12931
  if (!typeEntry.isDirectory()) continue;
12830
- const typeDir = path17.join(categoryDir, typeEntry.name);
12831
- const hasV1 = fs9.existsSync(path17.join(typeDir, "provider.v1.json"));
12832
- const hasV0 = fs9.existsSync(path17.join(typeDir, "provider.json"));
12932
+ const typeDir = path18.join(categoryDir, typeEntry.name);
12933
+ const hasV1 = fs9.existsSync(path18.join(typeDir, "provider.v1.json"));
12934
+ const hasV0 = fs9.existsSync(path18.join(typeDir, "provider.json"));
12833
12935
  if (hasV1 || hasV0) types.push(typeEntry.name);
12834
12936
  }
12835
12937
  if (types.length > 0) providers[category] = types;
@@ -13033,59 +13135,6 @@ var init_terminal_screen = __esm({
13033
13135
  }
13034
13136
  });
13035
13137
 
13036
- // src/cli-adapters/resolve-executable.ts
13037
- import { execFileSync } from "child_process";
13038
- import { existsSync as existsSync22 } from "fs";
13039
- import * as path18 from "path";
13040
- function resolveWin32GlobalBin(trimmed) {
13041
- if (path18.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
13042
- return null;
13043
- }
13044
- const extraDirs = [];
13045
- if (process.env.APPDATA) extraDirs.push(path18.join(process.env.APPDATA, "npm"));
13046
- try {
13047
- extraDirs.push(path18.dirname(process.execPath));
13048
- } catch {
13049
- }
13050
- for (const dir of extraDirs) {
13051
- if (!dir) continue;
13052
- for (const ext of WIN_EXEC_EXT) {
13053
- const full = path18.join(dir, trimmed + ext);
13054
- if (existsSync22(full)) return full;
13055
- }
13056
- }
13057
- return null;
13058
- }
13059
- function resolveWin32Executable(command) {
13060
- if (process.platform !== "win32") return command;
13061
- const trimmed = (command || "").trim();
13062
- if (!trimmed) return command;
13063
- if (path18.isAbsolute(trimmed) && existsSync22(trimmed)) return trimmed;
13064
- try {
13065
- const out = execFileSync("where", [trimmed], {
13066
- encoding: "utf8",
13067
- windowsHide: true
13068
- }).trim();
13069
- if (out) {
13070
- const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
13071
- const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path18.extname(m).toLowerCase()));
13072
- return direct || matches[0] || command;
13073
- }
13074
- } catch {
13075
- }
13076
- const globalBin = resolveWin32GlobalBin(trimmed);
13077
- if (globalBin) return globalBin;
13078
- return command;
13079
- }
13080
- var DIRECT_EXEC_EXT, WIN_EXEC_EXT;
13081
- var init_resolve_executable = __esm({
13082
- "src/cli-adapters/resolve-executable.ts"() {
13083
- "use strict";
13084
- DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
13085
- WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
13086
- }
13087
- });
13088
-
13089
13138
  // src/cli-adapters/pty-transport.ts
13090
13139
  var pty_transport_exports = {};
13091
13140
  __export(pty_transport_exports, {
@@ -19433,13 +19482,20 @@ var MESH_REFINE_CONFIG_SCHEMA = {
19433
19482
  function isMeshConfigRecord(value) {
19434
19483
  return !!value && typeof value === "object" && !Array.isArray(value);
19435
19484
  }
19485
+ var SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
19486
+ var SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
19487
+ var SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
19436
19488
  function tokenizeCommandString(command) {
19437
19489
  const trimmed = command.trim();
19438
19490
  if (!trimmed) return null;
19439
- if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
19491
+ if (SHELL_METACHAR_RE.test(trimmed)) return null;
19440
19492
  const tokens = trimmed.split(/\s+/).filter(Boolean);
19441
19493
  if (!tokens.length) return null;
19442
- if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
19494
+ const isWin32 = process.platform === "win32";
19495
+ for (let i = 0; i < tokens.length; i++) {
19496
+ const re = isWin32 && i === 0 ? SAFE_WIN32_EXEC_TOKEN_RE : SAFE_TOKEN_RE;
19497
+ if (!re.test(tokens[i])) return null;
19498
+ }
19443
19499
  return tokens;
19444
19500
  }
19445
19501
  function validateCategory(value) {
@@ -19649,8 +19705,9 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
19649
19705
  }
19650
19706
 
19651
19707
  // src/mesh/worktree-bootstrap-config.ts
19652
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
19653
- import { join as join13, resolve as pathResolve } from "path";
19708
+ init_resolve_executable();
19709
+ import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
19710
+ import { join as join14, resolve as pathResolve } from "path";
19654
19711
  import { execFile as execFile3 } from "child_process";
19655
19712
  import { createHash as createHash3 } from "crypto";
19656
19713
  import { promisify as promisify3 } from "util";
@@ -19741,8 +19798,8 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
19741
19798
  return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
19742
19799
  }
19743
19800
  for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
19744
- const configPath = join13(workspace, relative5);
19745
- if (!existsSync12(configPath)) continue;
19801
+ const configPath = join14(workspace, relative5);
19802
+ if (!existsSync13(configPath)) continue;
19746
19803
  try {
19747
19804
  const parsed = parseConfigText3(configPath, readFileSync10(configPath, "utf-8"));
19748
19805
  const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
@@ -19757,7 +19814,7 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
19757
19814
  function computeStaleInputsDigest(workspace, staleInputs) {
19758
19815
  const digest = {};
19759
19816
  for (const relative5 of staleInputs ?? []) {
19760
- const filePath = join13(workspace, relative5);
19817
+ const filePath = join14(workspace, relative5);
19761
19818
  try {
19762
19819
  digest[relative5] = createHash3("sha256").update(readFileSync10(filePath)).digest("hex");
19763
19820
  } catch {
@@ -19829,10 +19886,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
19829
19886
  staleInputs: loaded.config.staleInputs
19830
19887
  };
19831
19888
  const staleInputPaths = loaded.config.staleInputs ?? [];
19832
- const initiallyAbsent = staleInputPaths.filter((p) => !existsSync12(join13(workspace, p)));
19889
+ const initiallyAbsent = staleInputPaths.filter((p) => !existsSync13(join14(workspace, p)));
19833
19890
  for (const command of validation.commands) {
19834
19891
  if (initiallyAbsent.length > 0) {
19835
- const appearedNow = initiallyAbsent.filter((p) => existsSync12(join13(workspace, p)));
19892
+ const appearedNow = initiallyAbsent.filter((p) => existsSync13(join14(workspace, p)));
19836
19893
  if (appearedNow.length > 0) {
19837
19894
  state.status = "stale";
19838
19895
  state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -19843,8 +19900,9 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
19843
19900
  const cwd = command.cwd ? pathResolve(workspace, command.cwd) : workspace;
19844
19901
  const startedAt = Date.now();
19845
19902
  state.lastCommand = command.displayCommand;
19903
+ const resolvedCommand = resolveWin32Executable(command.command);
19846
19904
  try {
19847
- const result = await execFileAsync4(command.command, command.args, {
19905
+ const result = await execFileAsync4(resolvedCommand, command.args, {
19848
19906
  cwd,
19849
19907
  encoding: "utf8",
19850
19908
  timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
@@ -20080,8 +20138,8 @@ var P2pRelayFailureError = class extends Error {
20080
20138
 
20081
20139
  // src/config/state-store.ts
20082
20140
  init_config();
20083
- import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
20084
- import { join as join17 } from "path";
20141
+ import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
20142
+ import { join as join18 } from "path";
20085
20143
  var DEFAULT_STATE = {
20086
20144
  recentActivity: [],
20087
20145
  savedProviderSessions: [],
@@ -20094,7 +20152,7 @@ function isPlainObject2(value) {
20094
20152
  return !!value && typeof value === "object" && !Array.isArray(value);
20095
20153
  }
20096
20154
  function getStatePath() {
20097
- return join17(getConfigDir(), "state.json");
20155
+ return join18(getConfigDir(), "state.json");
20098
20156
  }
20099
20157
  function normalizeState(raw) {
20100
20158
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -20130,7 +20188,7 @@ function normalizeState(raw) {
20130
20188
  }
20131
20189
  function loadState() {
20132
20190
  const statePath = getStatePath();
20133
- if (!existsSync16(statePath)) {
20191
+ if (!existsSync17(statePath)) {
20134
20192
  return { ...DEFAULT_STATE };
20135
20193
  }
20136
20194
  try {
@@ -20152,19 +20210,19 @@ function resetState() {
20152
20210
  // src/detection/ide-detector.ts
20153
20211
  import { exec as exec2 } from "child_process";
20154
20212
  import { promisify as promisify4 } from "util";
20155
- import { existsSync as existsSync18, statSync as statSync8 } from "fs";
20213
+ import { existsSync as existsSync19, statSync as statSync8 } from "fs";
20156
20214
  import { platform as platform3, homedir as homedir8 } from "os";
20157
- import * as path13 from "path";
20215
+ import * as path14 from "path";
20158
20216
 
20159
20217
  // src/detection/win32-ide-version.ts
20160
20218
  import * as fs5 from "fs";
20161
- import * as path12 from "path";
20219
+ import * as path13 from "path";
20162
20220
  function manifestCandidates(exeDir) {
20163
20221
  return [
20164
- path12.join(exeDir, "resources", "app", "product.json"),
20165
- path12.join(exeDir, "resources", "app", "package.json"),
20222
+ path13.join(exeDir, "resources", "app", "product.json"),
20223
+ path13.join(exeDir, "resources", "app", "package.json"),
20166
20224
  // Some packagings keep product.json one level up.
20167
- path12.join(exeDir, "product.json")
20225
+ path13.join(exeDir, "product.json")
20168
20226
  ];
20169
20227
  }
20170
20228
  function parseVersionFromManifest(raw) {
@@ -20182,9 +20240,9 @@ function readWin32IdeVersionFromDisk(exePath) {
20182
20240
  if (!exePath) return null;
20183
20241
  let exeDir;
20184
20242
  try {
20185
- exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path12.dirname(exePath);
20243
+ exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path13.dirname(exePath);
20186
20244
  } catch {
20187
- exeDir = path12.dirname(exePath);
20245
+ exeDir = path13.dirname(exePath);
20188
20246
  }
20189
20247
  for (const candidate of manifestCandidates(exeDir)) {
20190
20248
  try {
@@ -20198,7 +20256,7 @@ function readWin32IdeVersionFromDisk(exePath) {
20198
20256
  }
20199
20257
  function isKnownWin32GuiExe(binPath, win32ProcessNames) {
20200
20258
  if (!binPath) return false;
20201
- const base = path12.win32.basename(binPath).toLowerCase();
20259
+ const base = path13.win32.basename(binPath).toLowerCase();
20202
20260
  if (!base.endsWith(".exe")) return false;
20203
20261
  for (const names of Object.values(win32ProcessNames)) {
20204
20262
  for (const name of names) {
@@ -20230,10 +20288,10 @@ function getMergedDefinitions() {
20230
20288
  function findCliCommand(command) {
20231
20289
  const trimmed = String(command || "").trim();
20232
20290
  if (!trimmed) return null;
20233
- if (path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
20234
- const candidate = trimmed.startsWith("~") ? path13.join(homedir8(), trimmed.slice(1)) : trimmed;
20235
- const resolved = path13.isAbsolute(candidate) ? candidate : path13.resolve(candidate);
20236
- return existsSync18(resolved) ? resolved : null;
20291
+ if (path14.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
20292
+ const candidate = trimmed.startsWith("~") ? path14.join(homedir8(), trimmed.slice(1)) : trimmed;
20293
+ const resolved = path14.isAbsolute(candidate) ? candidate : path14.resolve(candidate);
20294
+ return existsSync19(resolved) ? resolved : null;
20237
20295
  }
20238
20296
  const isWin = platform3() === "win32";
20239
20297
  const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
@@ -20241,9 +20299,9 @@ function findCliCommand(command) {
20241
20299
  for (const p of paths) {
20242
20300
  if (!p) continue;
20243
20301
  for (const ext of exes) {
20244
- const fullPath = path13.join(p, trimmed + ext);
20302
+ const fullPath = path14.join(p, trimmed + ext);
20245
20303
  try {
20246
- if (existsSync18(fullPath)) {
20304
+ if (existsSync19(fullPath)) {
20247
20305
  const stat2 = statSync8(fullPath);
20248
20306
  if (stat2.isFile() && (isWin || stat2.mode & 73)) {
20249
20307
  return fullPath;
@@ -20258,13 +20316,13 @@ function findCliCommand(command) {
20258
20316
  function checkPathExists(paths) {
20259
20317
  const home = homedir8();
20260
20318
  for (const p of paths) {
20261
- const normalized = p.startsWith("~") ? path13.join(home, p.slice(1)) : p;
20319
+ const normalized = p.startsWith("~") ? path14.join(home, p.slice(1)) : p;
20262
20320
  if (normalized.includes("*")) {
20263
20321
  const username = home.split(/[\\/]/).pop() || "";
20264
20322
  const resolved = normalized.replace("*", username);
20265
- if (existsSync18(resolved)) return resolved;
20323
+ if (existsSync19(resolved)) return resolved;
20266
20324
  } else {
20267
- if (existsSync18(normalized)) return normalized;
20325
+ if (existsSync19(normalized)) return normalized;
20268
20326
  }
20269
20327
  }
20270
20328
  return null;
@@ -20278,7 +20336,7 @@ async function detectIDEs(providerLoader) {
20278
20336
  let resolvedCli = cliPath;
20279
20337
  if (!resolvedCli && appPath && os30 === "darwin") {
20280
20338
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
20281
- if (existsSync18(bundledCli)) resolvedCli = bundledCli;
20339
+ if (existsSync19(bundledCli)) resolvedCli = bundledCli;
20282
20340
  }
20283
20341
  if (!resolvedCli && appPath && os30 === "win32") {
20284
20342
  const { dirname: dirname17 } = await import("path");
@@ -20291,7 +20349,7 @@ async function detectIDEs(providerLoader) {
20291
20349
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
20292
20350
  ];
20293
20351
  for (const c of candidates) {
20294
- if (existsSync18(c)) {
20352
+ if (existsSync19(c)) {
20295
20353
  resolvedCli = c;
20296
20354
  break;
20297
20355
  }
@@ -22150,9 +22208,9 @@ ${cleanBody}`;
22150
22208
  // src/config/chat-history.ts
22151
22209
  init_chat_message_normalization();
22152
22210
  import * as fs6 from "fs";
22153
- import * as path14 from "path";
22211
+ import * as path15 from "path";
22154
22212
  import * as os8 from "os";
22155
- var HISTORY_DIR = path14.join(os8.homedir(), ".adhdev", "history");
22213
+ var HISTORY_DIR = path15.join(os8.homedir(), ".adhdev", "history");
22156
22214
  var RETAIN_DAYS = 30;
22157
22215
  var SAVED_HISTORY_INDEX_VERSION = 1;
22158
22216
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -22338,7 +22396,7 @@ function extractSavedHistorySessionIdFromFile(file) {
22338
22396
  function buildSavedHistoryFileSignatureMap(dir, files) {
22339
22397
  return new Map(files.map((file) => {
22340
22398
  try {
22341
- const stat2 = fs6.statSync(path14.join(dir, file));
22399
+ const stat2 = fs6.statSync(path15.join(dir, file));
22342
22400
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
22343
22401
  } catch {
22344
22402
  return [file, `${file}:missing`];
@@ -22349,7 +22407,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
22349
22407
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
22350
22408
  }
22351
22409
  function getSavedHistoryIndexFilePath(dir) {
22352
- return path14.join(dir, SAVED_HISTORY_INDEX_FILE);
22410
+ return path15.join(dir, SAVED_HISTORY_INDEX_FILE);
22353
22411
  }
22354
22412
  function getSavedHistoryIndexLockPath(dir) {
22355
22413
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -22451,7 +22509,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
22451
22509
  }
22452
22510
  for (const file of Array.from(currentEntries.keys())) {
22453
22511
  if (incomingFiles.has(file)) continue;
22454
- if (!fs6.existsSync(path14.join(dir, file))) {
22512
+ if (!fs6.existsSync(path15.join(dir, file))) {
22455
22513
  currentEntries.delete(file);
22456
22514
  }
22457
22515
  }
@@ -22477,7 +22535,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
22477
22535
  const indexStat = fs6.statSync(getSavedHistoryIndexFilePath(dir));
22478
22536
  const files = listHistoryFiles(dir);
22479
22537
  for (const file of files) {
22480
- const stat2 = fs6.statSync(path14.join(dir, file));
22538
+ const stat2 = fs6.statSync(path15.join(dir, file));
22481
22539
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
22482
22540
  }
22483
22541
  return false;
@@ -22487,14 +22545,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
22487
22545
  }
22488
22546
  function buildSavedHistoryFileSignature(dir, file) {
22489
22547
  try {
22490
- const stat2 = fs6.statSync(path14.join(dir, file));
22548
+ const stat2 = fs6.statSync(path15.join(dir, file));
22491
22549
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
22492
22550
  } catch {
22493
22551
  return `${file}:missing`;
22494
22552
  }
22495
22553
  }
22496
22554
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
22497
- const filePath = path14.join(dir, file);
22555
+ const filePath = path15.join(dir, file);
22498
22556
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
22499
22557
  const currentEntry = entries.get(file) || null;
22500
22558
  const nextSummary = updater(currentEntry?.summary || null);
@@ -22567,7 +22625,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
22567
22625
  function computeSavedHistoryFileSummary(dir, file) {
22568
22626
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
22569
22627
  if (!historySessionId) return null;
22570
- const filePath = path14.join(dir, file);
22628
+ const filePath = path15.join(dir, file);
22571
22629
  const content = fs6.readFileSync(filePath, "utf-8");
22572
22630
  const lines = content.split("\n").filter(Boolean);
22573
22631
  let messageCount = 0;
@@ -22654,7 +22712,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
22654
22712
  const summaryBySessionId = /* @__PURE__ */ new Map();
22655
22713
  const nextPersistedEntries = /* @__PURE__ */ new Map();
22656
22714
  for (const file of files.slice().sort()) {
22657
- const filePath = path14.join(dir, file);
22715
+ const filePath = path15.join(dir, file);
22658
22716
  const signature = fileSignatures.get(file) || `${file}:missing`;
22659
22717
  const cached3 = savedHistoryFileSummaryCache.get(filePath);
22660
22718
  const persisted = persistedEntries.get(file);
@@ -22774,12 +22832,12 @@ var ChatHistoryWriter = class {
22774
22832
  });
22775
22833
  }
22776
22834
  if (newMessages.length === 0) return;
22777
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
22835
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
22778
22836
  fs6.mkdirSync(dir, { recursive: true });
22779
22837
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
22780
22838
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
22781
22839
  const fileName = `${filePrefix}${date}.jsonl`;
22782
- const filePath = path14.join(dir, fileName);
22840
+ const filePath = path15.join(dir, fileName);
22783
22841
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
22784
22842
  fs6.appendFileSync(filePath, lines, "utf-8");
22785
22843
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -22870,11 +22928,11 @@ var ChatHistoryWriter = class {
22870
22928
  const ws = String(workspace || "").trim();
22871
22929
  if (!id || !ws) return;
22872
22930
  try {
22873
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
22931
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
22874
22932
  fs6.mkdirSync(dir, { recursive: true });
22875
22933
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
22876
22934
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
22877
- const filePath = path14.join(dir, fileName);
22935
+ const filePath = path15.join(dir, fileName);
22878
22936
  const record = {
22879
22937
  ts: (/* @__PURE__ */ new Date()).toISOString(),
22880
22938
  receivedAt: Date.now(),
@@ -22920,14 +22978,14 @@ var ChatHistoryWriter = class {
22920
22978
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
22921
22979
  this.lastSeenCounts.delete(fromDedupKey);
22922
22980
  }
22923
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
22981
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
22924
22982
  if (!fs6.existsSync(dir)) return;
22925
22983
  const fromPrefix = `${this.sanitize(fromId)}_`;
22926
22984
  const toPrefix = `${this.sanitize(toId)}_`;
22927
22985
  const files = fs6.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
22928
22986
  for (const file of files) {
22929
- const sourcePath = path14.join(dir, file);
22930
- const targetPath = path14.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
22987
+ const sourcePath = path15.join(dir, file);
22988
+ const targetPath = path15.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
22931
22989
  const sourceLines = fs6.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
22932
22990
  const rewritten = sourceLines.map((line) => {
22933
22991
  try {
@@ -22961,13 +23019,13 @@ var ChatHistoryWriter = class {
22961
23019
  const sessionId = String(historySessionId || "").trim();
22962
23020
  if (!sessionId) return;
22963
23021
  try {
22964
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23022
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
22965
23023
  if (!fs6.existsSync(dir)) return;
22966
23024
  const prefix = `${this.sanitize(sessionId)}_`;
22967
23025
  const files = fs6.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
22968
23026
  const seen = /* @__PURE__ */ new Set();
22969
23027
  for (const file of files) {
22970
- const filePath = path14.join(dir, file);
23028
+ const filePath = path15.join(dir, file);
22971
23029
  const lines = fs6.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
22972
23030
  const next = [];
22973
23031
  for (const line of lines) {
@@ -23021,11 +23079,11 @@ var ChatHistoryWriter = class {
23021
23079
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
23022
23080
  const agentDirs = fs6.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
23023
23081
  for (const dir of agentDirs) {
23024
- const dirPath = path14.join(HISTORY_DIR, dir.name);
23082
+ const dirPath = path15.join(HISTORY_DIR, dir.name);
23025
23083
  const files = fs6.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
23026
23084
  let removedAny = false;
23027
23085
  for (const file of files) {
23028
- const filePath = path14.join(dirPath, file);
23086
+ const filePath = path15.join(dirPath, file);
23029
23087
  const stat2 = fs6.statSync(filePath);
23030
23088
  if (stat2.mtimeMs < cutoff) {
23031
23089
  fs6.unlinkSync(filePath);
@@ -23228,7 +23286,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
23228
23286
  const seen = /* @__PURE__ */ new Set();
23229
23287
  let readAllFiles = true;
23230
23288
  for (let f = 0; f < files.length; f++) {
23231
- const filePath = path14.join(dir, files[f]);
23289
+ const filePath = path15.join(dir, files[f]);
23232
23290
  const remaining = Math.max(0, needed - collected.length);
23233
23291
  const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
23234
23292
  const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
@@ -23261,7 +23319,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
23261
23319
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
23262
23320
  try {
23263
23321
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
23264
- const dir = path14.join(HISTORY_DIR, sanitized);
23322
+ const dir = path15.join(HISTORY_DIR, sanitized);
23265
23323
  if (!fs6.existsSync(dir)) return { messages: [], hasMore: false };
23266
23324
  const files = listHistoryFiles(dir, historySessionId);
23267
23325
  const bounded = isBoundedTailRequest(limit, offset, excludeRecentCount);
@@ -23284,7 +23342,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
23284
23342
  const allMessages = [];
23285
23343
  const seen = /* @__PURE__ */ new Set();
23286
23344
  for (const file of files) {
23287
- const filePath = path14.join(dir, file);
23345
+ const filePath = path15.join(dir, file);
23288
23346
  const content = fs6.readFileSync(filePath, "utf-8");
23289
23347
  const lines = content.trim().split("\n").filter(Boolean);
23290
23348
  for (let i = 0; i < lines.length; i++) {
@@ -23308,7 +23366,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
23308
23366
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
23309
23367
  try {
23310
23368
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
23311
- const dir = path14.join(HISTORY_DIR, sanitized);
23369
+ const dir = path15.join(HISTORY_DIR, sanitized);
23312
23370
  if (!fs6.existsSync(dir)) {
23313
23371
  savedHistorySessionCache.delete(sanitized);
23314
23372
  return { sessions: [], hasMore: false };
@@ -23369,11 +23427,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
23369
23427
  }
23370
23428
  function readExistingSessionStartRecord(agentType, historySessionId) {
23371
23429
  try {
23372
- const dir = path14.join(HISTORY_DIR, agentType);
23430
+ const dir = path15.join(HISTORY_DIR, agentType);
23373
23431
  if (!fs6.existsSync(dir)) return null;
23374
23432
  const files = listHistoryFiles(dir, historySessionId).sort();
23375
23433
  for (const file of files) {
23376
- const lines = fs6.readFileSync(path14.join(dir, file), "utf-8").split("\n").filter(Boolean);
23434
+ const lines = fs6.readFileSync(path15.join(dir, file), "utf-8").split("\n").filter(Boolean);
23377
23435
  for (const line of lines) {
23378
23436
  try {
23379
23437
  const parsed = JSON.parse(line);
@@ -23393,16 +23451,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
23393
23451
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
23394
23452
  if (records.length === 0) return false;
23395
23453
  try {
23396
- const dir = path14.join(HISTORY_DIR, agentType);
23454
+ const dir = path15.join(HISTORY_DIR, agentType);
23397
23455
  fs6.mkdirSync(dir, { recursive: true });
23398
23456
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
23399
23457
  for (const file of fs6.readdirSync(dir)) {
23400
23458
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
23401
- fs6.unlinkSync(path14.join(dir, file));
23459
+ fs6.unlinkSync(path15.join(dir, file));
23402
23460
  }
23403
23461
  }
23404
23462
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
23405
- const filePath = path14.join(dir, `${prefix}${targetDate}.jsonl`);
23463
+ const filePath = path15.join(dir, `${prefix}${targetDate}.jsonl`);
23406
23464
  fs6.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
23407
23465
  `, "utf-8");
23408
23466
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -26008,7 +26066,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
26008
26066
  init_contracts();
26009
26067
  import * as fs7 from "fs";
26010
26068
  import * as os9 from "os";
26011
- import * as path15 from "path";
26069
+ import * as path16 from "path";
26012
26070
  import { randomUUID as randomUUID11 } from "crypto";
26013
26071
  init_logger();
26014
26072
 
@@ -27058,7 +27116,7 @@ function readExactRuntimeMirrorMessages(args) {
27058
27116
  function normalizeComparableWorkspace(value) {
27059
27117
  const text = typeof value === "string" ? value.trim() : "";
27060
27118
  if (!text) return "";
27061
- return path15.resolve(text);
27119
+ return path16.resolve(text);
27062
27120
  }
27063
27121
  function isCurrentRuntimePtySafelyAttributed(args) {
27064
27122
  if (args.adapter.cliType !== "codex-cli") return false;
@@ -27543,7 +27601,7 @@ function buildDebugBundleText(bundle) {
27543
27601
  }
27544
27602
  function getChatDebugBundleDir() {
27545
27603
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
27546
- return override || path15.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
27604
+ return override || path16.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
27547
27605
  }
27548
27606
  function safeBundleIdSegment(value, fallback) {
27549
27607
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -27600,7 +27658,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
27600
27658
  const bundleId = createChatDebugBundleId(targetSessionId);
27601
27659
  const dir = getChatDebugBundleDir();
27602
27660
  fs7.mkdirSync(dir, { recursive: true });
27603
- const savedPath = path15.join(dir, `${bundleId}.json`);
27661
+ const savedPath = path16.join(dir, `${bundleId}.json`);
27604
27662
  const json = `${JSON.stringify(bundle, null, 2)}
27605
27663
  `;
27606
27664
  fs7.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -29164,7 +29222,7 @@ async function handleResolveAction(h, args) {
29164
29222
 
29165
29223
  // src/commands/cdp-commands.ts
29166
29224
  import * as fs8 from "fs";
29167
- import * as path16 from "path";
29225
+ import * as path17 from "path";
29168
29226
  import * as os10 from "os";
29169
29227
  var KEY_TO_VK = {
29170
29228
  Backspace: 8,
@@ -29421,25 +29479,25 @@ function resolveSafePath(requestedPath) {
29421
29479
  const inputPath = rawPath || ".";
29422
29480
  const home = os10.homedir();
29423
29481
  if (inputPath.startsWith("~")) {
29424
- return path16.resolve(path16.join(home, inputPath.slice(1)));
29482
+ return path17.resolve(path17.join(home, inputPath.slice(1)));
29425
29483
  }
29426
29484
  if (process.platform === "win32") {
29427
29485
  const normalized = normalizeWindowsRequestedPath(inputPath);
29428
- if (path16.win32.isAbsolute(normalized)) {
29429
- return path16.win32.normalize(normalized);
29486
+ if (path17.win32.isAbsolute(normalized)) {
29487
+ return path17.win32.normalize(normalized);
29430
29488
  }
29431
- return path16.win32.resolve(normalized);
29489
+ return path17.win32.resolve(normalized);
29432
29490
  }
29433
- if (path16.isAbsolute(inputPath)) {
29434
- return path16.normalize(inputPath);
29491
+ if (path17.isAbsolute(inputPath)) {
29492
+ return path17.normalize(inputPath);
29435
29493
  }
29436
- return path16.resolve(inputPath);
29494
+ return path17.resolve(inputPath);
29437
29495
  }
29438
29496
  function listDirectoryEntriesSafe(dirPath) {
29439
29497
  const entries = fs8.readdirSync(dirPath, { withFileTypes: true });
29440
29498
  const files = [];
29441
29499
  for (const entry of entries) {
29442
- const entryPath = path16.join(dirPath, entry.name);
29500
+ const entryPath = path17.join(dirPath, entry.name);
29443
29501
  try {
29444
29502
  if (entry.isDirectory()) {
29445
29503
  files.push({ name: entry.name, type: "directory" });
@@ -29493,7 +29551,7 @@ async function handleFileRead(h, args) {
29493
29551
  async function handleFileWrite(h, args) {
29494
29552
  try {
29495
29553
  const filePath = resolveSafePath(args?.path);
29496
- fs8.mkdirSync(path16.dirname(filePath), { recursive: true });
29554
+ fs8.mkdirSync(path17.dirname(filePath), { recursive: true });
29497
29555
  fs8.writeFileSync(filePath, args?.content || "", "utf-8");
29498
29556
  return { success: true, path: filePath };
29499
29557
  } catch (e) {
@@ -43306,6 +43364,7 @@ import { homedir as homedir26, hostname as osHostname } from "os";
43306
43364
  import { basename as pathBasename, join as pathJoin, resolve as pathResolve2 } from "path";
43307
43365
  import * as fs26 from "fs";
43308
43366
  import { execFileSync as execFileSync6 } from "child_process";
43367
+ init_resolve_executable();
43309
43368
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
43310
43369
  var CHANNEL_SERVER_URL = {
43311
43370
  stable: "https://api.adhf.dev",
@@ -44404,6 +44463,18 @@ function truncateValidationOutput(value) {
44404
44463
  return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
44405
44464
  [truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
44406
44465
  }
44466
+ function isSpawnResolutionError(error) {
44467
+ if (!error) return false;
44468
+ if (error.code === "ENOENT" && typeof error.syscall === "string" && error.syscall.startsWith("spawn")) return true;
44469
+ return error.code === "ENOENT" && (error.syscall === void 0 || String(error.syscall).startsWith("spawn"));
44470
+ }
44471
+ function describeSpawnError(error, command, spawnResolutionFailed) {
44472
+ if (spawnResolutionFailed) {
44473
+ 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." : "";
44474
+ return `Could not resolve executable "${command}" (spawn ENOENT).${hint}`;
44475
+ }
44476
+ return String(error?.message || error);
44477
+ }
44407
44478
  function recordMeshRefineStage(stages, stage, status, startedAt, details) {
44408
44479
  stages.push({
44409
44480
  stage,
@@ -45305,8 +45376,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45305
45376
  const startedAt = Date.now();
45306
45377
  const cwd = candidate.cwd ? pathResolve2(workspace, candidate.cwd) : workspace;
45307
45378
  const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
45379
+ const resolvedCommand = resolveWin32Executable(candidate.command);
45308
45380
  try {
45309
- const result = await execFileAsync4(candidate.command, candidate.args, {
45381
+ const result = await execFileAsync4(resolvedCommand, candidate.args, {
45310
45382
  cwd,
45311
45383
  encoding: "utf8",
45312
45384
  timeout,
@@ -45315,16 +45387,17 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45315
45387
  });
45316
45388
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
45317
45389
  } catch (error) {
45390
+ const spawnResolutionFailed = isSpawnResolutionError(error);
45318
45391
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
45319
45392
  exitCode: typeof error?.code === "number" ? error.code : null,
45320
45393
  signal: typeof error?.signal === "string" ? error.signal : null,
45321
45394
  timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
45322
- failureKind: "dependency_bootstrap_failed"
45395
+ ...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : { failureKind: "dependency_bootstrap_failed" }
45323
45396
  }));
45324
- summary.bootstrap = { stage: "failed", error: String(error?.message || error) };
45397
+ summary.bootstrap = { stage: "failed", error: describeSpawnError(error, candidate.command, spawnResolutionFailed) };
45325
45398
  summary.status = "failed";
45326
- summary.failureKind = "dependency_bootstrap_failed";
45327
- summary.failureCode = "dependency_bootstrap_failed";
45399
+ summary.failureKind = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
45400
+ summary.failureCode = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
45328
45401
  return summary;
45329
45402
  }
45330
45403
  }
@@ -45347,8 +45420,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45347
45420
  summary.failureCode = "missing_dependencies";
45348
45421
  return summary;
45349
45422
  }
45423
+ const resolvedCommand = resolveWin32Executable(candidate.command);
45350
45424
  try {
45351
- const result = await execFileAsync4(candidate.command, candidate.args, {
45425
+ const result = await execFileAsync4(resolvedCommand, candidate.args, {
45352
45426
  cwd,
45353
45427
  encoding: "utf8",
45354
45428
  timeout,
@@ -45357,16 +45431,21 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45357
45431
  });
45358
45432
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
45359
45433
  } catch (error) {
45434
+ const spawnResolutionFailed = isSpawnResolutionError(error);
45360
45435
  const stderr = truncateValidationOutput(error?.stderr || error?.message);
45361
- const missingDependencyFailure = /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
45436
+ const missingDependencyFailure = !spawnResolutionFailed && /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
45362
45437
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
45363
45438
  exitCode: typeof error?.code === "number" ? error.code : null,
45364
45439
  signal: typeof error?.signal === "string" ? error.signal : null,
45365
45440
  timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
45366
- ...missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
45441
+ ...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
45367
45442
  }));
45368
45443
  summary.status = "failed";
45369
- if (missingDependencyFailure) {
45444
+ if (spawnResolutionFailed) {
45445
+ summary.failureKind = "spawn_resolution_failed";
45446
+ summary.failureCode = "spawn_resolution_failed";
45447
+ summary.spawnResolutionError = describeSpawnError(error, candidate.command, true);
45448
+ } else if (missingDependencyFailure) {
45370
45449
  summary.failureKind = "missing_dependencies";
45371
45450
  summary.failureCode = "missing_dependencies";
45372
45451
  }
@@ -46627,7 +46706,7 @@ var DaemonCommandRouter = class {
46627
46706
  if (validationSummary.status === "failed") {
46628
46707
  const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
46629
46708
  const buildValidationFailedError = () => {
46630
- 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.";
46709
+ 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.";
46631
46710
  if (!firstFailedCmd) return base;
46632
46711
  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 : "";
46633
46712
  const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");