diff --git a/apps/hub/src/sidecar/data-root.ts b/apps/hub/src/sidecar/data-root.ts index 953d14da..f692cc2a 100644 --- a/apps/hub/src/sidecar/data-root.ts +++ b/apps/hub/src/sidecar/data-root.ts @@ -1,4 +1,12 @@ -/** Local sidecar state root. Never a launch-specific coding directory. */ +import { resolve } from "node:path"; + +/** + * Local sidecar state root. Never a launch-specific coding directory. + * + * Absolute because sidecars run with `vendor/interchange` as their working + * directory; a relative root would put their state there instead of beside the + * hub's. + */ export function localSidecarDataRoot(hubDataDir: string): string { - return `${hubDataDir}/local-sidecars`; + return resolve(hubDataDir, "local-sidecars"); } diff --git a/apps/hub/src/sidecar/local-provisioner.ts b/apps/hub/src/sidecar/local-provisioner.ts index 981cd82f..9f14ca64 100644 --- a/apps/hub/src/sidecar/local-provisioner.ts +++ b/apps/hub/src/sidecar/local-provisioner.ts @@ -503,10 +503,15 @@ export function createLocalProcessSidecarProvisioner({ }); return; } - manifest = stored; + // The data dir follows the hub's data root, not the manifest: a manifest written when the root was relative + // points the sidecar, which runs from vendor/interchange, at a directory under it. + const restored = + stored.dataDir === dataDir ? stored : { ...stored, dataDir }; + if (restored !== stored) await manifests.write(restored); + manifest = restored; for (const hold of live) holds.set(hold.allocationId, hold); await manifests.writeHolds(live); - const child = await start(stored); + const child = await start(restored); log({ level: "info", msg: "local_sidecar_respawned",