@episoda/cli 0.2.187 → 0.2.189

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.
@@ -1937,7 +1937,7 @@ var require_git_executor = __commonJS({
1937
1937
  async executeCloneBare(command, options) {
1938
1938
  try {
1939
1939
  const fs35 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
1940
- const path35 = await Promise.resolve().then(() => __importStar(require("path")));
1940
+ const path37 = await Promise.resolve().then(() => __importStar(require("path")));
1941
1941
  try {
1942
1942
  await fs35.access(command.path);
1943
1943
  return {
@@ -1948,7 +1948,7 @@ var require_git_executor = __commonJS({
1948
1948
  };
1949
1949
  } catch {
1950
1950
  }
1951
- const parentDir = path35.dirname(command.path);
1951
+ const parentDir = path37.dirname(command.path);
1952
1952
  try {
1953
1953
  await fs35.mkdir(parentDir, { recursive: true });
1954
1954
  } catch {
@@ -1999,13 +1999,13 @@ var require_git_executor = __commonJS({
1999
1999
  async executeProjectInfo(cwd, options) {
2000
2000
  try {
2001
2001
  const fs35 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
2002
- const path35 = await Promise.resolve().then(() => __importStar(require("path")));
2002
+ const path37 = await Promise.resolve().then(() => __importStar(require("path")));
2003
2003
  let currentPath = cwd;
2004
2004
  let projectPath = cwd;
2005
2005
  let bareRepoPath;
2006
2006
  for (let i = 0; i < 10; i++) {
2007
- const bareDir = path35.join(currentPath, ".bare");
2008
- const episodaDir = path35.join(currentPath, ".episoda");
2007
+ const bareDir = path37.join(currentPath, ".bare");
2008
+ const episodaDir = path37.join(currentPath, ".episoda");
2009
2009
  try {
2010
2010
  await fs35.access(bareDir);
2011
2011
  await fs35.access(episodaDir);
@@ -2013,7 +2013,7 @@ var require_git_executor = __commonJS({
2013
2013
  bareRepoPath = bareDir;
2014
2014
  break;
2015
2015
  } catch {
2016
- const parentPath = path35.dirname(currentPath);
2016
+ const parentPath = path37.dirname(currentPath);
2017
2017
  if (parentPath === currentPath) {
2018
2018
  break;
2019
2019
  }
@@ -2236,7 +2236,7 @@ var require_websocket_client = __commonJS({
2236
2236
  clearTimeout(this.reconnectTimeout);
2237
2237
  this.reconnectTimeout = void 0;
2238
2238
  }
2239
- return new Promise((resolve7, reject) => {
2239
+ return new Promise((resolve8, reject) => {
2240
2240
  const connectionTimeout = setTimeout(() => {
2241
2241
  if (this.ws) {
2242
2242
  this.ws.terminate();
@@ -2267,7 +2267,7 @@ var require_websocket_client = __commonJS({
2267
2267
  daemonPid: this.daemonPid
2268
2268
  });
2269
2269
  this.startHeartbeat();
2270
- resolve7();
2270
+ resolve8();
2271
2271
  });
2272
2272
  this.ws.on("pong", () => {
2273
2273
  if (this.heartbeatTimeoutTimer) {
@@ -2411,13 +2411,13 @@ var require_websocket_client = __commonJS({
2411
2411
  console.warn("[EpisodaClient] Cannot send - WebSocket not connected");
2412
2412
  return false;
2413
2413
  }
2414
- return new Promise((resolve7) => {
2414
+ return new Promise((resolve8) => {
2415
2415
  this.ws.send(JSON.stringify(message), (error) => {
2416
2416
  if (error) {
2417
2417
  console.error("[EpisodaClient] Failed to send message:", error);
2418
- resolve7(false);
2418
+ resolve8(false);
2419
2419
  } else {
2420
- resolve7(true);
2420
+ resolve8(true);
2421
2421
  }
2422
2422
  });
2423
2423
  });
@@ -2725,29 +2725,29 @@ var require_auth = __commonJS({
2725
2725
  exports2.saveConfig = saveConfig4;
2726
2726
  exports2.validateToken = validateToken;
2727
2727
  var fs35 = __importStar(require("fs"));
2728
- var path35 = __importStar(require("path"));
2728
+ var path37 = __importStar(require("path"));
2729
2729
  var os16 = __importStar(require("os"));
2730
2730
  var child_process_1 = require("child_process");
2731
2731
  var DEFAULT_CONFIG_FILE = "config.json";
2732
2732
  var hasWarnedMissingProjectId = false;
2733
2733
  var hasWarnedMissingRequiredFields = false;
2734
2734
  function getConfigDir10() {
2735
- return process.env.EPISODA_CONFIG_DIR || path35.join(os16.homedir(), ".episoda");
2735
+ return process.env.EPISODA_CONFIG_DIR || path37.join(os16.homedir(), ".episoda");
2736
2736
  }
2737
2737
  function getConfigPath(configPath) {
2738
2738
  if (configPath) {
2739
2739
  return configPath;
2740
2740
  }
2741
- return path35.join(getConfigDir10(), DEFAULT_CONFIG_FILE);
2741
+ return path37.join(getConfigDir10(), DEFAULT_CONFIG_FILE);
2742
2742
  }
2743
2743
  function ensureConfigDir(configPath) {
2744
- const dir = path35.dirname(configPath);
2744
+ const dir = path37.dirname(configPath);
2745
2745
  const isNew = !fs35.existsSync(dir);
2746
2746
  if (isNew) {
2747
2747
  fs35.mkdirSync(dir, { recursive: true, mode: 448 });
2748
2748
  }
2749
2749
  if (process.platform === "darwin") {
2750
- const nosyncPath = path35.join(dir, ".nosync");
2750
+ const nosyncPath = path37.join(dir, ".nosync");
2751
2751
  if (isNew || !fs35.existsSync(nosyncPath)) {
2752
2752
  try {
2753
2753
  fs35.writeFileSync(nosyncPath, "", { mode: 384 });
@@ -3046,7 +3046,7 @@ var require_package = __commonJS({
3046
3046
  "package.json"(exports2, module2) {
3047
3047
  module2.exports = {
3048
3048
  name: "@episoda/cli",
3049
- version: "0.2.187",
3049
+ version: "0.2.189",
3050
3050
  description: "CLI tool for Episoda local development workflow orchestration",
3051
3051
  main: "dist/index.js",
3052
3052
  types: "dist/index.d.ts",
@@ -3362,10 +3362,10 @@ var IPCServer = class {
3362
3362
  this.server = net.createServer((socket) => {
3363
3363
  this.handleConnection(socket);
3364
3364
  });
3365
- return new Promise((resolve7, reject) => {
3365
+ return new Promise((resolve8, reject) => {
3366
3366
  this.server.listen(socketPath, () => {
3367
3367
  fs3.chmodSync(socketPath, 384);
3368
- resolve7();
3368
+ resolve8();
3369
3369
  });
3370
3370
  this.server.on("error", reject);
3371
3371
  });
@@ -3376,12 +3376,12 @@ var IPCServer = class {
3376
3376
  async stop() {
3377
3377
  if (!this.server) return;
3378
3378
  const socketPath = getSocketPath();
3379
- return new Promise((resolve7) => {
3379
+ return new Promise((resolve8) => {
3380
3380
  this.server.close(() => {
3381
3381
  if (fs3.existsSync(socketPath)) {
3382
3382
  fs3.unlinkSync(socketPath);
3383
3383
  }
3384
- resolve7();
3384
+ resolve8();
3385
3385
  });
3386
3386
  });
3387
3387
  }
@@ -3626,7 +3626,7 @@ function getDownloadUrl() {
3626
3626
  return platformUrls[arch4] || null;
3627
3627
  }
3628
3628
  async function downloadFile(url, destPath) {
3629
- return new Promise((resolve7, reject) => {
3629
+ return new Promise((resolve8, reject) => {
3630
3630
  const followRedirect = (currentUrl, redirectCount = 0) => {
3631
3631
  if (redirectCount > 5) {
3632
3632
  reject(new Error("Too many redirects"));
@@ -3656,7 +3656,7 @@ async function downloadFile(url, destPath) {
3656
3656
  response.pipe(file);
3657
3657
  file.on("finish", () => {
3658
3658
  file.close();
3659
- resolve7();
3659
+ resolve8();
3660
3660
  });
3661
3661
  file.on("error", (err) => {
3662
3662
  fs4.unlinkSync(destPath);
@@ -4070,10 +4070,10 @@ var TunnelManager = class extends import_events.EventEmitter {
4070
4070
  const isTracked = Array.from(this.tunnelStates.values()).some((s) => s.info.pid === pid);
4071
4071
  console.log(`[Tunnel] EP904: Found cloudflared PID ${pid} on port ${port} (tracked: ${isTracked})`);
4072
4072
  this.killByPid(pid, "SIGTERM");
4073
- await new Promise((resolve7) => setTimeout(resolve7, 500));
4073
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
4074
4074
  if (this.isProcessRunning(pid)) {
4075
4075
  this.killByPid(pid, "SIGKILL");
4076
- await new Promise((resolve7) => setTimeout(resolve7, 200));
4076
+ await new Promise((resolve8) => setTimeout(resolve8, 200));
4077
4077
  }
4078
4078
  killed.push(pid);
4079
4079
  }
@@ -4107,7 +4107,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4107
4107
  if (!this.tunnelStates.has(moduleUid)) {
4108
4108
  console.log(`[Tunnel] EP877: Found orphaned process PID ${pid} for ${moduleUid}, killing...`);
4109
4109
  this.killByPid(pid, "SIGTERM");
4110
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
4110
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
4111
4111
  if (this.isProcessRunning(pid)) {
4112
4112
  this.killByPid(pid, "SIGKILL");
4113
4113
  }
@@ -4122,7 +4122,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4122
4122
  if (!trackedPids.includes(pid) && !cleaned.includes(pid)) {
4123
4123
  console.log(`[Tunnel] EP877: Found untracked cloudflared process PID ${pid}, killing...`);
4124
4124
  this.killByPid(pid, "SIGTERM");
4125
- await new Promise((resolve7) => setTimeout(resolve7, 500));
4125
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
4126
4126
  if (this.isProcessRunning(pid)) {
4127
4127
  this.killByPid(pid, "SIGKILL");
4128
4128
  }
@@ -4212,7 +4212,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4212
4212
  return { success: false, error: `Failed to get cloudflared: ${errorMessage}` };
4213
4213
  }
4214
4214
  }
4215
- return new Promise((resolve7) => {
4215
+ return new Promise((resolve8) => {
4216
4216
  const tunnelInfo = {
4217
4217
  moduleUid,
4218
4218
  url: previewUrl || "",
@@ -4278,7 +4278,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4278
4278
  moduleUid,
4279
4279
  url: tunnelInfo.url
4280
4280
  });
4281
- resolve7({ success: true, url: tunnelInfo.url });
4281
+ resolve8({ success: true, url: tunnelInfo.url });
4282
4282
  }
4283
4283
  };
4284
4284
  process2.stderr?.on("data", (data) => {
@@ -4305,7 +4305,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4305
4305
  onStatusChange?.("error", errorMsg);
4306
4306
  this.emitEvent({ type: "error", moduleUid, error: errorMsg });
4307
4307
  }
4308
- resolve7({ success: false, error: errorMsg });
4308
+ resolve8({ success: false, error: errorMsg });
4309
4309
  } else if (wasConnected) {
4310
4310
  if (currentState && !currentState.intentionallyStopped) {
4311
4311
  console.log(`[Tunnel] EP948: Named tunnel ${moduleUid} crashed unexpectedly, attempting reconnect...`);
@@ -4336,7 +4336,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4336
4336
  this.emitEvent({ type: "error", moduleUid, error: error.message });
4337
4337
  }
4338
4338
  if (!connected) {
4339
- resolve7({ success: false, error: error.message });
4339
+ resolve8({ success: false, error: error.message });
4340
4340
  }
4341
4341
  });
4342
4342
  setTimeout(() => {
@@ -4359,7 +4359,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4359
4359
  onStatusChange?.("error", errorMsg);
4360
4360
  this.emitEvent({ type: "error", moduleUid, error: errorMsg });
4361
4361
  }
4362
- resolve7({ success: false, error: errorMsg });
4362
+ resolve8({ success: false, error: errorMsg });
4363
4363
  }
4364
4364
  }, TUNNEL_TIMEOUTS.NAMED_TUNNEL_CONNECT);
4365
4365
  });
@@ -4420,7 +4420,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4420
4420
  if (orphanPid && this.isProcessRunning(orphanPid)) {
4421
4421
  console.log(`[Tunnel] EP877: Killing orphaned process ${orphanPid} for ${moduleUid} before starting new tunnel`);
4422
4422
  this.killByPid(orphanPid, "SIGTERM");
4423
- await new Promise((resolve7) => setTimeout(resolve7, 500));
4423
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
4424
4424
  if (this.isProcessRunning(orphanPid)) {
4425
4425
  this.killByPid(orphanPid, "SIGKILL");
4426
4426
  }
@@ -4429,7 +4429,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4429
4429
  const killedOnPort = await this.killCloudflaredOnPort(port);
4430
4430
  if (killedOnPort.length > 0) {
4431
4431
  console.log(`[Tunnel] EP904: Pre-start port cleanup killed ${killedOnPort.length} process(es) on port ${port}`);
4432
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
4432
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
4433
4433
  }
4434
4434
  const cleanup = await this.cleanupOrphanedProcesses();
4435
4435
  if (cleanup.cleaned > 0) {
@@ -4469,7 +4469,7 @@ var TunnelManager = class extends import_events.EventEmitter {
4469
4469
  if (orphanPid && this.isProcessRunning(orphanPid)) {
4470
4470
  console.log(`[Tunnel] EP877: Stopping orphaned process ${orphanPid} for ${moduleUid} via PID file`);
4471
4471
  this.killByPid(orphanPid, "SIGTERM");
4472
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
4472
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
4473
4473
  if (this.isProcessRunning(orphanPid)) {
4474
4474
  this.killByPid(orphanPid, "SIGKILL");
4475
4475
  }
@@ -4485,16 +4485,16 @@ var TunnelManager = class extends import_events.EventEmitter {
4485
4485
  const tunnel = state.info;
4486
4486
  if (tunnel.process && !tunnel.process.killed) {
4487
4487
  tunnel.process.kill("SIGTERM");
4488
- await new Promise((resolve7) => {
4488
+ await new Promise((resolve8) => {
4489
4489
  const timeout = setTimeout(() => {
4490
4490
  if (tunnel.process && !tunnel.process.killed) {
4491
4491
  tunnel.process.kill("SIGKILL");
4492
4492
  }
4493
- resolve7();
4493
+ resolve8();
4494
4494
  }, 3e3);
4495
4495
  tunnel.process.once("exit", () => {
4496
4496
  clearTimeout(timeout);
4497
- resolve7();
4497
+ resolve8();
4498
4498
  });
4499
4499
  });
4500
4500
  }
@@ -4781,15 +4781,15 @@ async function writeToStdinWithBackpressure(process2, data, drainTimeoutMs, labe
4781
4781
  if (!stdin || stdin.destroyed) {
4782
4782
  throw new Error(`[${label}] stdin not available. session=${sessionId}`);
4783
4783
  }
4784
- await new Promise((resolve7, reject) => {
4784
+ await new Promise((resolve8, reject) => {
4785
4785
  const ok = stdin.write(data);
4786
4786
  if (ok) {
4787
- resolve7();
4787
+ resolve8();
4788
4788
  return;
4789
4789
  }
4790
4790
  const onDrain = () => {
4791
4791
  cleanup();
4792
- resolve7();
4792
+ resolve8();
4793
4793
  };
4794
4794
  const onError = (err) => {
4795
4795
  cleanup();
@@ -4810,18 +4810,18 @@ async function writeToStdinWithBackpressure(process2, data, drainTimeoutMs, labe
4810
4810
  });
4811
4811
  }
4812
4812
  function waitForProcessExit(process2, alive, timeoutMs) {
4813
- return new Promise((resolve7) => {
4813
+ return new Promise((resolve8) => {
4814
4814
  if (!process2 || !alive) {
4815
- resolve7(true);
4815
+ resolve8(true);
4816
4816
  return;
4817
4817
  }
4818
4818
  const onExit = () => {
4819
4819
  clearTimeout(timer);
4820
- resolve7(true);
4820
+ resolve8(true);
4821
4821
  };
4822
4822
  const timer = setTimeout(() => {
4823
4823
  process2.removeListener("exit", onExit);
4824
- resolve7(false);
4824
+ resolve8(false);
4825
4825
  }, timeoutMs);
4826
4826
  process2.once("exit", onExit);
4827
4827
  });
@@ -5817,10 +5817,10 @@ var CodexPersistentRuntime = class {
5817
5817
  }
5818
5818
  waitForThreadId(timeoutMs) {
5819
5819
  if (this._agentSessionId) return Promise.resolve(this._agentSessionId);
5820
- return new Promise((resolve7, reject) => {
5820
+ return new Promise((resolve8, reject) => {
5821
5821
  const onId = (id) => {
5822
5822
  clearTimeout(timer);
5823
- resolve7(id);
5823
+ resolve8(id);
5824
5824
  };
5825
5825
  const timer = setTimeout(() => {
5826
5826
  this.threadIdWaiters = this.threadIdWaiters.filter((w) => w !== onId);
@@ -5851,12 +5851,12 @@ var CodexPersistentRuntime = class {
5851
5851
  sendRequest(method, params, timeoutMs = INIT_TIMEOUT_MS) {
5852
5852
  const id = this.nextId++;
5853
5853
  const msg = { jsonrpc: "2.0", id, method, params };
5854
- return new Promise(async (resolve7, reject) => {
5854
+ return new Promise(async (resolve8, reject) => {
5855
5855
  const timeout = setTimeout(() => {
5856
5856
  this.pending.delete(id);
5857
5857
  reject(new Error(`JSON-RPC timeout: ${method}`));
5858
5858
  }, timeoutMs);
5859
- this.pending.set(id, { resolve: resolve7, reject, timeout });
5859
+ this.pending.set(id, { resolve: resolve8, reject, timeout });
5860
5860
  try {
5861
5861
  await this.writeToStdin(JSON.stringify(msg) + "\n");
5862
5862
  } catch (err) {
@@ -6006,11 +6006,11 @@ var UnifiedAgentRuntime = class {
6006
6006
  if (!this.currentTurn && this.impl.turnState === "idle") {
6007
6007
  return this.dispatchTurn(message, callbacks);
6008
6008
  }
6009
- return new Promise((resolve7, reject) => {
6009
+ return new Promise((resolve8, reject) => {
6010
6010
  this.queuedTurns.push({
6011
6011
  message,
6012
6012
  callbacks,
6013
- resolve: resolve7,
6013
+ resolve: resolve8,
6014
6014
  reject
6015
6015
  });
6016
6016
  });
@@ -7523,13 +7523,13 @@ async function getChildProcessRssMb(pid) {
7523
7523
  if (!pid || pid <= 0) return null;
7524
7524
  try {
7525
7525
  if (typeof import_child_process9.execFile !== "function") return null;
7526
- const stdout = await new Promise((resolve7, reject) => {
7526
+ const stdout = await new Promise((resolve8, reject) => {
7527
7527
  (0, import_child_process9.execFile)("ps", ["-o", "rss=", "-p", String(pid)], { timeout: 1e3 }, (err, out) => {
7528
7528
  if (err) {
7529
7529
  reject(err);
7530
7530
  return;
7531
7531
  }
7532
- resolve7(String(out));
7532
+ resolve8(String(out));
7533
7533
  });
7534
7534
  });
7535
7535
  const kb = Number(String(stdout).trim());
@@ -7632,8 +7632,8 @@ var AgentControlPlane = class {
7632
7632
  async withConfigLock(fn) {
7633
7633
  const previousLock = this.configWriteLock;
7634
7634
  let releaseLock;
7635
- this.configWriteLock = new Promise((resolve7) => {
7636
- releaseLock = resolve7;
7635
+ this.configWriteLock = new Promise((resolve8) => {
7636
+ releaseLock = resolve8;
7637
7637
  });
7638
7638
  try {
7639
7639
  await previousLock;
@@ -8862,7 +8862,7 @@ var WorktreeManager = class _WorktreeManager {
8862
8862
  const lockContent = fs14.readFileSync(lockPath, "utf-8").trim();
8863
8863
  const lockPid = parseInt(lockContent, 10);
8864
8864
  if (!isNaN(lockPid) && this.isProcessRunning(lockPid)) {
8865
- await new Promise((resolve7) => setTimeout(resolve7, retryInterval));
8865
+ await new Promise((resolve8) => setTimeout(resolve8, retryInterval));
8866
8866
  continue;
8867
8867
  }
8868
8868
  } catch {
@@ -8876,7 +8876,7 @@ var WorktreeManager = class _WorktreeManager {
8876
8876
  } catch {
8877
8877
  continue;
8878
8878
  }
8879
- await new Promise((resolve7) => setTimeout(resolve7, retryInterval));
8879
+ await new Promise((resolve8) => setTimeout(resolve8, retryInterval));
8880
8880
  continue;
8881
8881
  }
8882
8882
  throw err;
@@ -9666,6 +9666,7 @@ function getInstallCommand(cwd) {
9666
9666
  var fs34 = __toESM(require("fs"));
9667
9667
  var http2 = __toESM(require("http"));
9668
9668
  var os15 = __toESM(require("os"));
9669
+ var path36 = __toESM(require("path"));
9669
9670
  var import_child_process19 = require("child_process");
9670
9671
 
9671
9672
  // src/daemon/ipc-router.ts
@@ -10400,7 +10401,7 @@ async function handleExec(command, projectPath) {
10400
10401
  env = {}
10401
10402
  } = command;
10402
10403
  const effectiveTimeout = Math.min(Math.max(timeout, 1e3), MAX_TIMEOUT);
10403
- return new Promise((resolve7) => {
10404
+ return new Promise((resolve8) => {
10404
10405
  let stdout = "";
10405
10406
  let stderr = "";
10406
10407
  let timedOut = false;
@@ -10408,7 +10409,7 @@ async function handleExec(command, projectPath) {
10408
10409
  const done = (result) => {
10409
10410
  if (resolved) return;
10410
10411
  resolved = true;
10411
- resolve7(result);
10412
+ resolve8(result);
10412
10413
  };
10413
10414
  try {
10414
10415
  const proc = (0, import_child_process11.spawn)(cmd, {
@@ -10512,18 +10513,18 @@ var import_core12 = __toESM(require_dist());
10512
10513
  // src/utils/port-check.ts
10513
10514
  var net2 = __toESM(require("net"));
10514
10515
  async function isPortInUse(port) {
10515
- return new Promise((resolve7) => {
10516
+ return new Promise((resolve8) => {
10516
10517
  const server = net2.createServer();
10517
10518
  server.once("error", (err) => {
10518
10519
  if (err.code === "EADDRINUSE") {
10519
- resolve7(true);
10520
+ resolve8(true);
10520
10521
  } else {
10521
- resolve7(false);
10522
+ resolve8(false);
10522
10523
  }
10523
10524
  });
10524
10525
  server.once("listening", () => {
10525
10526
  server.close();
10526
- resolve7(false);
10527
+ resolve8(false);
10527
10528
  });
10528
10529
  server.listen(port);
10529
10530
  });
@@ -10926,7 +10927,7 @@ var DevServerRegistry = class {
10926
10927
  return killed;
10927
10928
  }
10928
10929
  wait(ms) {
10929
- return new Promise((resolve7) => setTimeout(resolve7, ms));
10930
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
10930
10931
  }
10931
10932
  killWsServerOnPort(wsPort, worktreePath) {
10932
10933
  const killed = [];
@@ -11500,7 +11501,7 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11500
11501
  return Math.min(delay, DEV_SERVER_CONSTANTS.MAX_RESTART_DELAY_MS);
11501
11502
  }
11502
11503
  async checkHealth(port) {
11503
- return new Promise((resolve7) => {
11504
+ return new Promise((resolve8) => {
11504
11505
  const req = http.request(
11505
11506
  {
11506
11507
  hostname: "localhost",
@@ -11509,18 +11510,18 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11509
11510
  method: "HEAD",
11510
11511
  timeout: DEV_SERVER_CONSTANTS.HEALTH_CHECK_TIMEOUT_MS
11511
11512
  },
11512
- () => resolve7(true)
11513
+ () => resolve8(true)
11513
11514
  );
11514
- req.on("error", () => resolve7(false));
11515
+ req.on("error", () => resolve8(false));
11515
11516
  req.on("timeout", () => {
11516
11517
  req.destroy();
11517
- resolve7(false);
11518
+ resolve8(false);
11518
11519
  });
11519
11520
  req.end();
11520
11521
  });
11521
11522
  }
11522
11523
  async checkWsHealth(wsPort) {
11523
- return new Promise((resolve7) => {
11524
+ return new Promise((resolve8) => {
11524
11525
  const req = http.request(
11525
11526
  {
11526
11527
  hostname: "127.0.0.1",
@@ -11530,14 +11531,14 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11530
11531
  timeout: DEV_SERVER_CONSTANTS.HEALTH_CHECK_TIMEOUT_MS
11531
11532
  },
11532
11533
  (res) => {
11533
- resolve7(res.statusCode === 200);
11534
+ resolve8(res.statusCode === 200);
11534
11535
  res.resume();
11535
11536
  }
11536
11537
  );
11537
- req.on("error", () => resolve7(false));
11538
+ req.on("error", () => resolve8(false));
11538
11539
  req.on("timeout", () => {
11539
11540
  req.destroy();
11540
- resolve7(false);
11541
+ resolve8(false);
11541
11542
  });
11542
11543
  req.end();
11543
11544
  });
@@ -11565,7 +11566,7 @@ var DevServerRunner = class extends import_events2.EventEmitter {
11565
11566
  return false;
11566
11567
  }
11567
11568
  wait(ms) {
11568
- return new Promise((resolve7) => setTimeout(resolve7, ms));
11569
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
11569
11570
  }
11570
11571
  getLogsDir() {
11571
11572
  const logsDir = path25.join((0, import_core12.getConfigDir)(), "logs");
@@ -11764,7 +11765,7 @@ var PreviewManager = class extends import_events3.EventEmitter {
11764
11765
  for (let attempt = 1; attempt <= MAX_TUNNEL_RETRIES; attempt++) {
11765
11766
  if (attempt > 1) {
11766
11767
  console.log(`[PreviewManager] Retrying tunnel for ${moduleUid} (attempt ${attempt}/${MAX_TUNNEL_RETRIES})...`);
11767
- await new Promise((resolve7) => setTimeout(resolve7, 2e3));
11768
+ await new Promise((resolve8) => setTimeout(resolve8, 2e3));
11768
11769
  }
11769
11770
  tunnelResult = await this.tunnel.startTunnel({
11770
11771
  moduleUid,
@@ -11896,7 +11897,7 @@ var PreviewManager = class extends import_events3.EventEmitter {
11896
11897
  }
11897
11898
  console.log(`[PreviewManager] Restarting preview for ${moduleUid}`);
11898
11899
  await this.stopPreview(moduleUid);
11899
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
11900
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
11900
11901
  return this.startPreview({
11901
11902
  moduleUid,
11902
11903
  worktreePath: state.worktreePath,
@@ -13044,7 +13045,7 @@ async function killProcessOnPort(port) {
13044
13045
  } catch {
13045
13046
  }
13046
13047
  }
13047
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
13048
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
13048
13049
  for (const pid of pids) {
13049
13050
  try {
13050
13051
  (0, import_child_process15.execSync)(`kill -0 ${pid} 2>/dev/null`, { encoding: "utf8" });
@@ -13053,7 +13054,7 @@ async function killProcessOnPort(port) {
13053
13054
  } catch {
13054
13055
  }
13055
13056
  }
13056
- await new Promise((resolve7) => setTimeout(resolve7, 500));
13057
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
13057
13058
  const stillInUse = await isPortInUse(port);
13058
13059
  if (stillInUse) {
13059
13060
  console.error(`[DevServer] EP929: Port ${port} still in use after kill attempts`);
@@ -13073,7 +13074,7 @@ async function waitForPort(port, timeoutMs = 3e4) {
13073
13074
  if (await isPortInUse(port)) {
13074
13075
  return true;
13075
13076
  }
13076
- await new Promise((resolve7) => setTimeout(resolve7, checkInterval));
13077
+ await new Promise((resolve8) => setTimeout(resolve8, checkInterval));
13077
13078
  }
13078
13079
  return false;
13079
13080
  }
@@ -13145,7 +13146,7 @@ async function handleProcessExit(moduleUid, code, signal) {
13145
13146
  const delay = calculateRestartDelay(serverInfo.restartCount);
13146
13147
  console.log(`[DevServer] EP932: Restarting ${moduleUid} in ${delay}ms (attempt ${serverInfo.restartCount + 1}/${MAX_RESTART_ATTEMPTS})`);
13147
13148
  writeToLog(serverInfo.logFile || "", `Scheduling restart in ${delay}ms (attempt ${serverInfo.restartCount + 1})`, false);
13148
- await new Promise((resolve7) => setTimeout(resolve7, delay));
13149
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
13149
13150
  if (!activeServers.has(moduleUid)) {
13150
13151
  console.log(`[DevServer] EP932: Server ${moduleUid} was removed during restart delay, aborting restart`);
13151
13152
  return;
@@ -13270,7 +13271,7 @@ async function stopDevServer(moduleUid) {
13270
13271
  writeToLog(serverInfo.logFile, `Stopping server (manual stop)`, false);
13271
13272
  }
13272
13273
  serverInfo.process.kill("SIGTERM");
13273
- await new Promise((resolve7) => setTimeout(resolve7, 2e3));
13274
+ await new Promise((resolve8) => setTimeout(resolve8, 2e3));
13274
13275
  if (!serverInfo.process.killed) {
13275
13276
  serverInfo.process.kill("SIGKILL");
13276
13277
  }
@@ -13288,7 +13289,7 @@ async function restartDevServer(moduleUid) {
13288
13289
  writeToLog(logFile, `Manual restart requested`, false);
13289
13290
  }
13290
13291
  await stopDevServer(moduleUid);
13291
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
13292
+ await new Promise((resolve8) => setTimeout(resolve8, 1e3));
13292
13293
  if (await isPortInUse(port)) {
13293
13294
  await killProcessOnPort(port);
13294
13295
  }
@@ -13370,7 +13371,7 @@ var IPCRouter = class {
13370
13371
  if (attempt < MAX_RETRIES) {
13371
13372
  const delay = INITIAL_DELAY * Math.pow(2, attempt - 1);
13372
13373
  console.log(`[Daemon] Retrying in ${delay / 1e3}s...`);
13373
- await new Promise((resolve7) => setTimeout(resolve7, delay));
13374
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
13374
13375
  await this.host.disconnectProject(projectPath);
13375
13376
  }
13376
13377
  }
@@ -14646,7 +14647,7 @@ var ConnectionManager = class {
14646
14647
  * handlers are removed deterministically on every exit path.
14647
14648
  */
14648
14649
  async waitForAuthentication(client, timeoutMs = 3e4) {
14649
- await new Promise((resolve7, reject) => {
14650
+ await new Promise((resolve8, reject) => {
14650
14651
  let settled = false;
14651
14652
  const cleanup = () => {
14652
14653
  clearTimeout(timeout);
@@ -14665,7 +14666,7 @@ var ConnectionManager = class {
14665
14666
  if (settled) return;
14666
14667
  settled = true;
14667
14668
  cleanup();
14668
- resolve7();
14669
+ resolve8();
14669
14670
  };
14670
14671
  const authErrorHandler = (message) => {
14671
14672
  if (settled) return;
@@ -15282,6 +15283,36 @@ async function cacheMachineUuid(machineUuid, machineId) {
15282
15283
  }
15283
15284
  }
15284
15285
 
15286
+ // src/daemon/reconciliation-utils.ts
15287
+ var path35 = __toESM(require("path"));
15288
+ function isPathUnderRoot(candidatePath, projectRoot) {
15289
+ const relative4 = path35.relative(projectRoot, candidatePath);
15290
+ return relative4 !== "" && !relative4.startsWith("..") && !path35.isAbsolute(relative4);
15291
+ }
15292
+ function collectUnexpectedWorktrees(params) {
15293
+ const projectRootResolved = path35.resolve(params.projectRoot);
15294
+ const bareRepoPathResolved = path35.resolve(params.bareRepoPath);
15295
+ const unexpectedWorktrees = [];
15296
+ for (const worktree of params.worktrees) {
15297
+ const worktreePathResolved = path35.resolve(worktree.path);
15298
+ if (worktreePathResolved === bareRepoPathResolved) continue;
15299
+ if (worktree.prunable || worktree.locked) continue;
15300
+ if (!isPathUnderRoot(worktreePathResolved, projectRootResolved)) continue;
15301
+ const moduleUid = path35.basename(worktreePathResolved);
15302
+ if (!validateModuleUid(moduleUid)) continue;
15303
+ if (!/^EP\d+$/.test(moduleUid)) continue;
15304
+ if (params.expectedModuleUids.has(moduleUid)) continue;
15305
+ const branch = worktree.branch || "unknown";
15306
+ if (branch === "HEAD (detached)") continue;
15307
+ unexpectedWorktrees.push({
15308
+ moduleUid,
15309
+ path: worktreePathResolved,
15310
+ branch
15311
+ });
15312
+ }
15313
+ return unexpectedWorktrees;
15314
+ }
15315
+
15285
15316
  // src/daemon/daemon-process.ts
15286
15317
  var packageJson = require_package();
15287
15318
  var Daemon = class _Daemon {
@@ -15484,9 +15515,9 @@ var Daemon = class _Daemon {
15484
15515
  this.healthServer = http2.createServer((req, res) => {
15485
15516
  if (req.url === "/health" || req.url === "/") {
15486
15517
  const isConnected = this.connectionManager.liveConnectionCount() > 0;
15487
- const projects = Array.from(this.connectionManager.entries()).map(([path35, conn]) => ({
15488
- path: path35,
15489
- connected: this.connectionManager.hasLiveConnection(path35)
15518
+ const projects = Array.from(this.connectionManager.entries()).map(([path37, conn]) => ({
15519
+ path: path37,
15520
+ connected: this.connectionManager.hasLiveConnection(path37)
15490
15521
  }));
15491
15522
  const status = {
15492
15523
  status: isConnected ? "healthy" : "degraded",
@@ -15623,8 +15654,8 @@ var Daemon = class _Daemon {
15623
15654
  }
15624
15655
  }
15625
15656
  let releaseLock;
15626
- const lockPromise = new Promise((resolve7) => {
15627
- releaseLock = resolve7;
15657
+ const lockPromise = new Promise((resolve8) => {
15658
+ releaseLock = resolve8;
15628
15659
  });
15629
15660
  this.tunnelOperationLocks.set(moduleUid, lockPromise);
15630
15661
  try {
@@ -15670,7 +15701,7 @@ var Daemon = class _Daemon {
15670
15701
  const maxWait = 35e3;
15671
15702
  const startTime = Date.now();
15672
15703
  while (this.connectionManager.hasPendingConnection(projectPath) && Date.now() - startTime < maxWait) {
15673
- await new Promise((resolve7) => setTimeout(resolve7, 500));
15704
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
15674
15705
  }
15675
15706
  if (this.connectionManager.hasLiveConnection(projectPath)) {
15676
15707
  console.log(`[Daemon] Pending connection succeeded for ${projectPath}`);
@@ -16489,6 +16520,7 @@ var Daemon = class _Daemon {
16489
16520
  await tunnelManager.initialize();
16490
16521
  const moduleStatuses = [];
16491
16522
  const expectedModuleUids = new Set(modules.map((m) => m.uid));
16523
+ const bareRepoPath = path36.join(projectPath, ".bare");
16492
16524
  for (const mod of modules) {
16493
16525
  const moduleUid = mod.uid;
16494
16526
  const worktree = await getWorktreeInfoForModule(moduleUid);
@@ -16519,11 +16551,36 @@ var Daemon = class _Daemon {
16519
16551
  if (orphanTunnels.length > 0) {
16520
16552
  console.log(`[Daemon] EP1003: Reporting ${orphanTunnels.length} orphan tunnel(s) for server cleanup`);
16521
16553
  }
16554
+ let unexpectedWorktrees;
16555
+ try {
16556
+ const listResult = await new import_core22.GitExecutor().execute(
16557
+ { action: "worktree_list" },
16558
+ { cwd: bareRepoPath }
16559
+ );
16560
+ if (listResult.success) {
16561
+ const localWorktrees = listResult.details?.worktrees || [];
16562
+ const discoveredUnexpectedWorktrees = collectUnexpectedWorktrees({
16563
+ worktrees: localWorktrees,
16564
+ expectedModuleUids,
16565
+ projectRoot: projectPath,
16566
+ bareRepoPath
16567
+ });
16568
+ if (discoveredUnexpectedWorktrees.length > 0) {
16569
+ unexpectedWorktrees = discoveredUnexpectedWorktrees;
16570
+ console.log(`[Daemon] EP1446: Reporting ${discoveredUnexpectedWorktrees.length} unexpected worktree(s) for recovery`);
16571
+ }
16572
+ } else {
16573
+ console.warn("[Daemon] EP1446: Failed to list local worktrees for reconciliation");
16574
+ }
16575
+ } catch (error) {
16576
+ console.warn("[Daemon] EP1446: Error while scanning local worktrees:", error instanceof Error ? error.message : error);
16577
+ }
16522
16578
  const report = {
16523
16579
  projectId,
16524
16580
  machineId: this.machineUuid,
16525
16581
  modules: moduleStatuses,
16526
- orphanTunnels: orphanTunnels.length > 0 ? orphanTunnels : void 0
16582
+ orphanTunnels: orphanTunnels.length > 0 ? orphanTunnels : void 0,
16583
+ unexpectedWorktrees
16527
16584
  };
16528
16585
  console.log(`[Daemon] EP1003: Sending reconciliation report with ${moduleStatuses.length} module(s)`);
16529
16586
  await client.send({
@@ -16770,7 +16827,7 @@ var Daemon = class _Daemon {
16770
16827
  console.log(`[Daemon] EP1002: Worktree setup complete for ${moduleUid}`);
16771
16828
  }
16772
16829
  async runForegroundCommand(command, args, cwd, env, timeoutMs) {
16773
- await new Promise((resolve7, reject) => {
16830
+ await new Promise((resolve8, reject) => {
16774
16831
  const commandLabel = `${command} ${args.join(" ")}`.trim();
16775
16832
  const child = (0, import_child_process19.spawn)(command, args, {
16776
16833
  cwd,
@@ -16793,7 +16850,7 @@ var Daemon = class _Daemon {
16793
16850
  reject(error);
16794
16851
  return;
16795
16852
  }
16796
- resolve7();
16853
+ resolve8();
16797
16854
  };
16798
16855
  termTimer = setTimeout(() => {
16799
16856
  timedOut = true;