diff --git a/plugin/pi/index.ts b/plugin/pi/index.ts index 6f947d5ae..e0be40954 100644 --- a/plugin/pi/index.ts +++ b/plugin/pi/index.ts @@ -824,6 +824,9 @@ function spawnAndWaitForEngram(deadline: number, expectedID = ""): Promise try { proc = spawn(ENGRAM_BIN, ["serve"], { + // Opt into cloud autosync like the Claude Code and Codex launchers; the + // server skips it on its own when no cloud server or token is configured. + env: { ...process.env, ENGRAM_CLOUD_AUTOSYNC: "1" }, windowsHide: true, detached: true, stdio: "ignore", diff --git a/plugin/pi/test/startup-lifecycle.test.mjs b/plugin/pi/test/startup-lifecycle.test.mjs index 6a4821cbe..3efb62af1 100644 --- a/plugin/pi/test/startup-lifecycle.test.mjs +++ b/plugin/pi/test/startup-lifecycle.test.mjs @@ -45,6 +45,7 @@ if (process.argv.includes("sync") || process.argv.includes("--import")) { append const isServe = process.argv[2] === "serve" || isSyntheticServe; if (isServe) { appendFileSync(${JSON.stringify(spawnLog)}, "serve\\n"); + appendFileSync(${JSON.stringify(spawnLog)}, "autosync=" + (process.env.ENGRAM_CLOUD_AUTOSYNC ?? "") + "\\n"); ${exitCode === undefined ? `const server = createServer(async (req, res) => { if (req.url === "/sessions") { @@ -260,6 +261,24 @@ test("a slow health probe never authorizes a duplicate spawn", async () => { }); }); +test("a plugin-launched server starts with cloud autosync enabled", async () => { + const previous = process.env.ENGRAM_CLOUD_AUTOSYNC; + delete process.env.ENGRAM_CLOUD_AUTOSYNC; + try { + await withFixture({ readyAfterMs: 0 }, async ({ hooks, ctx, spawnLog }) => { + await hooks.get("session_start")({}, ctx); + + assert.equal(await countSpawns(spawnLog), 1, "the plugin spawns the server"); + const log = await readFile(spawnLog, "utf8"); + assert.ok(log.split("\n").includes("autosync=1"), + "the daemon must opt into cloud autosync, like the Claude Code and Codex launchers"); + }); + } finally { + if (previous === undefined) delete process.env.ENGRAM_CLOUD_AUTOSYNC; + else process.env.ENGRAM_CLOUD_AUTOSYNC = previous; + } +}); + test("a child that exits before readiness surfaces a normalized tool error", async () => { await withFixture({ exitCode: 1 }, async ({ tools, ctx }) => { const memSearch = tools.get("mem_search");