// Local CLI: `executor web` used to mean "start a foreground server". The// first-time CLI setup path is now explicit: install the durable background// service first, then use `executor web` to open it. A fresh `web` invocation// should guide the user without minting local-server credentials/manifest state// or binding ports.import { execFile } from "node:child_process";import { existsSync, mkdtempSync, rmSync } from "node:fs";import { tmpdir } from "node:os";import { join } from "node:path";import { fileURLToPath } from "node:url";import { promisify } from "node:util";import { expect } from "@effect/vitest";import { Effect } from "effect";import { scenario } from "../src/scenario";const execFileAsync = promisify(execFile);const repoRoot = fileURLToPath(new URL("../../", import.meta.url));scenario( "CLI web · a fresh install points users at setup instead of starting a foreground server", { timeout: 120_000 }, Effect.promise(async () => { const root = mkdtempSync(join(tmpdir(), "executor-web-transition-")); const dataDir = join(root, "data"); try { const { stdout, stderr } = await execFileAsync("bun", ["run", "dev:cli", "web"], { cwd: repoRoot, env: { ...process.env, EXECUTOR_DATA_DIR: dataDir }, }); const output = `${stdout}\n${stderr}`; expect(output, "plain web should not start the old foreground server").not.toContain("Open:"); expect(output, "plain web should explain that no service is running").toContain( "Executor is not running.", ); expect(output, "plain web should direct first-time users to durable setup").toContain( "install", ); expect( output, "plain web should keep the temporary-server escape hatch discoverable", ).toContain("web --foreground"); expect( existsSync(join(dataDir, "server-control", "auth.json")), "plain web should not mint a local auth token", ).toBe(false); expect( existsSync(join(dataDir, "server-control", "server.json")), "plain web should not write a foreground server manifest", ).toBe(false); } finally { rmSync(root, { recursive: true, force: true }); } }),);
// Local CLI: `executor web` used to mean "start a foreground server". The
// first-time CLI setup path is now explicit: install the durable background
// service first, then use `executor web` to open it. A fresh `web` invocation
// should guide the user without minting local-server credentials/manifest state
// or binding ports.
import { execFile } from "node:child_process";
import { existsSync, mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";
import { expect } from "@effect/vitest";
import { Effect } from "effect";
import { scenario } from "../src/scenario";
const execFileAsync = promisify(execFile);
const repoRoot = fileURLToPath(new URL("../../", import.meta.url));
scenario(
"CLI web · a fresh install points users at setup instead of starting a foreground server",
{ timeout: 120_000 },
Effect.promise(async () => {
const root = mkdtempSync(join(tmpdir(), "executor-web-transition-"));
const dataDir = join(root, "data");
try {
const { stdout, stderr } = await execFileAsync("bun", ["run", "dev:cli", "web"], {
cwd: repoRoot,
env: { ...process.env, EXECUTOR_DATA_DIR: dataDir },
});
const output = `${stdout}\n${stderr}`;
expect(output, "plain web should not start the old foreground server").not.toContain("Open:");
expect(output, "plain web should explain that no service is running").toContain(
"Executor is not running.",
);
expect(output, "plain web should direct first-time users to durable setup").toContain(
"install",
);
expect(
output,
"plain web should keep the temporary-server escape hatch discoverable",
).toContain("web --foreground");
expect(
existsSync(join(dataDir, "server-control", "auth.json")),
"plain web should not mint a local auth token",
).toBe(false);
expect(
existsSync(join(dataDir, "server-control", "server.json")),
"plain web should not write a foreground server manifest",
).toBe(false);
} finally {
rmSync(root, { recursive: true, force: true });
}
}),
);