Run server tests on Linux+Windows matrix (#809)

* Run server tests on Linux+Windows matrix

Replace the hand-curated Windows server test allow-list with a full-suite matrix run.\nBoth Ubuntu and Windows now run the same server test command with shared setup and secrets.

* Add isPlatform helper and gate Windows-hostile server tests

- Add a shared server test isPlatform helper.

- Migrate existing Windows-gated spawn, worktree, executable, and worktree-core tests to the helper.

- Gate Windows-hostile symlink, macOS path-normalization, and POSIX shell setup tests with skipIf.

* Replace POSIX shell calls in test fixtures with Node primitives

- Replaced test fixture mkdir/echo shell setup with fs mkdirSync/writeFileSync calls in touched server tests.

- Replaced git shell strings with execFileSync/spawnSync argv calls across checkout, worktree, MCP, script, and workspace git fixtures.

- Gated the directory suggestion symlink escape tests on Windows because those fixtures require POSIX symlink behavior.

* Fix Windows server-test failures and split POSIX-only suites into sibling files

- Fix Windows path/cwd assertions in terminal, session/workspace, git-service, checkout-git, MCP, logger, spawn, and registry bootstrap tests.\n- Keep terminal tests runnable on Windows by canonicalizing temp cwd fixtures and ensuring a Windows shell fallback.\n- Gate POSIX-only shell, signal, Unix socket, and git-worktree reuse fixtures that need dedicated Windows coverage later.

* Move POSIX-only test blocks into sibling .posix.test.ts files

- terminal.test.ts: moved PTY/bash interaction blocks into terminal.posix.test.ts.

- worktree.test.ts: moved git-worktree and teardown shell blocks into worktree.posix.test.ts.

- worktree-bootstrap.test.ts: moved setup shell and terminal-backed service blocks into worktree-bootstrap.posix.test.ts.

- worktree-core.test.ts: moved the POSIX-only worktree-core suite into worktree-core.posix.test.ts and removed the empty original.

- provider-availability.test.ts and file-explorer/service.test.ts: moved POSIX PATH/symlink blocks into sibling suites.

* Fix Windows 8.3 short-name, EBUSY cleanup, and node-pty shell-path failures in server tests

- Normalize temp home directories in directory suggestion assertions to avoid Windows short-name mismatches.

- Use Windows-valid terminal shells/cwds in terminal fixtures and wait for terminal-manager PTYs before cleanup.

- Replace hardcoded POSIX paths in workspace-git/MCP/loop fixtures with platform-resolved paths or command files.

- Gate the two explicitly Linux-only workspace-git watcher tests.

* Replace hardcoded POSIX paths with portable Node path constructions in server tests

- checkout-git.test.ts and worktree-session.test.ts: compare Windows temp paths with realpathSync.native to avoid 8.3 short-name mismatches.

- directory-suggestions.test.ts: canonicalize result and expected paths with realpathSync.native.

- session.workspaces.test.ts: replace literal /tmp and /Users fixtures with path.resolve/path.join constructions.

- workspace-git-service.primitive.test.ts, loop-service.test.ts, and mcp-server.test.ts: use canonical repo/temp paths and shell-safe relative verify commands.

* Fix loop-service verify-check shell and workspace-git-service path-separator on Windows

- Run the loop-service verify script through the current Node executable with a relative script path.

- Normalize the workspace-git-service expected repo cwd to forward slashes for the listWorktrees assertion.

* Fix loop-service worker PTY spawn on Windows

- Canonicalize the loop-service temporary root and workspace with realpathSync.native before worker agents use the path as cwd.

* Gate loop-service real-worker-PTY test on Windows

- Skip the real worker PTY loop test on Windows after ConPTY path resolution still fails with node-pty error 267.\n- Keep the test running on POSIX so the loop behavior remains covered.

* Stub getMetricsSnapshot in test mocks to suppress async-leak uncaught exceptions on Windows

- Add a no-op AgentManager metrics snapshot to the WebSocket notification test server stub.

* Fix terminal-manager Windows-path test to avoid PTY spawn into nonexistent dir

- Use an existing temporary cwd for the createTerminal absolute-path validation assertion so node-pty does not spawn into a missing Windows directory.
This commit is contained in:
Mohamed Boudra
2026-05-08 10:57:22 +08:00
committed by GitHub
parent 39e461b872
commit c4e4a28bc0
44 changed files with 5673 additions and 4899 deletions
@@ -1,4 +1,4 @@
import { execSync } from "node:child_process";
import { execFileSync } from "node:child_process";
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
import { homedir, tmpdir } from "node:os";
import path from "node:path";
@@ -48,6 +48,9 @@ import {
createPersistedWorkspaceRecord,
} from "./workspace-registry.js";
const REPO_CWD = path.resolve("/tmp/repo");
const UNREGISTERED_CWD = path.resolve("/tmp/unregistered");
interface SessionTestAccess {
projectRegistry: {
list(...args: unknown[]): Promise<unknown[]>;
@@ -604,7 +607,7 @@ test("unsupported persisted agents are excluded from active lists but preserved
const storedRecord = {
id: "agent-unsupported",
provider: "gemini",
cwd: "/tmp/history",
cwd: path.resolve("/tmp/history"),
createdAt: "2026-04-13T10:13:11.457Z",
updatedAt: "2026-04-13T10:16:06.556Z",
lastActivityAt: "2026-04-13T10:16:06.556Z",
@@ -727,7 +730,7 @@ test("agent_update placement does not refresh git snapshots", async () => {
);
const project = createPersistedProjectRecord({
projectId: "proj-1",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -736,7 +739,7 @@ test("agent_update placement does not refresh git snapshots", async () => {
const workspace = createPersistedWorkspaceRecord({
workspaceId: "ws-1",
projectId: project.projectId,
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -755,7 +758,7 @@ test("agent_update placement does not refresh git snapshots", async () => {
await session.forwardAgentUpdate(
makeManagedAgent({
id: "agent-1",
cwd: "/tmp/repo",
cwd: REPO_CWD,
lifecycle: "running",
updatedAt: "2026-03-30T15:00:00.000Z",
}),
@@ -801,7 +804,7 @@ test("agent_update emits fallback placement when no workspace is registered", as
await session.forwardAgentUpdate(
makeManagedAgent({
id: "agent-1",
cwd: "/tmp/unregistered",
cwd: UNREGISTERED_CWD,
lifecycle: "running",
updatedAt: "2026-03-30T15:00:00.000Z",
}),
@@ -811,10 +814,10 @@ test("agent_update emits fallback placement when no workspace is registered", as
expect(emitted.find((message) => message.type === "agent_update")?.payload).toMatchObject({
kind: "upsert",
project: {
projectKey: "/tmp/unregistered",
projectKey: UNREGISTERED_CWD,
projectName: "unregistered",
checkout: {
cwd: "/tmp/unregistered",
cwd: UNREGISTERED_CWD,
isGit: false,
},
},
@@ -826,7 +829,7 @@ test("archive emits an authoritative agent_update upsert for subscribed clients"
const archivedRecord = {
id: "agent-1",
provider: "codex",
cwd: "/tmp/repo",
cwd: REPO_CWD,
createdAt: "2026-03-30T15:00:00.000Z",
updatedAt: "2026-03-30T15:00:00.000Z",
lastActivityAt: "2026-03-30T15:00:00.000Z",
@@ -836,7 +839,7 @@ test("archive emits an authoritative agent_update upsert for subscribed clients"
runtimeInfo: null,
config: {
provider: "codex",
cwd: "/tmp/repo",
cwd: REPO_CWD,
},
persistence: null,
title: "Archive me",
@@ -893,7 +896,7 @@ test("archive emits an authoritative agent_update upsert for subscribed clients"
projectRegistry: (() => {
const proj = createPersistedProjectRecord({
projectId: "proj-1",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "non_git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -913,7 +916,7 @@ test("archive emits an authoritative agent_update upsert for subscribed clients"
const ws = createPersistedWorkspaceRecord({
workspaceId: "ws-1",
projectId: "proj-1",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "directory",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -934,7 +937,7 @@ test("archive emits an authoritative agent_update upsert for subscribed clients"
loopService: asLoopService(),
checkoutDiffManager: asCheckoutDiffManager({
subscribe: async () => ({
initial: { cwd: "/tmp/repo", files: [], error: null },
initial: { cwd: REPO_CWD, files: [], error: null },
unsubscribe: () => {},
}),
scheduleRefreshForCwd: () => {},
@@ -996,7 +999,7 @@ test("close_items_request archives agents and kills terminals in one batch", asy
const archivedRecord = {
id: "agent-1",
provider: "codex",
cwd: "/tmp/repo",
cwd: REPO_CWD,
model: null,
thinkingOptionId: null,
effectiveThinkingOptionId: null,
@@ -1055,7 +1058,7 @@ test("close_items_request archives agents and kills terminals in one batch", asy
projectRegistry: (() => {
const proj = createPersistedProjectRecord({
projectId: "proj-close",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "non_git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1075,7 +1078,7 @@ test("close_items_request archives agents and kills terminals in one batch", asy
const ws = createPersistedWorkspaceRecord({
workspaceId: "ws-close",
projectId: "proj-close",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "directory",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1170,7 +1173,7 @@ test("close_items_request archives stored agents that are not currently loaded",
const liveRecord = {
...makeAgent({
id: "agent-live",
cwd: "/tmp/repo",
cwd: REPO_CWD,
status: "idle",
updatedAt: "2026-03-01T12:00:00.000Z",
}),
@@ -1179,7 +1182,7 @@ test("close_items_request archives stored agents that are not currently loaded",
const storedRecord = {
...makeAgent({
id: storedAgentId,
cwd: "/tmp/repo",
cwd: REPO_CWD,
status: "idle",
updatedAt: "2026-03-01T12:05:00.000Z",
}),
@@ -1244,7 +1247,7 @@ test("close_items_request archives stored agents that are not currently loaded",
projectRegistry: (() => {
const proj = createPersistedProjectRecord({
projectId: "proj-stored",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "non_git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1264,7 +1267,7 @@ test("close_items_request archives stored agents that are not currently loaded",
const ws = createPersistedWorkspaceRecord({
workspaceId: "ws-stored",
projectId: "proj-stored",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "directory",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1350,7 +1353,7 @@ test("close_items_request continues after an archive failure", async () => {
const goodRecord = {
...makeAgent({
id: "agent-good",
cwd: "/tmp/repo",
cwd: REPO_CWD,
status: "idle",
updatedAt: "2026-03-01T12:00:00.000Z",
}),
@@ -1393,7 +1396,7 @@ test("close_items_request continues after an archive failure", async () => {
projectRegistry: (() => {
const proj = createPersistedProjectRecord({
projectId: "proj-err",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "non_git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1413,7 +1416,7 @@ test("close_items_request continues after an archive failure", async () => {
const ws = createPersistedWorkspaceRecord({
workspaceId: "ws-err",
projectId: "proj-err",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "directory",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1714,9 +1717,12 @@ test("active-scoped fetch_agents pages within active scope instead of global his
test("legacy unscoped fetch_agents keeps global workspace behavior", async () => {
const session = createSessionForWorkspaceTests();
const legacyRoot = path.resolve("/tmp/legacy");
const activeCwd = path.join(legacyRoot, "active");
const archivedCwd = path.join(legacyRoot, "archived");
const project = createPersistedProjectRecord({
projectId: "proj-legacy-global",
rootPath: "/tmp/legacy",
rootPath: legacyRoot,
kind: "non_git",
displayName: "legacy",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1725,7 +1731,7 @@ test("legacy unscoped fetch_agents keeps global workspace behavior", async () =>
const activeWorkspace = createPersistedWorkspaceRecord({
workspaceId: "ws-legacy-active",
projectId: project.projectId,
cwd: "/tmp/legacy/active",
cwd: activeCwd,
kind: "directory",
displayName: "active",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1734,7 +1740,7 @@ test("legacy unscoped fetch_agents keeps global workspace behavior", async () =>
const archivedWorkspace = createPersistedWorkspaceRecord({
workspaceId: "ws-legacy-archived",
projectId: project.projectId,
cwd: "/tmp/legacy/archived",
cwd: archivedCwd,
kind: "directory",
displayName: "archived",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1747,13 +1753,13 @@ test("legacy unscoped fetch_agents keeps global workspace behavior", async () =>
session.listAgentPayloads = async () => [
makeAgent({
id: "legacy-active",
cwd: "/tmp/legacy/active",
cwd: activeCwd,
status: "idle",
updatedAt: "2026-03-01T12:01:00.000Z",
}),
makeAgent({
id: "legacy-archived-workspace",
cwd: "/tmp/legacy/archived",
cwd: archivedCwd,
status: "idle",
updatedAt: "2026-03-01T12:00:00.000Z",
}),
@@ -1773,9 +1779,10 @@ test("legacy unscoped fetch_agents keeps global workspace behavior", async () =>
test("fetch_agent_history_request pages archived historical rows separately", async () => {
const emitted: SessionOutboundMessage[] = [];
const session = createSessionForWorkspaceTests();
const historyCwd = path.resolve("/tmp/history");
const project = createPersistedProjectRecord({
projectId: "proj-history",
rootPath: "/tmp/history",
rootPath: historyCwd,
kind: "non_git",
displayName: "history",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1784,7 +1791,7 @@ test("fetch_agent_history_request pages archived historical rows separately", as
const workspace = createPersistedWorkspaceRecord({
workspaceId: "ws-history",
projectId: project.projectId,
cwd: "/tmp/history",
cwd: historyCwd,
kind: "directory",
displayName: "history",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1801,7 +1808,7 @@ test("fetch_agent_history_request pages archived historical rows separately", as
{
...makeAgent({
id: "history-archived",
cwd: "/tmp/history",
cwd: historyCwd,
status: "idle",
updatedAt: "2026-03-01T12:00:00.000Z",
}),
@@ -1842,7 +1849,7 @@ test("fetch_agent_request still resolves archived historical agents", async () =
const agent = {
...makeAgent({
id: "archived-history-agent",
cwd: "/tmp/history-detail",
cwd: path.resolve("/tmp/history-detail"),
status: "idle",
updatedAt: "2026-03-01T12:00:00.000Z",
}),
@@ -1941,7 +1948,7 @@ test("branch/detached policies and dominant status bucket are deterministic", as
createPersistedWorkspaceRecord({
workspaceId: "ws-repo-status",
projectId: "proj-repo-status",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -1951,19 +1958,19 @@ test("branch/detached policies and dominant status bucket are deterministic", as
session.listAgentPayloads = async () => [
makeAgent({
id: "a1",
cwd: "/tmp/repo",
cwd: REPO_CWD,
status: "running",
updatedAt: "2026-03-01T12:00:00.000Z",
}),
makeAgent({
id: "a2",
cwd: "/tmp/repo",
cwd: REPO_CWD,
status: "error",
updatedAt: "2026-03-01T12:01:00.000Z",
}),
makeAgent({
id: "a3",
cwd: "/tmp/repo",
cwd: REPO_CWD,
status: "idle",
updatedAt: "2026-03-01T12:02:00.000Z",
pendingPermissions: 1,
@@ -1985,7 +1992,7 @@ test("subdirectory agents map to an existing parent workspace descriptor", async
createPersistedWorkspaceRecord({
workspaceId: "ws-repo-subdir",
projectId: "proj-repo-subdir",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "main",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -2101,12 +2108,12 @@ test("workspace update stream keeps persisted workspace visible after agents sto
session.buildWorkspaceDescriptorMap = async () =>
new Map([
[
"/tmp/repo",
REPO_CWD,
{
id: "ws-repo-running",
projectId: "proj-repo-running",
projectDisplayName: "repo",
projectRootPath: "/tmp/repo",
projectRootPath: REPO_CWD,
projectKind: "non_git",
workspaceKind: "directory",
name: "repo",
@@ -2115,17 +2122,17 @@ test("workspace update stream keeps persisted workspace visible after agents sto
},
],
]);
await session.emitWorkspaceUpdateForCwd("/tmp/repo");
await session.emitWorkspaceUpdateForCwd(REPO_CWD);
session.buildWorkspaceDescriptorMap = async () =>
new Map([
[
"/tmp/repo",
REPO_CWD,
{
id: "ws-repo-running",
projectId: "proj-repo-running",
projectDisplayName: "repo",
projectRootPath: "/tmp/repo",
projectRootPath: REPO_CWD,
projectKind: "non_git",
workspaceKind: "directory",
name: "repo",
@@ -2134,7 +2141,7 @@ test("workspace update stream keeps persisted workspace visible after agents sto
},
],
]);
await session.emitWorkspaceUpdateForCwd("/tmp/repo");
await session.emitWorkspaceUpdateForCwd(REPO_CWD);
const workspaceUpdates = filterByType(emitted, "workspace_update");
expect(workspaceUpdates).toHaveLength(2);
@@ -2145,7 +2152,7 @@ test("workspace update stream keeps persisted workspace visible after agents sto
id: "ws-repo-running",
projectId: "proj-repo-running",
projectDisplayName: "repo",
projectRootPath: "/tmp/repo",
projectRootPath: REPO_CWD,
projectKind: "non_git",
workspaceKind: "directory",
name: "repo",
@@ -2160,13 +2167,19 @@ test("create paseo worktree request returns a registered workspace descriptor",
const tempDir = realpathSync(mkdtempSync(path.join(tmpdir(), "session-worktree-test-")));
const repoDir = path.join(tempDir, "repo");
const paseoHome = path.join(tempDir, "paseo-home");
execSync(`mkdir -p ${repoDir}`);
execSync("git init -b main", { cwd: repoDir, stdio: "pipe" });
execSync("git config user.email 'test@test.com'", { cwd: repoDir, stdio: "pipe" });
execSync("git config user.name 'Test'", { cwd: repoDir, stdio: "pipe" });
mkdirSync(repoDir, { recursive: true });
execFileSync("git", ["init", "-b", "main"], { cwd: repoDir, stdio: "pipe" });
execFileSync("git", ["config", "user.email", "test@test.com"], {
cwd: repoDir,
stdio: "pipe",
});
execFileSync("git", ["config", "user.name", "Test"], { cwd: repoDir, stdio: "pipe" });
writeFileSync(path.join(repoDir, "file.txt"), "hello\n");
execSync("git add .", { cwd: repoDir, stdio: "pipe" });
execSync("git -c commit.gpgsign=false commit -m 'initial'", { cwd: repoDir, stdio: "pipe" });
execFileSync("git", ["add", "."], { cwd: repoDir, stdio: "pipe" });
execFileSync("git", ["-c", "commit.gpgsign=false", "commit", "-m", "initial"], {
cwd: repoDir,
stdio: "pipe",
});
const workspaceGitService = createNoopWorkspaceGitService();
workspaceGitService.getSnapshot = vi.fn(async (cwd: string) => {
if (cwd === repoDir) {
@@ -2263,7 +2276,7 @@ test("workspace update fanout for multiple cwd values is deduplicated", async ()
createPersistedWorkspaceRecord({
workspaceId: "ws-repo-main",
projectId: "proj-repo-main",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "main",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -2296,7 +2309,7 @@ test("workspace update fanout for multiple cwd values is deduplicated", async ()
id: "ws-repo-main",
projectId: "proj-repo-main",
projectDisplayName: "repo",
projectRootPath: "/tmp/repo",
projectRootPath: REPO_CWD,
projectKind: "git",
workspaceKind: "local_checkout",
name: "main",
@@ -2310,7 +2323,7 @@ test("workspace update fanout for multiple cwd values is deduplicated", async ()
id: "ws-repo-feature",
projectId: "proj-repo-main",
projectDisplayName: "repo",
projectRootPath: "/tmp/repo",
projectRootPath: REPO_CWD,
projectKind: "git",
workspaceKind: "worktree",
name: "feature",
@@ -2376,14 +2389,14 @@ test("open_project_request registers a workspace before any agent exists", async
await session.handleMessage({
type: "open_project_request",
cwd: "/tmp/repo",
cwd: REPO_CWD,
requestId: "req-open",
});
expect(workspaces.get("/tmp/repo")).toBeTruthy();
expect(workspaces.get(REPO_CWD)).toBeTruthy();
const response = findByType(emitted, "open_project_response");
expect(response?.payload.error).toBeNull();
expect(response?.payload.workspace?.id).toBe("/tmp/repo");
expect(response?.payload.workspace?.id).toBe(REPO_CWD);
});
test("open_project_response returns immediately even when the GitHub fetch is slow", async () => {
@@ -2391,7 +2404,7 @@ test("open_project_response returns immediately even when the GitHub fetch is sl
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const cwd = "/tmp/slow-github-repo";
const cwd = path.resolve("/tmp/slow-github-repo");
session.emit = (message) => {
if (isSessionOutboundMessage(message)) emitted.push(message);
@@ -2453,7 +2466,7 @@ test("open_project_request emits a workspace_update with githubRuntime once the
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const cwd = "/tmp/github-runtime-repo";
const cwd = path.resolve("/tmp/github-runtime-repo");
const snapshot = createWorkspaceRuntimeSnapshot(cwd);
let listener: ((snapshot: WorkspaceGitRuntimeSnapshot) => void) | null = null;
@@ -2545,8 +2558,8 @@ test("open_project_request does not match a new child directory to an existing p
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const home = "/Users/moboudra";
const worktree = "/Users/moboudra/.paseo/worktrees/project-config-lifecycle-textarea";
const home = path.resolve("/Users/moboudra");
const worktree = path.join(home, ".paseo", "worktrees", "project-config-lifecycle-textarea");
projects.set(
home,
@@ -2609,8 +2622,8 @@ test("open_project_request does not unarchive an archived parent workspace for a
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const home = "/Users/moboudra";
const worktree = "/Users/moboudra/.paseo/worktrees/project-config-lifecycle-textarea";
const home = path.resolve("/Users/moboudra");
const worktree = path.join(home, ".paseo", "worktrees", "project-config-lifecycle-textarea");
const archivedAt = "2026-04-24T08:00:00.000Z";
projects.set(
@@ -2677,8 +2690,14 @@ test("open_project_request reclassifies an archived directory workspace when git
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const cwd = "/Users/moboudra/.paseo/worktrees/orchestrate/desktop-daemon-settings";
const repoRoot = "/Users/moboudra/dev/paseo";
const repoRoot = path.resolve("/Users/moboudra/dev/paseo");
const cwd = path.join(
path.resolve("/Users/moboudra"),
".paseo",
"worktrees",
"orchestrate",
"desktop-daemon-settings",
);
const remoteProjectId = "remote:github.com/getpaseo/paseo";
const archivedAt = "2026-04-24T09:48:36.168Z";
@@ -2769,8 +2788,14 @@ test("open_project_request reclassifies an active directory workspace when git m
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const cwd = "/Users/moboudra/.paseo/worktrees/orchestrate/desktop-daemon-settings";
const repoRoot = "/Users/moboudra/dev/paseo";
const repoRoot = path.resolve("/Users/moboudra/dev/paseo");
const cwd = path.join(
path.resolve("/Users/moboudra"),
".paseo",
"worktrees",
"orchestrate",
"desktop-daemon-settings",
);
projects.set(
cwd,
@@ -2879,8 +2904,14 @@ test("open_project_request groups a plain git worktree under an existing repo pr
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const cwd = "/Users/moboudra/.paseo/worktrees/orchestrate/desktop-daemon-settings";
const repoRoot = "/Users/moboudra/dev/paseo";
const repoRoot = path.resolve("/Users/moboudra/dev/paseo");
const cwd = path.join(
path.resolve("/Users/moboudra"),
".paseo",
"worktrees",
"orchestrate",
"desktop-daemon-settings",
);
projects.set(
repoRoot,
@@ -2966,7 +2997,7 @@ test("open_project_request unarchives an existing archived workspace and project
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const cwd = "/tmp/repo";
const cwd = REPO_CWD;
projects.set(
cwd,
createPersistedProjectRecord({
@@ -3030,7 +3061,7 @@ test.skip("open_project_request collapses a git subdirectory onto the repo root
const session = createSessionForWorkspaceTests();
const projects = new Map<string, ReturnType<typeof createPersistedProjectRecord>>();
const workspaces = new Map<string, ReturnType<typeof createPersistedWorkspaceRecord>>();
const repoRoot = "/tmp/repo";
const repoRoot = REPO_CWD;
const subdir = "/tmp/repo/packages/app";
session.emit = (message) => {
@@ -3213,10 +3244,10 @@ test("open_in_editor_request launches the selected target", async () => {
type: "open_in_editor_request",
requestId: "req-open-editor",
editorId: "vscode",
path: "/tmp/repo",
path: REPO_CWD,
});
expect(calls).toEqual([{ editorId: "vscode", path: "/tmp/repo" }]);
expect(calls).toEqual([{ editorId: "vscode", path: REPO_CWD }]);
const response = emitted.find((message) => message.type === "open_in_editor_response") as
| { payload: Record<string, unknown> }
| undefined;
@@ -3229,7 +3260,7 @@ test("archive_workspace_request hides non-destructive workspace records", async
const workspace = createPersistedWorkspaceRecord({
workspaceId: "ws-repo-archive",
projectId: "proj-repo-archive",
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "directory",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3271,7 +3302,7 @@ test.skip("opening a new worktree reconciles older local workspaces into the rem
const localProjectId = mainWorkspaceId;
const remoteProjectId = "remote:github.com/zimakki/inkwell";
execSync(`mkdir -p ${JSON.stringify(worktreeWorkspaceId)}`);
mkdirSync(worktreeWorkspaceId, { recursive: true });
projects.set(
localProjectId,
@@ -3381,7 +3412,7 @@ test.skip("fetch_workspaces_request reconciles remote URL changes for existing w
const oldProjectId = "remote:github.com/old-owner/inkwell";
const newProjectId = "remote:github.com/new-owner/inkwell";
execSync(`mkdir -p ${JSON.stringify(worktreeWorkspaceId)}`);
mkdirSync(worktreeWorkspaceId, { recursive: true });
projects.set(
oldProjectId,
@@ -3476,7 +3507,7 @@ test.skip("reconcile archives stale subdirectory workspace records when collapsi
const subdirWorkspaceId = path.join(repoRoot, "packages", "app");
const projectId = "remote:github.com/acme/repo";
execSync(`mkdir -p ${JSON.stringify(subdirWorkspaceId)}`);
mkdirSync(subdirWorkspaceId, { recursive: true });
projects.set(
projectId,
@@ -3566,7 +3597,7 @@ test("listWorkspaceDescriptorsSnapshot keeps git workspaces on the baseline desc
const session = createSessionForWorkspaceTests();
const project = createPersistedProjectRecord({
projectId: "proj-baseline",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3575,7 +3606,7 @@ test("listWorkspaceDescriptorsSnapshot keeps git workspaces on the baseline desc
const workspace = createPersistedWorkspaceRecord({
workspaceId: "ws-baseline",
projectId: project.projectId,
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "main",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3627,7 +3658,7 @@ test("buildWorkspaceDescriptorMap stamps workspace archiving state", async () =>
const archivingAt = "2026-04-30T20:45:00.000Z";
const project = createPersistedProjectRecord({
projectId: "proj-archiving-map",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3669,7 +3700,7 @@ test("emitWorkspaceUpdatesForWorkspaceIds includes archiving state and dedupes u
const archivingAt = "2026-04-30T20:45:00.000Z";
const project = createPersistedProjectRecord({
projectId: "proj-archiving-emit",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3725,7 +3756,7 @@ test("emitWorkspaceUpdatesForWorkspaceIds includes archiving state and dedupes u
test("fetch_workspaces_response reads runtime fields from passive workspace git service snapshots", async () => {
const emitted: SessionOutboundMessage[] = [];
const runtimeSnapshot = createWorkspaceRuntimeSnapshot("/tmp/repo", {
const runtimeSnapshot = createWorkspaceRuntimeSnapshot(REPO_CWD, {
git: {
currentBranch: "runtime-branch",
isDirty: true,
@@ -3758,7 +3789,7 @@ test("fetch_workspaces_response reads runtime fields from passive workspace git
);
const project = createPersistedProjectRecord({
projectId: "proj-runtime-fetch",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3767,7 +3798,7 @@ test("fetch_workspaces_response reads runtime fields from passive workspace git
const workspace = createPersistedWorkspaceRecord({
workspaceId: "ws-runtime-fetch",
projectId: project.projectId,
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "main",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3803,7 +3834,7 @@ test("fetch_workspaces_response reads runtime fields from passive workspace git
| { type: "fetch_workspaces_response"; payload: Record<string, unknown> }
| undefined;
expect(peekSnapshotRuntimeFetch).toHaveBeenCalledWith("/tmp/repo");
expect(peekSnapshotRuntimeFetch).toHaveBeenCalledWith(REPO_CWD);
expect(response?.payload.entries).toEqual([
expect.objectContaining({
id: "ws-runtime-fetch",
@@ -3856,7 +3887,7 @@ test("fetch_workspaces_response emits before cold registration-triggered git wor
);
const project = createPersistedProjectRecord({
projectId: "proj-fetch-boundary",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3865,7 +3896,7 @@ test("fetch_workspaces_response emits before cold registration-triggered git wor
const workspace = createPersistedWorkspaceRecord({
workspaceId: "ws-fetch-boundary",
projectId: project.projectId,
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "main",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3895,7 +3926,7 @@ test("fetch_workspaces_response emits before cold registration-triggered git wor
test("workspace_update includes updated runtime fields", async () => {
const emitted: SessionOutboundMessage[] = [];
const runtimeSnapshot = createWorkspaceRuntimeSnapshot("/tmp/repo", {
const runtimeSnapshot = createWorkspaceRuntimeSnapshot(REPO_CWD, {
git: {
currentBranch: "feature/runtime-payloads",
isDirty: true,
@@ -3922,7 +3953,7 @@ test("workspace_update includes updated runtime fields", async () => {
);
const project = createPersistedProjectRecord({
projectId: "proj-runtime-update",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3931,7 +3962,7 @@ test("workspace_update includes updated runtime fields", async () => {
const workspace = createPersistedWorkspaceRecord({
workspaceId: "ws-runtime-update",
projectId: project.projectId,
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "main",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -3966,11 +3997,11 @@ test("workspace_update includes updated runtime fields", async () => {
},
});
await session.emitWorkspaceUpdateForCwd("/tmp/repo", {
await session.emitWorkspaceUpdateForCwd(REPO_CWD, {
skipReconcile: true,
});
expect(peekSnapshotRuntimeUpdate).toHaveBeenCalledWith("/tmp/repo");
expect(peekSnapshotRuntimeUpdate).toHaveBeenCalledWith(REPO_CWD);
expect(emitted).toContainEqual({
type: "workspace_update",
payload: {
@@ -3998,7 +4029,7 @@ test("subscribed fetch_workspaces includes git enrichment in the initial snapsho
const session = createSessionForWorkspaceTests();
const gitProject = createPersistedProjectRecord({
projectId: "proj-git-subscribe",
rootPath: "/tmp/repo",
rootPath: REPO_CWD,
kind: "git",
displayName: "repo",
createdAt: "2026-03-01T12:00:00.000Z",
@@ -4015,7 +4046,7 @@ test("subscribed fetch_workspaces includes git enrichment in the initial snapsho
const gitWorkspace = createPersistedWorkspaceRecord({
workspaceId: "ws-git-subscribe",
projectId: gitProject.projectId,
cwd: "/tmp/repo",
cwd: REPO_CWD,
kind: "local_checkout",
displayName: "main",
createdAt: "2026-03-01T12:00:00.000Z",