diff --git a/src/lib/actions/uninstall/run-plan.ts b/src/lib/actions/uninstall/run-plan.ts index c99289bbeb..29b6f5ef75 100644 --- a/src/lib/actions/uninstall/run-plan.ts +++ b/src/lib/actions/uninstall/run-plan.ts @@ -601,6 +601,7 @@ function executePlan(plan: UninstallPlan, paths: UninstallPaths, options: Uninst if (options.keepOpenShell) runtime.log("Keeping OpenShell binaries as requested."); else for (const target of paths.openshellInstallPaths) removeFileWithOptionalSudo(target, runtime); removePath(paths.nemoclawStateDir, runtime); + removePath(paths.gatewayLocalStateDir, runtime); removePath(paths.openshellConfigDir, runtime); removePath(paths.nemoclawConfigDir, runtime); } diff --git a/src/lib/domain/uninstall/paths.test.ts b/src/lib/domain/uninstall/paths.test.ts index 98fe073412..7027562bbf 100644 --- a/src/lib/domain/uninstall/paths.test.ts +++ b/src/lib/domain/uninstall/paths.test.ts @@ -44,8 +44,18 @@ describe("uninstall paths", () => { const paths = defaultUninstallPaths({ home: "/home/test" }); expect(uninstallStatePaths(paths)).toEqual([ path.join("/home/test", ".nemoclaw"), + path.join("/home/test", ".local", "state", "nemoclaw"), path.join("/home/test", ".config", "openshell"), path.join("/home/test", ".config", "nemoclaw"), ]); }); + it("#3456: exposes the Linux Docker-driver gateway state dir so uninstall can clean it", () => { + // ~/.local/state/nemoclaw/ holds the openshell-gateway PID file, SQLite + // database, audit log, and vm-driver/ state. Documented as + // NEMOCLAW_OPENSHELL_GATEWAY_STATE_DIR in docs/reference/commands.md. + // Before this fix, uninstall left it behind (#3456 hulynn comment). + const paths = defaultUninstallPaths({ home: "/home/test" }); + expect(paths.gatewayLocalStateDir).toBe(path.join("/home/test", ".local", "state", "nemoclaw")); + expect(uninstallStatePaths(paths)).toContain(path.join("/home/test", ".local", "state", "nemoclaw")); + }); }); diff --git a/src/lib/domain/uninstall/paths.ts b/src/lib/domain/uninstall/paths.ts index 2c46a3a3bb..32e8602ca3 100644 --- a/src/lib/domain/uninstall/paths.ts +++ b/src/lib/domain/uninstall/paths.ts @@ -32,6 +32,7 @@ export interface UninstallPaths { nemoclawConfigDir: string; nemoclawShimPath: string; nemoclawStateDir: string; + gatewayLocalStateDir: string; openshellConfigDir: string; openshellInstallPaths: string[]; repoRoot: string; @@ -57,6 +58,7 @@ export function defaultUninstallPaths(options: UninstallPathOptions): UninstallP nemoclawConfigDir: path.join(options.home, ".config", "nemoclaw"), nemoclawShimPath: path.join(options.home, ".local", "bin", "nemoclaw"), nemoclawStateDir: path.join(options.home, ".nemoclaw"), + gatewayLocalStateDir: path.join(options.home, ".local", "state", "nemoclaw"), openshellConfigDir: path.join(options.home, ".config", "openshell"), openshellInstallPaths: openshellInstallPathsForBinDirs(["/usr/local/bin", xdgBinHome]), repoRoot: options.repoRoot || path.resolve(__dirname, "..", "..", "..", ".."), @@ -73,6 +75,6 @@ export function defaultUninstallPaths(options: UninstallPathOptions): UninstallP }; } -export function uninstallStatePaths(paths: Pick): string[] { - return [paths.nemoclawStateDir, paths.openshellConfigDir, paths.nemoclawConfigDir]; +export function uninstallStatePaths(paths: Pick): string[] { + return [paths.nemoclawStateDir, paths.gatewayLocalStateDir, paths.openshellConfigDir, paths.nemoclawConfigDir]; }