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

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 ? "e9e62c9770c0f4a419a90f5287125f3d3bb0fd95" : void 0) ?? "unknown";
320
+ const commitShort = readInjected(true ? "e9e62c97" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
321
+ const version = readInjected(true ? "0.9.82-rc.335" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
322
+ const builtAt = readInjected(true ? "2026-06-20T04:30:54.863Z" : 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, {
@@ -15079,7 +15128,7 @@ function appendBoundedText(current, chunk, maxChars) {
15079
15128
  if (current.length <= keepFromCurrent) return current + chunk;
15080
15129
  return current.slice(-keepFromCurrent) + chunk;
15081
15130
  }
15082
- var os14, import_session_host_core5, ProviderCliAdapter;
15131
+ var os14, import_session_host_core5, FORCE_SUBMIT_SETTLE_MS, FORCE_SUBMIT_MAX_WAIT_MS, FORCE_SUBMIT_POLL_MS, ProviderCliAdapter;
15083
15132
  var init_provider_cli_adapter = __esm({
15084
15133
  "src/cli-adapters/provider-cli-adapter.ts"() {
15085
15134
  "use strict";
@@ -15096,6 +15145,9 @@ var init_provider_cli_adapter = __esm({
15096
15145
  init_provider_cli_config();
15097
15146
  init_provider_cli_runtime();
15098
15147
  init_provider_cli_shared();
15148
+ FORCE_SUBMIT_SETTLE_MS = 150;
15149
+ FORCE_SUBMIT_MAX_WAIT_MS = 1500;
15150
+ FORCE_SUBMIT_POLL_MS = 50;
15099
15151
  ProviderCliAdapter = class _ProviderCliAdapter {
15100
15152
  constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
15101
15153
  this.extraArgs = extraArgs;
@@ -16024,9 +16076,23 @@ ${lastSnapshot}`;
16024
16076
  return;
16025
16077
  }
16026
16078
  LOG.info("CLI", `[${this.cliType}] force-sending prompt while status=${this.engine.currentStatus}`);
16027
- await this.writeToPty(content + this.sendKey);
16079
+ await this.writeToPty(content);
16080
+ await this.waitForForceSubmitSettle(content);
16081
+ await this.writeToPty(this.sendKey);
16028
16082
  this.onStatusChange?.();
16029
16083
  }
16084
+ async waitForForceSubmitSettle(content) {
16085
+ const startedAt = Date.now();
16086
+ const normalizedPromptSnippet = normalizePromptText(extractPromptRetrySnippet(content));
16087
+ await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_SETTLE_MS));
16088
+ if (!normalizedPromptSnippet) return;
16089
+ while (Date.now() - startedAt < FORCE_SUBMIT_MAX_WAIT_MS) {
16090
+ if (!this.ptyProcess) return;
16091
+ const screenText = this.terminalScreen.getText();
16092
+ if (promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
16093
+ await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_POLL_MS));
16094
+ }
16095
+ }
16030
16096
  enqueuePendingOutboundMessage(text, reason) {
16031
16097
  const content = String(text || "");
16032
16098
  const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
@@ -19793,13 +19859,20 @@ var MESH_REFINE_CONFIG_SCHEMA = {
19793
19859
  function isMeshConfigRecord(value) {
19794
19860
  return !!value && typeof value === "object" && !Array.isArray(value);
19795
19861
  }
19862
+ var SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
19863
+ var SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
19864
+ var SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
19796
19865
  function tokenizeCommandString(command) {
19797
19866
  const trimmed = command.trim();
19798
19867
  if (!trimmed) return null;
19799
- if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
19868
+ if (SHELL_METACHAR_RE.test(trimmed)) return null;
19800
19869
  const tokens = trimmed.split(/\s+/).filter(Boolean);
19801
19870
  if (!tokens.length) return null;
19802
- if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
19871
+ const isWin32 = process.platform === "win32";
19872
+ for (let i = 0; i < tokens.length; i++) {
19873
+ const re = isWin32 && i === 0 ? SAFE_WIN32_EXEC_TOKEN_RE : SAFE_TOKEN_RE;
19874
+ if (!re.test(tokens[i])) return null;
19875
+ }
19803
19876
  return tokens;
19804
19877
  }
19805
19878
  function validateCategory(value) {
@@ -20009,12 +20082,13 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
20009
20082
  }
20010
20083
 
20011
20084
  // src/mesh/worktree-bootstrap-config.ts
20012
- var import_fs8 = require("fs");
20085
+ var import_fs9 = require("fs");
20013
20086
  var import_path8 = require("path");
20014
20087
  var import_node_child_process3 = require("child_process");
20015
20088
  var import_node_crypto2 = require("crypto");
20016
20089
  var import_node_util3 = require("util");
20017
20090
  var yaml3 = __toESM(require("js-yaml"));
20091
+ init_resolve_executable();
20018
20092
  var MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
20019
20093
  ".adhdev/worktree_bootstrap.json",
20020
20094
  ".adhdev/worktree_bootstrap.yaml",
@@ -20102,9 +20176,9 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
20102
20176
  }
20103
20177
  for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
20104
20178
  const configPath = (0, import_path8.join)(workspace, relative5);
20105
- if (!(0, import_fs8.existsSync)(configPath)) continue;
20179
+ if (!(0, import_fs9.existsSync)(configPath)) continue;
20106
20180
  try {
20107
- const parsed = parseConfigText3(configPath, (0, import_fs8.readFileSync)(configPath, "utf-8"));
20181
+ const parsed = parseConfigText3(configPath, (0, import_fs9.readFileSync)(configPath, "utf-8"));
20108
20182
  const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
20109
20183
  if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
20110
20184
  return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
@@ -20119,7 +20193,7 @@ function computeStaleInputsDigest(workspace, staleInputs) {
20119
20193
  for (const relative5 of staleInputs ?? []) {
20120
20194
  const filePath = (0, import_path8.join)(workspace, relative5);
20121
20195
  try {
20122
- digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs8.readFileSync)(filePath)).digest("hex");
20196
+ digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs9.readFileSync)(filePath)).digest("hex");
20123
20197
  } catch {
20124
20198
  digest[relative5] = "absent";
20125
20199
  }
@@ -20189,10 +20263,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
20189
20263
  staleInputs: loaded.config.staleInputs
20190
20264
  };
20191
20265
  const staleInputPaths = loaded.config.staleInputs ?? [];
20192
- const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs8.existsSync)((0, import_path8.join)(workspace, p)));
20266
+ const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs9.existsSync)((0, import_path8.join)(workspace, p)));
20193
20267
  for (const command of validation.commands) {
20194
20268
  if (initiallyAbsent.length > 0) {
20195
- const appearedNow = initiallyAbsent.filter((p) => (0, import_fs8.existsSync)((0, import_path8.join)(workspace, p)));
20269
+ const appearedNow = initiallyAbsent.filter((p) => (0, import_fs9.existsSync)((0, import_path8.join)(workspace, p)));
20196
20270
  if (appearedNow.length > 0) {
20197
20271
  state.status = "stale";
20198
20272
  state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -20203,8 +20277,9 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
20203
20277
  const cwd = command.cwd ? (0, import_path8.resolve)(workspace, command.cwd) : workspace;
20204
20278
  const startedAt = Date.now();
20205
20279
  state.lastCommand = command.displayCommand;
20280
+ const resolvedCommand = resolveWin32Executable(command.command);
20206
20281
  try {
20207
- const result = await execFileAsync4(command.command, command.args, {
20282
+ const result = await execFileAsync4(resolvedCommand, command.args, {
20208
20283
  cwd,
20209
20284
  encoding: "utf8",
20210
20285
  timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
@@ -20439,7 +20514,7 @@ var P2pRelayFailureError = class extends Error {
20439
20514
  };
20440
20515
 
20441
20516
  // src/config/state-store.ts
20442
- var import_fs12 = require("fs");
20517
+ var import_fs13 = require("fs");
20443
20518
  var import_path10 = require("path");
20444
20519
  init_config();
20445
20520
  var DEFAULT_STATE = {
@@ -20490,11 +20565,11 @@ function normalizeState(raw) {
20490
20565
  }
20491
20566
  function loadState() {
20492
20567
  const statePath = getStatePath();
20493
- if (!(0, import_fs12.existsSync)(statePath)) {
20568
+ if (!(0, import_fs13.existsSync)(statePath)) {
20494
20569
  return { ...DEFAULT_STATE };
20495
20570
  }
20496
20571
  try {
20497
- const raw = (0, import_fs12.readFileSync)(statePath, "utf-8");
20572
+ const raw = (0, import_fs13.readFileSync)(statePath, "utf-8");
20498
20573
  return normalizeState(JSON.parse(raw));
20499
20574
  } catch {
20500
20575
  return { ...DEFAULT_STATE };
@@ -20503,28 +20578,28 @@ function loadState() {
20503
20578
  function saveState(state) {
20504
20579
  const statePath = getStatePath();
20505
20580
  const normalized = normalizeState(state);
20506
- (0, import_fs12.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
20581
+ (0, import_fs13.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
20507
20582
  }
20508
20583
  function resetState() {
20509
20584
  saveState({ ...DEFAULT_STATE });
20510
20585
  }
20511
20586
 
20512
20587
  // src/detection/ide-detector.ts
20513
- var import_child_process2 = require("child_process");
20588
+ var import_child_process3 = require("child_process");
20514
20589
  var import_util = require("util");
20515
- var import_fs13 = require("fs");
20590
+ var import_fs14 = require("fs");
20516
20591
  var import_os2 = require("os");
20517
- var path13 = __toESM(require("path"));
20592
+ var path14 = __toESM(require("path"));
20518
20593
 
20519
20594
  // src/detection/win32-ide-version.ts
20520
20595
  var fs5 = __toESM(require("fs"));
20521
- var path12 = __toESM(require("path"));
20596
+ var path13 = __toESM(require("path"));
20522
20597
  function manifestCandidates(exeDir) {
20523
20598
  return [
20524
- path12.join(exeDir, "resources", "app", "product.json"),
20525
- path12.join(exeDir, "resources", "app", "package.json"),
20599
+ path13.join(exeDir, "resources", "app", "product.json"),
20600
+ path13.join(exeDir, "resources", "app", "package.json"),
20526
20601
  // Some packagings keep product.json one level up.
20527
- path12.join(exeDir, "product.json")
20602
+ path13.join(exeDir, "product.json")
20528
20603
  ];
20529
20604
  }
20530
20605
  function parseVersionFromManifest(raw) {
@@ -20542,9 +20617,9 @@ function readWin32IdeVersionFromDisk(exePath) {
20542
20617
  if (!exePath) return null;
20543
20618
  let exeDir;
20544
20619
  try {
20545
- exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path12.dirname(exePath);
20620
+ exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path13.dirname(exePath);
20546
20621
  } catch {
20547
- exeDir = path12.dirname(exePath);
20622
+ exeDir = path13.dirname(exePath);
20548
20623
  }
20549
20624
  for (const candidate of manifestCandidates(exeDir)) {
20550
20625
  try {
@@ -20558,7 +20633,7 @@ function readWin32IdeVersionFromDisk(exePath) {
20558
20633
  }
20559
20634
  function isKnownWin32GuiExe(binPath, win32ProcessNames) {
20560
20635
  if (!binPath) return false;
20561
- const base = path12.win32.basename(binPath).toLowerCase();
20636
+ const base = path13.win32.basename(binPath).toLowerCase();
20562
20637
  if (!base.endsWith(".exe")) return false;
20563
20638
  for (const names of Object.values(win32ProcessNames)) {
20564
20639
  for (const name of names) {
@@ -20571,7 +20646,7 @@ function isKnownWin32GuiExe(binPath, win32ProcessNames) {
20571
20646
  }
20572
20647
 
20573
20648
  // src/detection/ide-detector.ts
20574
- var execAsync2 = (0, import_util.promisify)(import_child_process2.exec);
20649
+ var execAsync2 = (0, import_util.promisify)(import_child_process3.exec);
20575
20650
  var BUILTIN_IDE_DEFINITIONS = [];
20576
20651
  var registeredIDEs = /* @__PURE__ */ new Map();
20577
20652
  function registerIDEDefinition(def) {
@@ -20590,10 +20665,10 @@ function getMergedDefinitions() {
20590
20665
  function findCliCommand(command) {
20591
20666
  const trimmed = String(command || "").trim();
20592
20667
  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;
20668
+ if (path14.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
20669
+ const candidate = trimmed.startsWith("~") ? path14.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
20670
+ const resolved = path14.isAbsolute(candidate) ? candidate : path14.resolve(candidate);
20671
+ return (0, import_fs14.existsSync)(resolved) ? resolved : null;
20597
20672
  }
20598
20673
  const isWin = (0, import_os2.platform)() === "win32";
20599
20674
  const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
@@ -20601,10 +20676,10 @@ function findCliCommand(command) {
20601
20676
  for (const p of paths) {
20602
20677
  if (!p) continue;
20603
20678
  for (const ext of exes) {
20604
- const fullPath = path13.join(p, trimmed + ext);
20679
+ const fullPath = path14.join(p, trimmed + ext);
20605
20680
  try {
20606
- if ((0, import_fs13.existsSync)(fullPath)) {
20607
- const stat2 = (0, import_fs13.statSync)(fullPath);
20681
+ if ((0, import_fs14.existsSync)(fullPath)) {
20682
+ const stat2 = (0, import_fs14.statSync)(fullPath);
20608
20683
  if (stat2.isFile() && (isWin || stat2.mode & 73)) {
20609
20684
  return fullPath;
20610
20685
  }
@@ -20618,13 +20693,13 @@ function findCliCommand(command) {
20618
20693
  function checkPathExists(paths) {
20619
20694
  const home = (0, import_os2.homedir)();
20620
20695
  for (const p of paths) {
20621
- const normalized = p.startsWith("~") ? path13.join(home, p.slice(1)) : p;
20696
+ const normalized = p.startsWith("~") ? path14.join(home, p.slice(1)) : p;
20622
20697
  if (normalized.includes("*")) {
20623
20698
  const username = home.split(/[\\/]/).pop() || "";
20624
20699
  const resolved = normalized.replace("*", username);
20625
- if ((0, import_fs13.existsSync)(resolved)) return resolved;
20700
+ if ((0, import_fs14.existsSync)(resolved)) return resolved;
20626
20701
  } else {
20627
- if ((0, import_fs13.existsSync)(normalized)) return normalized;
20702
+ if ((0, import_fs14.existsSync)(normalized)) return normalized;
20628
20703
  }
20629
20704
  }
20630
20705
  return null;
@@ -20638,7 +20713,7 @@ async function detectIDEs(providerLoader) {
20638
20713
  let resolvedCli = cliPath;
20639
20714
  if (!resolvedCli && appPath && os30 === "darwin") {
20640
20715
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
20641
- if ((0, import_fs13.existsSync)(bundledCli)) resolvedCli = bundledCli;
20716
+ if ((0, import_fs14.existsSync)(bundledCli)) resolvedCli = bundledCli;
20642
20717
  }
20643
20718
  if (!resolvedCli && appPath && os30 === "win32") {
20644
20719
  const { dirname: dirname17 } = await import("path");
@@ -20651,7 +20726,7 @@ async function detectIDEs(providerLoader) {
20651
20726
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
20652
20727
  ];
20653
20728
  for (const c of candidates) {
20654
- if ((0, import_fs13.existsSync)(c)) {
20729
+ if ((0, import_fs14.existsSync)(c)) {
20655
20730
  resolvedCli = c;
20656
20731
  break;
20657
20732
  }
@@ -20678,9 +20753,9 @@ init_cli_detector();
20678
20753
 
20679
20754
  // src/system/host-memory.ts
20680
20755
  var os7 = __toESM(require("os"));
20681
- var import_child_process3 = require("child_process");
20756
+ var import_child_process4 = require("child_process");
20682
20757
  var import_util2 = require("util");
20683
- var execAsync3 = (0, import_util2.promisify)(import_child_process3.exec);
20758
+ var execAsync3 = (0, import_util2.promisify)(import_child_process4.exec);
20684
20759
  var cachedDarwinAvail = null;
20685
20760
  var darwinMemoryInterval = null;
20686
20761
  async function updateDarwinMemoryCache() {
@@ -22509,10 +22584,10 @@ ${cleanBody}`;
22509
22584
 
22510
22585
  // src/config/chat-history.ts
22511
22586
  var fs6 = __toESM(require("fs"));
22512
- var path14 = __toESM(require("path"));
22587
+ var path15 = __toESM(require("path"));
22513
22588
  var os8 = __toESM(require("os"));
22514
22589
  init_chat_message_normalization();
22515
- var HISTORY_DIR = path14.join(os8.homedir(), ".adhdev", "history");
22590
+ var HISTORY_DIR = path15.join(os8.homedir(), ".adhdev", "history");
22516
22591
  var RETAIN_DAYS = 30;
22517
22592
  var SAVED_HISTORY_INDEX_VERSION = 1;
22518
22593
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -22698,7 +22773,7 @@ function extractSavedHistorySessionIdFromFile(file) {
22698
22773
  function buildSavedHistoryFileSignatureMap(dir, files) {
22699
22774
  return new Map(files.map((file) => {
22700
22775
  try {
22701
- const stat2 = fs6.statSync(path14.join(dir, file));
22776
+ const stat2 = fs6.statSync(path15.join(dir, file));
22702
22777
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
22703
22778
  } catch {
22704
22779
  return [file, `${file}:missing`];
@@ -22709,7 +22784,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
22709
22784
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
22710
22785
  }
22711
22786
  function getSavedHistoryIndexFilePath(dir) {
22712
- return path14.join(dir, SAVED_HISTORY_INDEX_FILE);
22787
+ return path15.join(dir, SAVED_HISTORY_INDEX_FILE);
22713
22788
  }
22714
22789
  function getSavedHistoryIndexLockPath(dir) {
22715
22790
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -22811,7 +22886,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
22811
22886
  }
22812
22887
  for (const file of Array.from(currentEntries.keys())) {
22813
22888
  if (incomingFiles.has(file)) continue;
22814
- if (!fs6.existsSync(path14.join(dir, file))) {
22889
+ if (!fs6.existsSync(path15.join(dir, file))) {
22815
22890
  currentEntries.delete(file);
22816
22891
  }
22817
22892
  }
@@ -22837,7 +22912,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
22837
22912
  const indexStat = fs6.statSync(getSavedHistoryIndexFilePath(dir));
22838
22913
  const files = listHistoryFiles(dir);
22839
22914
  for (const file of files) {
22840
- const stat2 = fs6.statSync(path14.join(dir, file));
22915
+ const stat2 = fs6.statSync(path15.join(dir, file));
22841
22916
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
22842
22917
  }
22843
22918
  return false;
@@ -22847,14 +22922,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
22847
22922
  }
22848
22923
  function buildSavedHistoryFileSignature(dir, file) {
22849
22924
  try {
22850
- const stat2 = fs6.statSync(path14.join(dir, file));
22925
+ const stat2 = fs6.statSync(path15.join(dir, file));
22851
22926
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
22852
22927
  } catch {
22853
22928
  return `${file}:missing`;
22854
22929
  }
22855
22930
  }
22856
22931
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
22857
- const filePath = path14.join(dir, file);
22932
+ const filePath = path15.join(dir, file);
22858
22933
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
22859
22934
  const currentEntry = entries.get(file) || null;
22860
22935
  const nextSummary = updater(currentEntry?.summary || null);
@@ -22927,7 +23002,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
22927
23002
  function computeSavedHistoryFileSummary(dir, file) {
22928
23003
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
22929
23004
  if (!historySessionId) return null;
22930
- const filePath = path14.join(dir, file);
23005
+ const filePath = path15.join(dir, file);
22931
23006
  const content = fs6.readFileSync(filePath, "utf-8");
22932
23007
  const lines = content.split("\n").filter(Boolean);
22933
23008
  let messageCount = 0;
@@ -23014,7 +23089,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
23014
23089
  const summaryBySessionId = /* @__PURE__ */ new Map();
23015
23090
  const nextPersistedEntries = /* @__PURE__ */ new Map();
23016
23091
  for (const file of files.slice().sort()) {
23017
- const filePath = path14.join(dir, file);
23092
+ const filePath = path15.join(dir, file);
23018
23093
  const signature = fileSignatures.get(file) || `${file}:missing`;
23019
23094
  const cached3 = savedHistoryFileSummaryCache.get(filePath);
23020
23095
  const persisted = persistedEntries.get(file);
@@ -23134,12 +23209,12 @@ var ChatHistoryWriter = class {
23134
23209
  });
23135
23210
  }
23136
23211
  if (newMessages.length === 0) return;
23137
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23212
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23138
23213
  fs6.mkdirSync(dir, { recursive: true });
23139
23214
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
23140
23215
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
23141
23216
  const fileName = `${filePrefix}${date}.jsonl`;
23142
- const filePath = path14.join(dir, fileName);
23217
+ const filePath = path15.join(dir, fileName);
23143
23218
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
23144
23219
  fs6.appendFileSync(filePath, lines, "utf-8");
23145
23220
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -23230,11 +23305,11 @@ var ChatHistoryWriter = class {
23230
23305
  const ws = String(workspace || "").trim();
23231
23306
  if (!id || !ws) return;
23232
23307
  try {
23233
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23308
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23234
23309
  fs6.mkdirSync(dir, { recursive: true });
23235
23310
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
23236
23311
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
23237
- const filePath = path14.join(dir, fileName);
23312
+ const filePath = path15.join(dir, fileName);
23238
23313
  const record = {
23239
23314
  ts: (/* @__PURE__ */ new Date()).toISOString(),
23240
23315
  receivedAt: Date.now(),
@@ -23280,14 +23355,14 @@ var ChatHistoryWriter = class {
23280
23355
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
23281
23356
  this.lastSeenCounts.delete(fromDedupKey);
23282
23357
  }
23283
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23358
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23284
23359
  if (!fs6.existsSync(dir)) return;
23285
23360
  const fromPrefix = `${this.sanitize(fromId)}_`;
23286
23361
  const toPrefix = `${this.sanitize(toId)}_`;
23287
23362
  const files = fs6.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
23288
23363
  for (const file of files) {
23289
- const sourcePath = path14.join(dir, file);
23290
- const targetPath = path14.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
23364
+ const sourcePath = path15.join(dir, file);
23365
+ const targetPath = path15.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
23291
23366
  const sourceLines = fs6.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
23292
23367
  const rewritten = sourceLines.map((line) => {
23293
23368
  try {
@@ -23321,13 +23396,13 @@ var ChatHistoryWriter = class {
23321
23396
  const sessionId = String(historySessionId || "").trim();
23322
23397
  if (!sessionId) return;
23323
23398
  try {
23324
- const dir = path14.join(HISTORY_DIR, this.sanitize(agentType));
23399
+ const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
23325
23400
  if (!fs6.existsSync(dir)) return;
23326
23401
  const prefix = `${this.sanitize(sessionId)}_`;
23327
23402
  const files = fs6.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
23328
23403
  const seen = /* @__PURE__ */ new Set();
23329
23404
  for (const file of files) {
23330
- const filePath = path14.join(dir, file);
23405
+ const filePath = path15.join(dir, file);
23331
23406
  const lines = fs6.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
23332
23407
  const next = [];
23333
23408
  for (const line of lines) {
@@ -23381,11 +23456,11 @@ var ChatHistoryWriter = class {
23381
23456
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
23382
23457
  const agentDirs = fs6.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
23383
23458
  for (const dir of agentDirs) {
23384
- const dirPath = path14.join(HISTORY_DIR, dir.name);
23459
+ const dirPath = path15.join(HISTORY_DIR, dir.name);
23385
23460
  const files = fs6.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
23386
23461
  let removedAny = false;
23387
23462
  for (const file of files) {
23388
- const filePath = path14.join(dirPath, file);
23463
+ const filePath = path15.join(dirPath, file);
23389
23464
  const stat2 = fs6.statSync(filePath);
23390
23465
  if (stat2.mtimeMs < cutoff) {
23391
23466
  fs6.unlinkSync(filePath);
@@ -23588,7 +23663,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
23588
23663
  const seen = /* @__PURE__ */ new Set();
23589
23664
  let readAllFiles = true;
23590
23665
  for (let f = 0; f < files.length; f++) {
23591
- const filePath = path14.join(dir, files[f]);
23666
+ const filePath = path15.join(dir, files[f]);
23592
23667
  const remaining = Math.max(0, needed - collected.length);
23593
23668
  const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
23594
23669
  const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
@@ -23621,7 +23696,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
23621
23696
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
23622
23697
  try {
23623
23698
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
23624
- const dir = path14.join(HISTORY_DIR, sanitized);
23699
+ const dir = path15.join(HISTORY_DIR, sanitized);
23625
23700
  if (!fs6.existsSync(dir)) return { messages: [], hasMore: false };
23626
23701
  const files = listHistoryFiles(dir, historySessionId);
23627
23702
  const bounded = isBoundedTailRequest(limit, offset, excludeRecentCount);
@@ -23644,7 +23719,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
23644
23719
  const allMessages = [];
23645
23720
  const seen = /* @__PURE__ */ new Set();
23646
23721
  for (const file of files) {
23647
- const filePath = path14.join(dir, file);
23722
+ const filePath = path15.join(dir, file);
23648
23723
  const content = fs6.readFileSync(filePath, "utf-8");
23649
23724
  const lines = content.trim().split("\n").filter(Boolean);
23650
23725
  for (let i = 0; i < lines.length; i++) {
@@ -23668,7 +23743,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
23668
23743
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
23669
23744
  try {
23670
23745
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
23671
- const dir = path14.join(HISTORY_DIR, sanitized);
23746
+ const dir = path15.join(HISTORY_DIR, sanitized);
23672
23747
  if (!fs6.existsSync(dir)) {
23673
23748
  savedHistorySessionCache.delete(sanitized);
23674
23749
  return { sessions: [], hasMore: false };
@@ -23729,11 +23804,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
23729
23804
  }
23730
23805
  function readExistingSessionStartRecord(agentType, historySessionId) {
23731
23806
  try {
23732
- const dir = path14.join(HISTORY_DIR, agentType);
23807
+ const dir = path15.join(HISTORY_DIR, agentType);
23733
23808
  if (!fs6.existsSync(dir)) return null;
23734
23809
  const files = listHistoryFiles(dir, historySessionId).sort();
23735
23810
  for (const file of files) {
23736
- const lines = fs6.readFileSync(path14.join(dir, file), "utf-8").split("\n").filter(Boolean);
23811
+ const lines = fs6.readFileSync(path15.join(dir, file), "utf-8").split("\n").filter(Boolean);
23737
23812
  for (const line of lines) {
23738
23813
  try {
23739
23814
  const parsed = JSON.parse(line);
@@ -23753,16 +23828,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
23753
23828
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
23754
23829
  if (records.length === 0) return false;
23755
23830
  try {
23756
- const dir = path14.join(HISTORY_DIR, agentType);
23831
+ const dir = path15.join(HISTORY_DIR, agentType);
23757
23832
  fs6.mkdirSync(dir, { recursive: true });
23758
23833
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
23759
23834
  for (const file of fs6.readdirSync(dir)) {
23760
23835
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
23761
- fs6.unlinkSync(path14.join(dir, file));
23836
+ fs6.unlinkSync(path15.join(dir, file));
23762
23837
  }
23763
23838
  }
23764
23839
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
23765
- const filePath = path14.join(dir, `${prefix}${targetDate}.jsonl`);
23840
+ const filePath = path15.join(dir, `${prefix}${targetDate}.jsonl`);
23766
23841
  fs6.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
23767
23842
  `, "utf-8");
23768
23843
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -26367,7 +26442,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
26367
26442
  // src/commands/chat-commands.ts
26368
26443
  var fs7 = __toESM(require("fs"));
26369
26444
  var os9 = __toESM(require("os"));
26370
- var path15 = __toESM(require("path"));
26445
+ var path16 = __toESM(require("path"));
26371
26446
  var import_node_crypto3 = require("crypto");
26372
26447
  init_contracts();
26373
26448
  init_logger();
@@ -27418,7 +27493,7 @@ function readExactRuntimeMirrorMessages(args) {
27418
27493
  function normalizeComparableWorkspace(value) {
27419
27494
  const text = typeof value === "string" ? value.trim() : "";
27420
27495
  if (!text) return "";
27421
- return path15.resolve(text);
27496
+ return path16.resolve(text);
27422
27497
  }
27423
27498
  function isCurrentRuntimePtySafelyAttributed(args) {
27424
27499
  if (args.adapter.cliType !== "codex-cli") return false;
@@ -27903,7 +27978,7 @@ function buildDebugBundleText(bundle) {
27903
27978
  }
27904
27979
  function getChatDebugBundleDir() {
27905
27980
  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");
27981
+ return override || path16.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
27907
27982
  }
27908
27983
  function safeBundleIdSegment(value, fallback) {
27909
27984
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -27960,7 +28035,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
27960
28035
  const bundleId = createChatDebugBundleId(targetSessionId);
27961
28036
  const dir = getChatDebugBundleDir();
27962
28037
  fs7.mkdirSync(dir, { recursive: true });
27963
- const savedPath = path15.join(dir, `${bundleId}.json`);
28038
+ const savedPath = path16.join(dir, `${bundleId}.json`);
27964
28039
  const json = `${JSON.stringify(bundle, null, 2)}
27965
28040
  `;
27966
28041
  fs7.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -29524,7 +29599,7 @@ async function handleResolveAction(h, args) {
29524
29599
 
29525
29600
  // src/commands/cdp-commands.ts
29526
29601
  var fs8 = __toESM(require("fs"));
29527
- var path16 = __toESM(require("path"));
29602
+ var path17 = __toESM(require("path"));
29528
29603
  var os10 = __toESM(require("os"));
29529
29604
  var KEY_TO_VK = {
29530
29605
  Backspace: 8,
@@ -29781,25 +29856,25 @@ function resolveSafePath(requestedPath) {
29781
29856
  const inputPath = rawPath || ".";
29782
29857
  const home = os10.homedir();
29783
29858
  if (inputPath.startsWith("~")) {
29784
- return path16.resolve(path16.join(home, inputPath.slice(1)));
29859
+ return path17.resolve(path17.join(home, inputPath.slice(1)));
29785
29860
  }
29786
29861
  if (process.platform === "win32") {
29787
29862
  const normalized = normalizeWindowsRequestedPath(inputPath);
29788
- if (path16.win32.isAbsolute(normalized)) {
29789
- return path16.win32.normalize(normalized);
29863
+ if (path17.win32.isAbsolute(normalized)) {
29864
+ return path17.win32.normalize(normalized);
29790
29865
  }
29791
- return path16.win32.resolve(normalized);
29866
+ return path17.win32.resolve(normalized);
29792
29867
  }
29793
- if (path16.isAbsolute(inputPath)) {
29794
- return path16.normalize(inputPath);
29868
+ if (path17.isAbsolute(inputPath)) {
29869
+ return path17.normalize(inputPath);
29795
29870
  }
29796
- return path16.resolve(inputPath);
29871
+ return path17.resolve(inputPath);
29797
29872
  }
29798
29873
  function listDirectoryEntriesSafe(dirPath) {
29799
29874
  const entries = fs8.readdirSync(dirPath, { withFileTypes: true });
29800
29875
  const files = [];
29801
29876
  for (const entry of entries) {
29802
- const entryPath = path16.join(dirPath, entry.name);
29877
+ const entryPath = path17.join(dirPath, entry.name);
29803
29878
  try {
29804
29879
  if (entry.isDirectory()) {
29805
29880
  files.push({ name: entry.name, type: "directory" });
@@ -29853,7 +29928,7 @@ async function handleFileRead(h, args) {
29853
29928
  async function handleFileWrite(h, args) {
29854
29929
  try {
29855
29930
  const filePath = resolveSafePath(args?.path);
29856
- fs8.mkdirSync(path16.dirname(filePath), { recursive: true });
29931
+ fs8.mkdirSync(path17.dirname(filePath), { recursive: true });
29857
29932
  fs8.writeFileSync(filePath, args?.content || "", "utf-8");
29858
29933
  return { success: true, path: filePath };
29859
29934
  } catch (e) {
@@ -43661,6 +43736,7 @@ var import_os3 = require("os");
43661
43736
  var import_path12 = require("path");
43662
43737
  var fs26 = __toESM(require("fs"));
43663
43738
  var import_node_child_process6 = require("child_process");
43739
+ init_resolve_executable();
43664
43740
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
43665
43741
  var CHANNEL_SERVER_URL = {
43666
43742
  stable: "https://api.adhf.dev",
@@ -44759,6 +44835,18 @@ function truncateValidationOutput(value) {
44759
44835
  return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
44760
44836
  [truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
44761
44837
  }
44838
+ function isSpawnResolutionError(error) {
44839
+ if (!error) return false;
44840
+ if (error.code === "ENOENT" && typeof error.syscall === "string" && error.syscall.startsWith("spawn")) return true;
44841
+ return error.code === "ENOENT" && (error.syscall === void 0 || String(error.syscall).startsWith("spawn"));
44842
+ }
44843
+ function describeSpawnError(error, command, spawnResolutionFailed) {
44844
+ if (spawnResolutionFailed) {
44845
+ 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." : "";
44846
+ return `Could not resolve executable "${command}" (spawn ENOENT).${hint}`;
44847
+ }
44848
+ return String(error?.message || error);
44849
+ }
44762
44850
  function recordMeshRefineStage(stages, stage, status, startedAt, details) {
44763
44851
  stages.push({
44764
44852
  stage,
@@ -45660,8 +45748,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45660
45748
  const startedAt = Date.now();
45661
45749
  const cwd = candidate.cwd ? (0, import_path12.resolve)(workspace, candidate.cwd) : workspace;
45662
45750
  const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
45751
+ const resolvedCommand = resolveWin32Executable(candidate.command);
45663
45752
  try {
45664
- const result = await execFileAsync4(candidate.command, candidate.args, {
45753
+ const result = await execFileAsync4(resolvedCommand, candidate.args, {
45665
45754
  cwd,
45666
45755
  encoding: "utf8",
45667
45756
  timeout,
@@ -45670,16 +45759,17 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45670
45759
  });
45671
45760
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
45672
45761
  } catch (error) {
45762
+ const spawnResolutionFailed = isSpawnResolutionError(error);
45673
45763
  summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
45674
45764
  exitCode: typeof error?.code === "number" ? error.code : null,
45675
45765
  signal: typeof error?.signal === "string" ? error.signal : null,
45676
45766
  timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
45677
- failureKind: "dependency_bootstrap_failed"
45767
+ ...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : { failureKind: "dependency_bootstrap_failed" }
45678
45768
  }));
45679
- summary.bootstrap = { stage: "failed", error: String(error?.message || error) };
45769
+ summary.bootstrap = { stage: "failed", error: describeSpawnError(error, candidate.command, spawnResolutionFailed) };
45680
45770
  summary.status = "failed";
45681
- summary.failureKind = "dependency_bootstrap_failed";
45682
- summary.failureCode = "dependency_bootstrap_failed";
45771
+ summary.failureKind = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
45772
+ summary.failureCode = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
45683
45773
  return summary;
45684
45774
  }
45685
45775
  }
@@ -45702,8 +45792,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45702
45792
  summary.failureCode = "missing_dependencies";
45703
45793
  return summary;
45704
45794
  }
45795
+ const resolvedCommand = resolveWin32Executable(candidate.command);
45705
45796
  try {
45706
- const result = await execFileAsync4(candidate.command, candidate.args, {
45797
+ const result = await execFileAsync4(resolvedCommand, candidate.args, {
45707
45798
  cwd,
45708
45799
  encoding: "utf8",
45709
45800
  timeout,
@@ -45712,16 +45803,21 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
45712
45803
  });
45713
45804
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
45714
45805
  } catch (error) {
45806
+ const spawnResolutionFailed = isSpawnResolutionError(error);
45715
45807
  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);
45808
+ const missingDependencyFailure = !spawnResolutionFailed && /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
45717
45809
  summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
45718
45810
  exitCode: typeof error?.code === "number" ? error.code : null,
45719
45811
  signal: typeof error?.signal === "string" ? error.signal : null,
45720
45812
  timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
45721
- ...missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
45813
+ ...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
45722
45814
  }));
45723
45815
  summary.status = "failed";
45724
- if (missingDependencyFailure) {
45816
+ if (spawnResolutionFailed) {
45817
+ summary.failureKind = "spawn_resolution_failed";
45818
+ summary.failureCode = "spawn_resolution_failed";
45819
+ summary.spawnResolutionError = describeSpawnError(error, candidate.command, true);
45820
+ } else if (missingDependencyFailure) {
45725
45821
  summary.failureKind = "missing_dependencies";
45726
45822
  summary.failureCode = "missing_dependencies";
45727
45823
  }
@@ -46982,7 +47078,7 @@ var DaemonCommandRouter = class {
46982
47078
  if (validationSummary.status === "failed") {
46983
47079
  const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
46984
47080
  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.";
47081
+ 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
47082
  if (!firstFailedCmd) return base;
46987
47083
  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
47084
  const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");