episoda 0.2.96 → 0.2.98

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.
@@ -2786,7 +2786,7 @@ var require_package = __commonJS({
2786
2786
  "package.json"(exports2, module2) {
2787
2787
  module2.exports = {
2788
2788
  name: "episoda",
2789
- version: "0.2.96",
2789
+ version: "0.2.98",
2790
2790
  description: "CLI tool for Episoda local development workflow orchestration",
2791
2791
  main: "dist/index.js",
2792
2792
  types: "dist/index.d.ts",
@@ -4406,6 +4406,48 @@ var WorktreeManager = class _WorktreeManager {
4406
4406
  }
4407
4407
  return { valid, stale, orphaned };
4408
4408
  }
4409
+ /**
4410
+ * EP1190: Clean up non-module worktrees (like 'main')
4411
+ *
4412
+ * In K1273 per-user-per-workspace model, only EP### worktrees should exist.
4413
+ * The 'main' worktree and other non-module worktrees are legacy artifacts
4414
+ * that can contain stale code and should be removed.
4415
+ *
4416
+ * @returns Object with removed paths and errors
4417
+ */
4418
+ async cleanupNonModuleWorktrees() {
4419
+ const removed = [];
4420
+ const errors = [];
4421
+ try {
4422
+ const validation = await this.validateWorktrees();
4423
+ for (const orphanPath of validation.orphaned) {
4424
+ const dirName = path7.basename(orphanPath);
4425
+ const isModuleWorktree = /^EP\d+$/.test(dirName);
4426
+ if (!isModuleWorktree) {
4427
+ console.log(`[WorktreeManager] EP1190: Found non-module worktree: ${dirName}`);
4428
+ try {
4429
+ const removeResult = await this.gitExecutor.execute({
4430
+ action: "worktree_remove",
4431
+ path: orphanPath,
4432
+ force: true
4433
+ // Force removal since it's not tracked
4434
+ }, { cwd: this.bareRepoPath });
4435
+ if (removeResult.success) {
4436
+ removed.push(dirName);
4437
+ console.log(`[WorktreeManager] EP1190: Removed non-module worktree: ${dirName}`);
4438
+ } else {
4439
+ errors.push(`Failed to remove ${dirName}: ${removeResult.output}`);
4440
+ }
4441
+ } catch (removeError) {
4442
+ errors.push(`Error removing ${dirName}: ${removeError.message}`);
4443
+ }
4444
+ }
4445
+ }
4446
+ } catch (error) {
4447
+ errors.push(`Validation error: ${error.message}`);
4448
+ }
4449
+ return { removed, errors };
4450
+ }
4409
4451
  /**
4410
4452
  * Get project configuration
4411
4453
  */
@@ -9425,7 +9467,6 @@ async function fetchEnvVars2() {
9425
9467
  }
9426
9468
  }
9427
9469
  var Daemon = class _Daemon {
9428
- // 60 seconds
9429
9470
  constructor() {
9430
9471
  this.machineId = "";
9431
9472
  this.machineUuid = null;
@@ -9464,6 +9505,9 @@ var Daemon = class _Daemon {
9464
9505
  // Health checks are orthogonal to push-based state sync - they detect dead tunnels
9465
9506
  this.healthCheckInterval = null;
9466
9507
  this.healthCheckInProgress = false;
9508
+ // 60 seconds
9509
+ // EP1190: Worktree cleanup runs every N health checks (5 * 60s = 5 minutes)
9510
+ this.healthCheckCounter = 0;
9467
9511
  this.ipcServer = new IPCServer();
9468
9512
  }
9469
9513
  static {
@@ -9480,6 +9524,9 @@ var Daemon = class _Daemon {
9480
9524
  static {
9481
9525
  this.HEALTH_CHECK_INTERVAL_MS = 6e4;
9482
9526
  }
9527
+ static {
9528
+ this.WORKTREE_CLEANUP_EVERY_N_CHECKS = 5;
9529
+ }
9483
9530
  /**
9484
9531
  * Start the daemon
9485
9532
  */
@@ -9555,6 +9602,8 @@ var Daemon = class _Daemon {
9555
9602
  // EP1091: New preferred field name
9556
9603
  deviceId: this.machineUuid,
9557
9604
  // EP726: Kept for backward compatibility
9605
+ machineName: this.deviceName,
9606
+ // EP1186: User-friendly machine name from server
9558
9607
  hostname: os8.hostname(),
9559
9608
  platform: os8.platform(),
9560
9609
  arch: os8.arch(),
@@ -10374,6 +10423,10 @@ var Daemon = class _Daemon {
10374
10423
  client.on("machine_uuid_update", async (message) => {
10375
10424
  try {
10376
10425
  const uuidMsg = message;
10426
+ if (uuidMsg.machineName) {
10427
+ this.deviceName = uuidMsg.machineName;
10428
+ console.log(`[Daemon] EP1186: Machine name updated: ${this.deviceName}`);
10429
+ }
10377
10430
  if (uuidMsg.machineUuid) {
10378
10431
  this.machineUuid = uuidMsg.machineUuid;
10379
10432
  console.log(`[Daemon] EP1095: Machine UUID updated: ${this.machineUuid}`);
@@ -11211,6 +11264,11 @@ var Daemon = class _Daemon {
11211
11264
  if (config?.access_token) {
11212
11265
  await this.performHealthChecks(config);
11213
11266
  }
11267
+ this.healthCheckCounter++;
11268
+ if (this.healthCheckCounter >= _Daemon.WORKTREE_CLEANUP_EVERY_N_CHECKS) {
11269
+ this.healthCheckCounter = 0;
11270
+ await this.auditWorktreesOnStartup();
11271
+ }
11214
11272
  } catch (error) {
11215
11273
  console.error("[Daemon] EP929: Health check error:", error instanceof Error ? error.message : error);
11216
11274
  } finally {
@@ -11397,6 +11455,19 @@ var Daemon = class _Daemon {
11397
11455
  console.warn("[Daemon] EP1035: Failed to prune stale worktrees:", pruneError.message);
11398
11456
  }
11399
11457
  }
11458
+ try {
11459
+ const cleanupResult = await manager.cleanupNonModuleWorktrees();
11460
+ if (cleanupResult.removed.length > 0) {
11461
+ console.log(`[Daemon] EP1190: Cleaned up ${cleanupResult.removed.length} non-module worktree(s): ${cleanupResult.removed.join(", ")}`);
11462
+ }
11463
+ if (cleanupResult.errors.length > 0) {
11464
+ for (const err of cleanupResult.errors) {
11465
+ console.warn(`[Daemon] EP1190: Non-module cleanup error: ${err}`);
11466
+ }
11467
+ }
11468
+ } catch (cleanupError) {
11469
+ console.warn("[Daemon] EP1190: Failed to cleanup non-module worktrees:", cleanupError.message);
11470
+ }
11400
11471
  } catch (error) {
11401
11472
  console.warn(`[Daemon] EP1035: Failed to audit ${projectPath}:`, error);
11402
11473
  }