OrchestrationProjectShell declares workspaceFile, and the value is persisted correctly, but it never reaches the client. Every consumer that keys off it is therefore dead in practice:
Root cause
Two independent omissions in apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts, both needed:
- The three project SELECTs never select the column. They enumerate columns explicitly and
workspace_file is not among them, so row.workspaceFile is always undefined:
listProjectRows (feeds the snapshot at the two mapProjectShellRow call sites)
getActiveProjectRowByWorkspaceRoot
getActiveProjectRowById
mapProjectShellRow does not map the field even when present. It returns an explicit object literal listing every other column.
Because workspaceFile is Schema.optional on OrchestrationProjectShell, both omissions typecheck silently.
Worth noting the column is selected in apps/server/src/persistence/Layers/ProjectionProjects.ts:87,110, which is probably why this went unnoticed — that path just doesn't feed the client snapshot. ProjectionPipeline.ts:500 persists it correctly, and projector.ts:221,258 sets it on the server-side read model; only the client-facing read drops it.
Fix
Four lines, one file. Verified working locally on ff52c9fd:
@@ function mapProjectShellRow
id: row.projectId,
title: row.title,
workspaceRoot: row.workspaceRoot,
+ ...(row.workspaceFile ? { workspaceFile: row.workspaceFile } : {}),
repoRoots: normalizeRepoRoots(row),
and the same added line in each of the three SELECTs (listProjectRows, getActiveProjectRowByWorkspaceRoot, getActiveProjectRowById):
project_id AS "projectId",
title,
workspace_root AS "workspaceRoot",
+ workspace_file AS "workspaceFile",
repo_roots AS "repoRoots",
ProjectionProjectDbRowSchema derives from ProjectionProject and only overrides repoRoots/defaultModelSelection/scripts, so the field decodes without any schema change.
I deliberately left the two other projects.workspace_root selects alone — getThreadCheckpointContextThreadRow and getFullThreadDiffContextRow use different Result schemas and aren't part of the project shell.
Verification
Applied both halves on ff52c9fd, pnpm dev, reloaded the client:
- Open in VS Code now opens the multi-root workspace with all repo roots in the tree.
- The new sidebar shows the layers icon for the workspace project.
- "Manage folders…" appears and is enabled in the legacy sidebar's right-click menu.
tsgo --noEmit on apps/server reports no errors.
Also worth knowing: applying only the mapper half changes nothing, because the column isn't selected. That was my first attempt and it was a no-op — both halves are required.
Not opening a PR as I'm not familiar enough with this codebase to own the change, but happy to test any patch you push.
Version: multi-repo-workspaces @ ff52c9fd; also confirmed still missing on the current tip 646a9546. macOS arm64, dev build (pnpm dev).
OrchestrationProjectShelldeclaresworkspaceFile, and the value is persisted correctly, but it never reaches the client. Every consumer that keys off it is therefore dead in practice:.code-workspace.ChatView.tsxcomputesopenInWorkspaceFile = activeThread?.worktreePath ? null : (activeProject?.workspaceFile ?? null). With the field absent this is alwaysnull,OpenInPickeromits it from the RPC, andresolveEditorTargetfalls back toinput.cwd. So the "Open in VS Code" opens the workspace file's parent folder instead of the .code-workspace #112 fix is correct but never receives its input — the symptom "Open in VS Code" opens the workspace file's parent folder instead of the .code-workspace #112 describes still reproduces on currentmulti-repo-workspaces.Sidebar.logic.ts:329computesisWorkspace: Boolean(project.workspaceFile), always false.project.memberProjects.some((member) => member.workspaceFile)(LegacySidebar.tsx:1706-1713).Root cause
Two independent omissions in
apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts, both needed:workspace_fileis not among them, sorow.workspaceFileis alwaysundefined:listProjectRows(feeds the snapshot at the twomapProjectShellRowcall sites)getActiveProjectRowByWorkspaceRootgetActiveProjectRowByIdmapProjectShellRowdoes not map the field even when present. It returns an explicit object literal listing every other column.Because
workspaceFileisSchema.optionalonOrchestrationProjectShell, both omissions typecheck silently.Worth noting the column is selected in
apps/server/src/persistence/Layers/ProjectionProjects.ts:87,110, which is probably why this went unnoticed — that path just doesn't feed the client snapshot.ProjectionPipeline.ts:500persists it correctly, andprojector.ts:221,258sets it on the server-side read model; only the client-facing read drops it.Fix
Four lines, one file. Verified working locally on
ff52c9fd:@@ function mapProjectShellRow id: row.projectId, title: row.title, workspaceRoot: row.workspaceRoot, + ...(row.workspaceFile ? { workspaceFile: row.workspaceFile } : {}), repoRoots: normalizeRepoRoots(row),and the same added line in each of the three SELECTs (
listProjectRows,getActiveProjectRowByWorkspaceRoot,getActiveProjectRowById):project_id AS "projectId", title, workspace_root AS "workspaceRoot", + workspace_file AS "workspaceFile", repo_roots AS "repoRoots",ProjectionProjectDbRowSchemaderives fromProjectionProjectand only overridesrepoRoots/defaultModelSelection/scripts, so the field decodes without any schema change.I deliberately left the two other
projects.workspace_rootselects alone —getThreadCheckpointContextThreadRowandgetFullThreadDiffContextRowuse different Result schemas and aren't part of the project shell.Verification
Applied both halves on
ff52c9fd,pnpm dev, reloaded the client:tsgo --noEmitonapps/serverreports no errors.Also worth knowing: applying only the mapper half changes nothing, because the column isn't selected. That was my first attempt and it was a no-op — both halves are required.
Not opening a PR as I'm not familiar enough with this codebase to own the change, but happy to test any patch you push.
Version:
multi-repo-workspaces@ff52c9fd; also confirmed still missing on the current tip646a9546. macOS arm64, dev build (pnpm dev).