Compare commits

...

2 Commits

Author SHA1 Message Date
Mohamed Boudra
5eedc8b056 test(server): cover home directory prefix match in workspace resolution
Locks down the fix from e92f0847 so prefix matching never swallows a
child path under the user's home workspace.
2026-04-27 19:26:57 +07:00
hissincn
e92f084727 fix(server): skip home directory in workspace prefix matching
When resolving a workspace for a given cwd, the prefix matching loop
would match the user's home directory (~) as a prefix for any path
under it. This caused new projects created under the home directory
to be incorrectly associated with the home workspace instead of
getting their own independent workspace.

Added a check to skip the home directory (homedir()) during prefix
matching. Exact matches for the home directory still work fine.

Fixes #BUG

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:54:55 +08:00
2 changed files with 25 additions and 1 deletions

View File

@@ -6010,8 +6010,10 @@ export class Session {
return exact.workspaceId;
}
const userHome = homedir();
let bestMatch: PersistedWorkspaceRecord | null = null;
for (const workspace of workspaces) {
if (workspace.cwd === userHome) continue;
const prefix = workspace.cwd.endsWith(sep) ? workspace.cwd : `${workspace.cwd}${sep}`;
if (!normalizedCwd.startsWith(prefix)) {
continue;

View File

@@ -1,6 +1,6 @@
import { execSync } from "node:child_process";
import { mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { homedir, tmpdir } from "node:os";
import path from "node:path";
import { expect, test, vi } from "vitest";
import { Session } from "./session.js";
@@ -47,6 +47,10 @@ interface SessionTestAccess {
getAgentPayloadById(agentId: string): Promise<unknown>;
buildProjectPlacementForCwd(cwd: string): Promise<unknown>;
buildProjectPlacement(cwd: string): Promise<unknown>;
resolveRegisteredWorkspaceIdForCwd(
cwd: string,
workspaces: ReturnType<typeof createPersistedWorkspaceRecord>[],
): string;
buildWorkspaceDescriptorMap(...args: unknown[]): Promise<Map<string, unknown>>;
describeWorkspaceRecord(...args: unknown[]): Promise<unknown>;
describeWorkspaceRecordWithGitData(...args: unknown[]): Promise<unknown>;
@@ -3042,3 +3046,21 @@ test("subscribed fetch_workspaces includes git enrichment in the initial snapsho
expect(workspaceUpdates).toEqual([]);
expect(session.describeWorkspaceRecordWithGitData).toHaveBeenCalledWith(gitWorkspace, gitProject);
});
test("resolveRegisteredWorkspaceIdForCwd does not match home directory as a prefix", () => {
const session = createSessionForWorkspaceTests();
const home = homedir();
const childCwd = path.join(home, "projects/new-app");
const homeWorkspace = createPersistedWorkspaceRecord({
workspaceId: home,
projectId: "proj-home",
cwd: home,
kind: "directory",
displayName: "home",
createdAt: "2026-03-01T12:00:00.000Z",
updatedAt: "2026-03-01T12:00:00.000Z",
});
expect(session.resolveRegisteredWorkspaceIdForCwd(childCwd, [homeWorkspace])).toBe(childCwd);
expect(session.resolveRegisteredWorkspaceIdForCwd(home, [homeWorkspace])).toBe(home);
});