@adhdev/daemon-core 0.9.82-rc.377 → 0.9.82-rc.379

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.
@@ -314,8 +314,18 @@ export const meshCrudHandlers: Record<string, MedFamilyHandler> = {
314
314
  }
315
315
  }
316
316
 
317
+ // Default worktree session cleanup ON: when the caller OMITS a mode and the
318
+ // node is a local worktree, default to 'stop_and_delete' instead of the mesh
319
+ // policy ('preserve' by default). A worktree's chat session has no reason to
320
+ // outlive the worktree's node + directory + branch, and leaving it on
321
+ // 'preserve' is what orphaned chats after a worktree remove. An explicit mode
322
+ // (including an explicit 'preserve') is always honored — only the OMITTED case
323
+ // changes, and only for worktrees. Base nodes keep arg ?? policy ?? preserve.
324
+ const explicitCleanupMode = args?.sessionCleanupMode ?? args?.session_cleanup_mode;
317
325
  const sessionCleanupMode = ctx.normalizeMeshSessionCleanupMode(
318
- args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove,
326
+ explicitCleanupMode
327
+ ?? (node?.isLocalWorktree === true ? 'stop_and_delete' : undefined)
328
+ ?? mesh?.policy?.sessionCleanupOnNodeRemove,
319
329
  );
320
330
  // Explicit sessionIds (e.g. supplied by refine auto-cleanup) bypass the
321
331
  // workspace-only-match guard so a delegate session that lacks a
@@ -423,12 +433,29 @@ export const meshCrudHandlers: Record<string, MedFamilyHandler> = {
423
433
  const residueWarning = worktreeCleanup?.residue === true && typeof worktreeCleanup?.residueWarning === 'string'
424
434
  ? worktreeCleanup.residueWarning
425
435
  : undefined;
436
+
437
+ // Orphan guard: if the session cleanup still left any LIVE session skipped
438
+ // (e.g. a future skip reason, or a workspace-only session on a base node),
439
+ // surface it at the top level so the caller knows a manual mesh_cleanup_sessions
440
+ // is still required for those sessionIds. Without this, a skipped-live session
441
+ // silently outlives a removed node (the very NODE-REMOVE-SESSION-ORPHAN bug).
442
+ const skippedLiveSessionIds = Array.isArray(sessionCleanup?.skippedLiveSessionIds)
443
+ ? (sessionCleanup!.skippedLiveSessionIds as unknown[]).filter((v): v is string => typeof v === 'string')
444
+ : [];
445
+ const orphanedSessionsRemaining = skippedLiveSessionIds.length > 0;
446
+ const orphanNextAction = orphanedSessionsRemaining
447
+ ? `Live session(s) [${skippedLiveSessionIds.join(', ')}] were skipped and still survive this node removal. `
448
+ + `Run mesh_cleanup_sessions with mode:'stop_and_delete' and sessionIds:[${skippedLiveSessionIds.map(id => `'${id}'`).join(', ')}] to release them.`
449
+ : undefined;
426
450
  return {
427
451
  success: true,
428
452
  removed,
429
453
  ...(residueWarning ? { residueWarning } : {}),
430
454
  ...(sessionCleanup ? { sessionCleanup } : {}),
431
455
  ...(worktreeCleanup ? { worktreeCleanup } : {}),
456
+ ...(orphanedSessionsRemaining
457
+ ? { orphanedSessionsRemaining: true, nextAction: orphanNextAction }
458
+ : {}),
432
459
  };
433
460
  } catch (e: any) {
434
461
  return { success: false, error: e.message };