From 68ebb261f887b08febbd8e2b19ee2a90bc9256d4 Mon Sep 17 00:00:00 2001 From: Waishnav Date: Sun, 9 Aug 2026 20:21:01 +0530 Subject: [PATCH 1/3] refactor(server): make workspace reuse the default --- src/artifact-tools.ts | 4 +-- src/server.test.ts | 47 +++++++++++++++++++++++++++----- src/server.ts | 63 ++++++++++++++++++++++--------------------- 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/src/artifact-tools.ts b/src/artifact-tools.ts index 4734f095..fe9a195a 100644 --- a/src/artifact-tools.ts +++ b/src/artifact-tools.ts @@ -98,13 +98,13 @@ export function registerArtifactTools( { title: "Download attached or generated file", description: - "Stream one MCP-host-provided native file to a requested relative path inside an already-open workspace. Existing destinations, arbitrary URLs, absolute paths, traversal, symlinked parents, local source paths, and malformed file objects are rejected.", + "Stream one MCP-host-provided native file to a requested relative path inside a workspace. Existing destinations, arbitrary URLs, absolute paths, traversal, symlinked parents, source filesystem paths, and malformed file objects are rejected.", inputSchema: { file: openAIFileReferenceInputSchema.describe( "Native file value authorized and supplied by the MCP host.", ), workspaceId: z.string().min(1).describe( - "Workspace identifier returned by open_workspace.", + "Workspace to use. Reuse the current project's workspaceId.", ), path: z.string().min(1).describe( "Relative destination path inside the selected workspace. The destination must not already exist.", diff --git a/src/server.test.ts b/src/server.test.ts index c2f659d1..b8dac69d 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -16,6 +16,37 @@ import { WorkspaceRegistry } from "./workspaces.js"; const execFileAsync = promisify(execFile); +test("server and tools make workspace reuse the normal path", async (t) => { + const context = await fixture(t); + + assert.equal( + context.client.getServerVersion()?.description, + "Coding tools for project workspaces. Open each project or worktree once, then reuse its workspaceId.", + ); + assert.doesNotMatch(context.client.getServerVersion()?.description ?? "", /\blocal\b/i); + + const instructions = context.client.getInstructions(); + assert.ok(instructions); + assert.match(instructions, /During continued work in the same project or worktree, do not call open_workspace again/); + assert.match(instructions, /when the current workspaceId is rejected/); + + const tools = await context.client.listTools(); + const openTool = tools.tools.find((tool) => tool.name === "open_workspace"); + assert.ok(openTool?.description); + assert.match(openTool.description, /when no usable workspaceId exists/); + assert.match(openTool.description, /reuse the existing workspaceId instead of calling this tool again/); + assert.doesNotMatch(openTool.description, /\blocal\b/i); + + for (const tool of tools.tools.filter((candidate) => candidate.name !== "open_workspace")) { + const modelContract = JSON.stringify({ + description: tool.description, + inputSchema: tool.inputSchema, + }); + assert.doesNotMatch(modelContract, /Call open_workspace first/); + assert.doesNotMatch(modelContract, /Workspace identifier returned by open_workspace/); + } +}); + test("open_workspace keeps lifecycle flags out of model output and preserves complete card metadata", async (t) => { const context = await fixture(t); const first = await callOpen(context.client, context.project, "chat-1"); @@ -50,10 +81,12 @@ test("open_workspace keeps lifecycle flags out of model output and preserves com const repeatedText = responseText(repeated); assert.match(repeatedText, /Workspace already open as/); - assert.match(repeatedText, /same checkout previously opened/); - assert.match(repeatedText, /Reuse this workspaceId for subsequent tool calls/); - assert.match(repeatedText, /previously provided for this workspace/); - assert.match(repeatedText, /not repeated here/); + assert.match(repeatedText, /Continue with this workspaceId/); + assert.match(repeatedText, /already provided for this workspace/); + + const firstInstruction = structuredContent(first).instruction; + assert.ok(typeof firstInstruction === "string"); + assert.match(firstInstruction, /Keep reusing it while working in this project/); const card = responseCard(repeated); assert.equal(card.workspaceReused, true); @@ -104,7 +137,7 @@ test("new worktrees always receive a fresh workspace and complete worktree conte assert.match(responseText(result), /Opened isolated worktree workspace/); } assert.equal(structuredContent(checkoutAgain).agentsFiles, undefined); - assert.match(responseText(checkoutAgain), /same checkout previously opened/); + assert.match(responseText(checkoutAgain), /Continue with this workspaceId/); }); test("checkout opened after a worktree receives its own complete context", async (t) => { @@ -119,7 +152,7 @@ test("checkout opened after a worktree receives its own complete context", async assert.ok(Array.isArray(structuredContent(checkout).agentsFiles)); assert.equal(structuredContent(checkoutAgain).workspaceId, structuredContent(checkout).workspaceId); assert.equal(structuredContent(checkoutAgain).agentsFiles, undefined); - assert.match(responseText(checkoutAgain), /same checkout previously opened/); + assert.match(responseText(checkoutAgain), /Continue with this workspaceId/); }); test("a host without conversation metadata receives normal explicit-workspace behavior", async (t) => { @@ -171,7 +204,7 @@ test("checkout reuse and context suppression survive a registry restart", async const restored = await callOpen(restoredClient, context.project, "chat-1"); assert.equal(structuredContent(restored).workspaceId, firstWorkspaceId); assert.equal(structuredContent(restored).agentsFiles, undefined); - assert.match(responseText(restored), /same checkout previously opened/); + assert.match(responseText(restored), /Continue with this workspaceId/); } finally { await closeRestored(); } diff --git a/src/server.ts b/src/server.ts index 37ec4165..840594ab 100644 --- a/src/server.ts +++ b/src/server.ts @@ -175,6 +175,9 @@ const toolNames = { shell: "bash", } as const; +const workspaceIdDescription = + "Workspace to use. Reuse the current project's workspaceId."; + interface ToolLogFields { tool: string; workspaceId?: string; @@ -197,7 +200,7 @@ function serverInstructions(config: ServerConfig): string { : ""; if (config.toolMode === "codex") { - return `Use DevSpace as a local coding workspace. Call ${toolNames.openWorkspace} once per project folder or worktree and reuse its workspaceId. Open it again when the workspaceId is invalid, the project changes, checkout/worktree mode changes, or another isolated worktree is needed. Use ${toolNames.read} for direct file reads, apply_patch for all file modifications, exec_command for inspection, tests, builds, and other commands, and write_stdin to poll or interact with running processes. Follow instructions returned by ${toolNames.openWorkspace}; read applicable instruction and skill files before working in their scope.${artifactInstruction}${showChangesInstruction}`; + return `Use DevSpace for coding work. Call ${toolNames.openWorkspace} once for each project folder or isolated worktree, then keep using its workspaceId. During continued work in the same project or worktree, do not call ${toolNames.openWorkspace} again. Open another workspace only when changing projects, switching checkout/worktree mode, creating another isolated worktree, or when the current workspaceId is rejected. Use ${toolNames.read} for direct file reads, apply_patch for all file modifications, exec_command for inspection, tests, builds, and other commands, and write_stdin to poll or interact with running processes. Follow instructions returned by ${toolNames.openWorkspace}; read applicable instruction and skill files before working in their scope.${artifactInstruction}${showChangesInstruction}`; } const inspection = config.toolMode !== "full" @@ -210,7 +213,7 @@ function serverInstructions(config: ServerConfig): string { const agentsMd = `Follow instructions returned by ${toolNames.openWorkspace}. Before working under a path listed in availableAgentsFiles, use ${toolNames.read} to inspect that instruction file and follow it. `; - return `Use DevSpace as a local coding workspace. Call ${toolNames.openWorkspace} once per project folder or worktree to obtain a workspaceId. Reuse that same workspaceId for all later file, search, edit, write, show-changes, and shell tools in that folder; do not call ${toolNames.openWorkspace} again unless switching to a different project folder, changing checkout/worktree mode, the workspaceId is rejected as unknown, or a new isolated worktree is requested. ${agentsMd}${skills}${inspection}Prefer ${toolNames.edit} for targeted modifications, ${toolNames.write} only for new files or complete rewrites, and ${toolNames.shell} for tests, builds, git inspection, package scripts, and commands that are better executed by the shell. Do not create or modify files with ${toolNames.shell}; avoid shell redirection, heredocs, tee, sed -i, perl -i, node/python/ruby scripts, or any command whose purpose is to write project files.${artifactInstruction}${showChangesInstruction}`; + return `Use DevSpace for coding work. Call ${toolNames.openWorkspace} once for each project folder or isolated worktree, then keep using its workspaceId. During continued work in the same project or worktree, do not call ${toolNames.openWorkspace} again. Open another workspace only when changing projects, switching checkout/worktree mode, creating another isolated worktree, or when the current workspaceId is rejected. ${agentsMd}${skills}${inspection}Prefer ${toolNames.edit} for targeted modifications, ${toolNames.write} only for new files or complete rewrites, and ${toolNames.shell} for tests, builds, git inspection, package scripts, and commands that are better executed by the shell. Do not create or modify files with ${toolNames.shell}; avoid shell redirection, heredocs, tee, sed -i, perl -i, node/python/ruby scripts, or any command whose purpose is to write project files.${artifactInstruction}${showChangesInstruction}`; } function formatVisibleAgent(agent: { @@ -562,9 +565,9 @@ function registerCodexProcessTools( { title: "Execute command", description: - "Run a command inside an open workspace. Returns its result when it exits during the yield window, otherwise returns a sessionId for write_stdin. Use this for file inspection, tests, builds, package scripts, and long-running processes. Call open_workspace first and pass workspaceId.", + "Run a command in a workspace. Returns its result when it exits during the yield window, otherwise returns a sessionId for write_stdin. Use this for file inspection, tests, builds, package scripts, and long-running processes.", inputSchema: { - workspaceId: z.string().describe("Workspace identifier returned by open_workspace."), + workspaceId: z.string().describe(workspaceIdDescription), cmd: z.string().min(1).describe("Shell command to execute."), tty: z .boolean() @@ -708,7 +711,7 @@ export function createMcpServer( title: "DevSpace", version: "0.1.0", description: - "Secure local coding workspace for MCP clients. Provides workspace-scoped file, search, edit, write, and shell tools.", + "Coding tools for project workspaces. Open each project or worktree once, then reuse its workspaceId.", }, { instructions: serverInstructions(config), @@ -752,12 +755,12 @@ export function createMcpServer( { title: "Open workspace", description: - "Open a local project directory as a coding workspace. Call this once before working in a project or worktree, then reuse the returned workspaceId for later file, search, edit, show-changes, and shell calls. By default this opens the actual checkout; set mode=\"worktree\" when you need isolated or parallel work. Open another workspace when changing projects, switching modes, or starting another isolated worktree.", + "Start work in a project directory or isolated worktree when no usable workspaceId exists for it. During continued work, reuse the existing workspaceId instead of calling this tool again. By default this uses the actual checkout; set mode=\"worktree\" for isolated or parallel work.", inputSchema: { path: z .string() .describe( - "Absolute path, or a leading-tilde home path such as ~/project, to a local project directory inside an allowed root.", + "Absolute path, or a leading-tilde home path such as ~/project, to a project directory inside an allowed root.", ), mode: z .enum(["checkout", "worktree"]) @@ -844,16 +847,16 @@ export function createMcpServer( const loadedAgentsFiles = includeBootstrapContext ? cardAgentsFiles : []; const availableAgentsFileOutputs = includeBootstrapContext ? cardAvailableAgentsFiles : []; const cardInstruction = config.skillsEnabled - ? "Use this workspaceId in all subsequent tool calls for this project. Do not call open_workspace again for this same folder unless this workspaceId stops working, you switch to a different project folder or checkout/worktree mode, or the user requests a new isolated worktree. Follow loaded agentsFiles instructions. Before working under a path listed in availableAgentsFiles, read that instruction file. When a task matches an available skill in skills, read its path before proceeding." - : "Use this workspaceId in all subsequent tool calls for this project. Do not call open_workspace again for this same folder unless this workspaceId stops working, you switch to a different project folder or checkout/worktree mode, or the user requests a new isolated worktree. Follow loaded agentsFiles instructions. Before working under a path listed in availableAgentsFiles, read that instruction file."; + ? "Use this workspaceId for subsequent work in this project. Keep reusing it while working in this project. Follow loaded agentsFiles instructions. Before working under a path listed in availableAgentsFiles, read that instruction file. When a task matches an available skill in skills, read its path before proceeding." + : "Use this workspaceId for subsequent work in this project. Keep reusing it while working in this project. Follow loaded agentsFiles instructions. Before working under a path listed in availableAgentsFiles, read that instruction file."; const instruction = workspaceReused ? [ `Workspace already open as ${workspace.id}.`, - "Reuse this workspaceId for subsequent tool calls. This is the same checkout previously opened for this project in this conversation.", - "Continue following the project instructions, nested instruction files, skills, agent profiles, and diagnostics previously provided for this workspace. They remain the active workspace context and are not repeated here.", + "Continue with this workspaceId.", + "Keep following the project instructions, nested instruction files, skills, agent profiles, and diagnostics already provided for this workspace.", ].join("\n\n") : workspace.mode === "worktree" - ? "Use this workspaceId for subsequent tool calls. Follow the project instructions, nested instruction files, skills, agent profiles, and diagnostics returned for this isolated worktree." + ? "Use this workspaceId for subsequent work in this isolated worktree. Keep reusing it while working in this worktree. Follow the project instructions, nested instruction files, skills, agent profiles, and diagnostics returned for it." : cardInstruction; const resultContent: ToolContent[] = [ { @@ -954,7 +957,7 @@ export function createMcpServer( title: "Read file", description: [ - "Read a file inside an open workspace. Use this for file inspection instead of shell commands like cat or sed. Call open_workspace first and pass workspaceId.", + "Read a file in a workspace. Use this for file inspection instead of shell commands like cat or sed.", "Use this tool to inspect relevant AGENTS.md or CLAUDE.md files listed by open_workspace before working in nested directories.", config.skillsEnabled ? "If available skills were returned and a task matches one, read that skill's path before proceeding. Skill paths may be outside the workspace; only advertised SKILL.md files and files under already-loaded skill directories are readable." @@ -965,7 +968,7 @@ export function createMcpServer( inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), path: z .string() .describe( @@ -1051,11 +1054,11 @@ export function createMcpServer( { title: "Write file", description: - `Create or completely overwrite a file inside an open workspace. Prefer ${toolNames.edit} for targeted changes to existing files. Call open_workspace first and pass workspaceId.`, + `Create or completely overwrite a file in a workspace. Prefer ${toolNames.edit} for targeted changes to existing files.`, inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), path: z .string() .describe("File path to write, relative to the workspace root."), @@ -1125,11 +1128,11 @@ export function createMcpServer( { title: "Edit file", description: - `Edit one file inside an open workspace by replacing exact text blocks. Prefer this over ${toolNames.write} for targeted changes. Each oldText must match a unique, non-overlapping region of the original file; merge nearby changes into one edit and keep oldText as small as possible while still unique. Call open_workspace first and pass workspaceId.`, + `Edit one file in a workspace by replacing exact text blocks. Prefer this over ${toolNames.write} for targeted changes. Each oldText must match a unique, non-overlapping region of the original file; merge nearby changes into one edit and keep oldText as small as possible while still unique.`, inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), path: z .string() .describe("File path to edit, relative to the workspace root."), @@ -1217,11 +1220,11 @@ export function createMcpServer( { title: "Apply patch", description: - "Apply one Codex-style patch inside an open workspace. Supports adding, overwriting, updating, deleting, and moving files. Use this for all file modifications. Paths must be relative to the workspace. Call open_workspace first and pass workspaceId.", + "Apply one Codex-style patch in a workspace. Supports adding, overwriting, updating, deleting, and moving files. Use this for all file modifications. Paths must be relative to the workspace.", inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), patch: z .string() .describe("Patch text enclosed by *** Begin Patch and *** End Patch markers."), @@ -1296,7 +1299,7 @@ export function createMcpServer( inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), }, outputSchema: resultOutputSchema(), ...toolWidgetDescriptorMeta(config, "show_changes"), @@ -1347,11 +1350,11 @@ export function createMcpServer( { title: "Grep", description: - "Search file contents inside an open workspace. Use this before broad reads when looking for symbols, text, or usage sites. Respects project ignore rules. Call open_workspace first and pass workspaceId.", + "Search file contents in a workspace. Use this before broad reads when looking for symbols, text, or usage sites. Respects project ignore rules.", inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), pattern: z.string().describe("Search pattern."), path: z .string() @@ -1420,11 +1423,11 @@ export function createMcpServer( { title: "Glob", description: - "Find files by glob pattern inside an open workspace. Use this to discover filenames or narrow file sets before reading. Respects project ignore rules. Call open_workspace first and pass workspaceId.", + "Find files by glob pattern in a workspace. Use this to discover filenames or narrow file sets before reading. Respects project ignore rules.", inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), pattern: z.string().describe("File glob pattern."), path: z .string() @@ -1490,11 +1493,11 @@ export function createMcpServer( { title: "Ls", description: - "List a directory inside an open workspace. Use this for directory inspection before reading files. Call open_workspace first and pass workspaceId.", + "List a directory in a workspace. Use this for directory inspection before reading files.", inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), path: z .string() .describe( @@ -1558,12 +1561,12 @@ export function createMcpServer( { title: "Bash", description: config.toolMode !== "full" - ? `Run a shell command inside an open workspace. Use only for tests, builds, git inspection, package scripts, search, file discovery, and directory inspection. In minimal tool mode, ${toolNames.grep}, ${toolNames.glob}, and ${toolNames.ls} are disabled; use command-line tools such as grep, rg, find, ls, and tree for those read-only inspection actions. Do not use ${toolNames.shell} to create or modify files. Do not use shell redirection, heredocs, tee, sed -i, perl -i, node/python/ruby scripts, or generated scripts to write project files; use ${toolNames.edit} for targeted changes and ${toolNames.write} for new files or full rewrites. Prefer ${toolNames.read} for direct file reads. Call open_workspace first and pass workspaceId. This is powerful local execution and should only be exposed behind strong authentication.` - : `Run a shell command inside an open workspace. Use only for tests, builds, git inspection, package scripts, and commands that are better executed by the shell. Do not use ${toolNames.shell} to create or modify files. Do not use shell redirection, heredocs, tee, sed -i, perl -i, node/python/ruby scripts, or generated scripts to write project files; use ${toolNames.edit} for targeted changes and ${toolNames.write} for new files or full rewrites. Prefer ${toolNames.read}, ${toolNames.grep}, ${toolNames.glob}, and ${toolNames.ls} for file inspection. Call open_workspace first and pass workspaceId. This is powerful local execution and should only be exposed behind strong authentication.`, + ? `Run a shell command in a workspace. Use only for tests, builds, git inspection, package scripts, search, file discovery, and directory inspection. In minimal tool mode, ${toolNames.grep}, ${toolNames.glob}, and ${toolNames.ls} are disabled; use command-line tools such as grep, rg, find, ls, and tree for those read-only inspection actions. Do not use ${toolNames.shell} to create or modify files. Do not use shell redirection, heredocs, tee, sed -i, perl -i, node/python/ruby scripts, or generated scripts to write project files; use ${toolNames.edit} for targeted changes and ${toolNames.write} for new files or full rewrites. Prefer ${toolNames.read} for direct file reads. This is powerful execution and should only be exposed behind strong authentication.` + : `Run a shell command in a workspace. Use only for tests, builds, git inspection, package scripts, and commands that are better executed by the shell. Do not use ${toolNames.shell} to create or modify files. Do not use shell redirection, heredocs, tee, sed -i, perl -i, node/python/ruby scripts, or generated scripts to write project files; use ${toolNames.edit} for targeted changes and ${toolNames.write} for new files or full rewrites. Prefer ${toolNames.read}, ${toolNames.grep}, ${toolNames.glob}, and ${toolNames.ls} for file inspection. This is powerful execution and should only be exposed behind strong authentication.`, inputSchema: { workspaceId: z .string() - .describe("Workspace identifier returned by open_workspace."), + .describe(workspaceIdDescription), command: z .string() .describe( From c08c57a6b833b8e05563ea864317b5d7c68d9fab Mon Sep 17 00:00:00 2001 From: Waishnav Date: Sun, 9 Aug 2026 20:21:01 +0530 Subject: [PATCH 2/3] fix(workspace): make unknown id recovery actionable --- src/workspaces.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/workspaces.ts b/src/workspaces.ts index 05c8b9d2..30762648 100644 --- a/src/workspaces.ts +++ b/src/workspaces.ts @@ -251,7 +251,9 @@ export class WorkspaceRegistry { const session = this.store?.getSession(workspaceId); if (!session) { - throw new Error(`Unknown workspaceId: ${workspaceId}. Call open_workspace first.`); + throw new Error( + `Unknown workspaceId: ${workspaceId}. Open the target project or worktree again and continue with the new workspaceId.`, + ); } const root = this.assertWorkspaceRootAllowed(session.root, session.mode, session.sourceRoot); From 37ecf5cb5bdbf438e0d23b94eca6823e62ac79f5 Mon Sep 17 00:00:00 2001 From: Waishnav Date: Sun, 9 Aug 2026 20:35:30 +0530 Subject: [PATCH 3/3] test(server): drop prompt copy assertions --- src/server.test.ts | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/server.test.ts b/src/server.test.ts index b8dac69d..73eaf03b 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -16,37 +16,6 @@ import { WorkspaceRegistry } from "./workspaces.js"; const execFileAsync = promisify(execFile); -test("server and tools make workspace reuse the normal path", async (t) => { - const context = await fixture(t); - - assert.equal( - context.client.getServerVersion()?.description, - "Coding tools for project workspaces. Open each project or worktree once, then reuse its workspaceId.", - ); - assert.doesNotMatch(context.client.getServerVersion()?.description ?? "", /\blocal\b/i); - - const instructions = context.client.getInstructions(); - assert.ok(instructions); - assert.match(instructions, /During continued work in the same project or worktree, do not call open_workspace again/); - assert.match(instructions, /when the current workspaceId is rejected/); - - const tools = await context.client.listTools(); - const openTool = tools.tools.find((tool) => tool.name === "open_workspace"); - assert.ok(openTool?.description); - assert.match(openTool.description, /when no usable workspaceId exists/); - assert.match(openTool.description, /reuse the existing workspaceId instead of calling this tool again/); - assert.doesNotMatch(openTool.description, /\blocal\b/i); - - for (const tool of tools.tools.filter((candidate) => candidate.name !== "open_workspace")) { - const modelContract = JSON.stringify({ - description: tool.description, - inputSchema: tool.inputSchema, - }); - assert.doesNotMatch(modelContract, /Call open_workspace first/); - assert.doesNotMatch(modelContract, /Workspace identifier returned by open_workspace/); - } -}); - test("open_workspace keeps lifecycle flags out of model output and preserves complete card metadata", async (t) => { const context = await fixture(t); const first = await callOpen(context.client, context.project, "chat-1"); @@ -79,15 +48,6 @@ test("open_workspace keeps lifecycle flags out of model output and preserves com assert.equal("workspaceReused" in repeatedStructured, false); assert.equal("includeBootstrapContext" in repeatedStructured, false); - const repeatedText = responseText(repeated); - assert.match(repeatedText, /Workspace already open as/); - assert.match(repeatedText, /Continue with this workspaceId/); - assert.match(repeatedText, /already provided for this workspace/); - - const firstInstruction = structuredContent(first).instruction; - assert.ok(typeof firstInstruction === "string"); - assert.match(firstInstruction, /Keep reusing it while working in this project/); - const card = responseCard(repeated); assert.equal(card.workspaceReused, true); assert.equal(card.includeBootstrapContext, false); @@ -137,7 +97,6 @@ test("new worktrees always receive a fresh workspace and complete worktree conte assert.match(responseText(result), /Opened isolated worktree workspace/); } assert.equal(structuredContent(checkoutAgain).agentsFiles, undefined); - assert.match(responseText(checkoutAgain), /Continue with this workspaceId/); }); test("checkout opened after a worktree receives its own complete context", async (t) => { @@ -152,7 +111,6 @@ test("checkout opened after a worktree receives its own complete context", async assert.ok(Array.isArray(structuredContent(checkout).agentsFiles)); assert.equal(structuredContent(checkoutAgain).workspaceId, structuredContent(checkout).workspaceId); assert.equal(structuredContent(checkoutAgain).agentsFiles, undefined); - assert.match(responseText(checkoutAgain), /Continue with this workspaceId/); }); test("a host without conversation metadata receives normal explicit-workspace behavior", async (t) => { @@ -204,7 +162,6 @@ test("checkout reuse and context suppression survive a registry restart", async const restored = await callOpen(restoredClient, context.project, "chat-1"); assert.equal(structuredContent(restored).workspaceId, firstWorkspaceId); assert.equal(structuredContent(restored).agentsFiles, undefined); - assert.match(responseText(restored), /Continue with this workspaceId/); } finally { await closeRestored(); }