diff --git a/README.md b/README.md index d848731..9a46f4d 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ The recommended project override path is `.opencode/kompass.jsonc`. ## Kompass Navigator -Navigator is an OpenCode capability for orchestrating native sessions in the current checkout and OpenCode-managed Git worktrees. It is enabled by default, follows OpenCode Desktop's protocol detection so session creation, prompts, reads, status, and interrupts stay on one compatible API, returns immediately after admitting prompts, and supports parallel sessions. Until OpenCode implements V2 wait, Navigator waits by polling the active-session API locally. It requires OpenCode `1.17.12` or newer. +Navigator is an OpenCode capability for explicitly requested orchestration of native sessions in the current checkout and OpenCode-managed Git worktrees. It is not a subagent mechanism; ordinary delegation should use OpenCode's built-in `task` tool. Navigator is enabled by default, follows OpenCode Desktop's protocol detection so session creation, prompts, reads, status, and interrupts stay on one compatible API, returns immediately after admitting prompts, and supports parallel sessions. Until OpenCode implements V2 wait, Navigator waits by polling the active-session API locally. It requires OpenCode `1.17.12` or newer. Configure Navigator and its limits with: @@ -78,7 +78,7 @@ The default runtime names are `kompass_worktree_list`, `kompass_session_create`, Set `adapters.opencode.navigator.enabled` to `false` to disable all Navigator tools. -Navigator accepts only sessions from the current OpenCode project and only worktrees returned by OpenCode. It rejects self-targeting lifecycle calls, arbitrary directories, main-checkout removal, unmanaged worktrees, and removal while a worktree has active sessions. `session_send` can switch the target session's agent or model before admitting a steered prompt when the detected OpenCode protocol supports it. `session_wait` defaults to `maxWaitMs`, caps requested timeouts at `maxWaitMs`, and treats `timeoutMs: 0` as an immediate snapshot. Navigator never force-removes or automatically cleans up resources after a partial failure. +Navigator accepts only sessions from the current OpenCode project and only worktrees returned by OpenCode. New sessions inherit the calling session's agent, model, and variant unless explicitly overridden. It rejects self-targeting lifecycle calls, arbitrary directories, unknown V2 agent overrides, main-checkout removal, unmanaged worktrees, and removal while a worktree has active sessions. `session_send` can switch the target session's agent or model before admitting a steered prompt when the detected OpenCode protocol supports it. `session_wait` defaults to `maxWaitMs`, caps requested timeouts at `maxWaitMs`, and treats `timeoutMs: 0` as an immediate snapshot. Navigator never force-removes or automatically cleans up resources after a partial failure. When OpenCode exposes experimental workspace adapters, Kompass registers a `rift` workspace adapter backed by its bundled `rift-snapshot` dependency. Navigator automatically uses that adapter for `new_worktree` sessions when no `startCommand` is requested, falling back to Git worktrees otherwise. diff --git a/packages/opencode/README.md b/packages/opencode/README.md index d848731..9a46f4d 100644 --- a/packages/opencode/README.md +++ b/packages/opencode/README.md @@ -54,7 +54,7 @@ The recommended project override path is `.opencode/kompass.jsonc`. ## Kompass Navigator -Navigator is an OpenCode capability for orchestrating native sessions in the current checkout and OpenCode-managed Git worktrees. It is enabled by default, follows OpenCode Desktop's protocol detection so session creation, prompts, reads, status, and interrupts stay on one compatible API, returns immediately after admitting prompts, and supports parallel sessions. Until OpenCode implements V2 wait, Navigator waits by polling the active-session API locally. It requires OpenCode `1.17.12` or newer. +Navigator is an OpenCode capability for explicitly requested orchestration of native sessions in the current checkout and OpenCode-managed Git worktrees. It is not a subagent mechanism; ordinary delegation should use OpenCode's built-in `task` tool. Navigator is enabled by default, follows OpenCode Desktop's protocol detection so session creation, prompts, reads, status, and interrupts stay on one compatible API, returns immediately after admitting prompts, and supports parallel sessions. Until OpenCode implements V2 wait, Navigator waits by polling the active-session API locally. It requires OpenCode `1.17.12` or newer. Configure Navigator and its limits with: @@ -78,7 +78,7 @@ The default runtime names are `kompass_worktree_list`, `kompass_session_create`, Set `adapters.opencode.navigator.enabled` to `false` to disable all Navigator tools. -Navigator accepts only sessions from the current OpenCode project and only worktrees returned by OpenCode. It rejects self-targeting lifecycle calls, arbitrary directories, main-checkout removal, unmanaged worktrees, and removal while a worktree has active sessions. `session_send` can switch the target session's agent or model before admitting a steered prompt when the detected OpenCode protocol supports it. `session_wait` defaults to `maxWaitMs`, caps requested timeouts at `maxWaitMs`, and treats `timeoutMs: 0` as an immediate snapshot. Navigator never force-removes or automatically cleans up resources after a partial failure. +Navigator accepts only sessions from the current OpenCode project and only worktrees returned by OpenCode. New sessions inherit the calling session's agent, model, and variant unless explicitly overridden. It rejects self-targeting lifecycle calls, arbitrary directories, unknown V2 agent overrides, main-checkout removal, unmanaged worktrees, and removal while a worktree has active sessions. `session_send` can switch the target session's agent or model before admitting a steered prompt when the detected OpenCode protocol supports it. `session_wait` defaults to `maxWaitMs`, caps requested timeouts at `maxWaitMs`, and treats `timeoutMs: 0` as an immediate snapshot. Navigator never force-removes or automatically cleans up resources after a partial failure. When OpenCode exposes experimental workspace adapters, Kompass registers a `rift` workspace adapter backed by its bundled `rift-snapshot` dependency. Navigator automatically uses that adapter for `new_worktree` sessions when no `startCommand` is requested, falling back to Git worktrees otherwise. diff --git a/packages/opencode/navigator.ts b/packages/opencode/navigator.ts index 28d37ef..9e04a42 100644 --- a/packages/opencode/navigator.ts +++ b/packages/opencode/navigator.ts @@ -89,6 +89,8 @@ type NavigatorContext = { type NativeWorktree = { directory: string; name: string; branch?: string; id?: string; type: "worktree" | "rift" }; +const explicitNavigatorUse = "Use only when the user explicitly asks to create or manage native OpenCode sessions, worktrees, or a multi-session workflow. Do not use for subagent delegation; use the built-in task tool instead."; + function failResponse(error: unknown, operation: string): never { const message = error instanceof Error ? error.message @@ -108,6 +110,15 @@ function envelopeData(response: { data?: { data: T }; error?: unknown }, oper return responseData(response, operation).data; } +async function assertKnownV2Agent(client: NavigatorClient, directory: string, agent: string) { + const agents = envelopeData>( + await client.v2.agent.list({ location: { directory } }), + "OpenCode agent list", + ); + if (agents.some((item) => item.id === agent)) return; + throw new Error(`Unknown OpenCode agent "${agent}". Available agents: ${agents.map((item) => item.id).join(", ")}`); +} + function normalizeDirectory(directory: string) { return path.resolve(directory); } @@ -471,7 +482,7 @@ export function createNavigatorTools( const { client, ...navigator } = input; return { worktree_list: tool({ - description: "List the current OpenCode project checkout and its managed native worktrees.", + description: `${explicitNavigatorUse} List the current OpenCode project checkout and its managed native worktrees.`, args: {}, async execute() { return json({ @@ -482,7 +493,7 @@ export function createNavigatorTools( }), session_create: tool({ - description: "Create and asynchronously prompt a native OpenCode session in the checkout or a managed worktree.", + description: `${explicitNavigatorUse} Create and asynchronously prompt a native OpenCode session in the checkout or a managed worktree.`, args: { prompt: tool.schema.string().min(1), environment: tool.schema.discriminatedUnion("type", [ @@ -501,9 +512,10 @@ export function createNavigatorTools( model: tool.schema.object({ providerID: tool.schema.string().min(1), modelID: tool.schema.string().min(1), + variant: tool.schema.string().min(1).optional(), }).optional(), }, - async execute(args) { + async execute(args, context) { const active = await activeSessionIDs(client, navigator); const activeSessions = await Promise.all([...active].map((sessionID) => getSession(client, sessionID))); const activeOwnedCount = activeSessions.filter((session) => session.projectID === navigator.projectID).length; @@ -511,6 +523,20 @@ export function createNavigatorTools( throw new Error(`Navigator allows at most ${navigator.config.maxConcurrentSessions} concurrent sessions`); } + const caller = await getOwnedSession(client, navigator.projectID, context.sessionID).catch(() => undefined); + const selectedAgent = args.agent ?? caller?.agent; + const selectedModel = args.model ?? (caller?.model + ? { + providerID: caller.model.providerID, + modelID: caller.model.id, + ...(caller.model.variant ? { variant: caller.model.variant } : {}), + } + : undefined); + + if (navigator.protocol === "v2" && selectedAgent) { + await assertKnownV2Agent(client, navigator.checkout, selectedAgent); + } + let directory = navigator.checkout; let createdWorktree: NativeWorktree | undefined; if (args.environment.type === "existing_worktree") { @@ -567,8 +593,16 @@ export function createNavigatorTools( ) as { id: string; projectID: string } : envelopeData( await client.v2.session.create({ - ...(args.agent ? { agent: args.agent } : {}), - ...(args.model ? { model: { providerID: args.model.providerID, id: args.model.modelID } } : {}), + ...(selectedAgent ? { agent: selectedAgent } : {}), + ...(selectedModel + ? { + model: { + providerID: selectedModel.providerID, + id: selectedModel.modelID, + ...(selectedModel.variant ? { variant: selectedModel.variant } : {}), + }, + } + : {}), location: { directory }, }), "OpenCode session create", @@ -589,8 +623,13 @@ export function createNavigatorTools( path: { id: session.id }, body: { parts: [{ type: "text", text: args.prompt }], - ...(args.agent ? { agent: args.agent } : {}), - ...(args.model ? { model: args.model } : {}), + ...(selectedAgent ? { agent: selectedAgent } : {}), + ...(selectedModel + ? { + model: { providerID: selectedModel.providerID, modelID: selectedModel.modelID }, + ...(selectedModel.variant ? { variant: selectedModel.variant } : {}), + } + : {}), }, }); if (response.error !== undefined) failResponse(response.error, `OpenCode prompt admission for session ${session.id}`); @@ -622,7 +661,7 @@ export function createNavigatorTools( }), session_list: tool({ - description: "List native OpenCode sessions owned by the current project.", + description: `${explicitNavigatorUse} List native OpenCode sessions owned by the current project.`, args: { directory: tool.schema.string().optional(), search: tool.schema.string().optional(), @@ -655,7 +694,7 @@ export function createNavigatorTools( }), session_read: tool({ - description: "Read a bounded page of recent messages from a current-project OpenCode session.", + description: `${explicitNavigatorUse} Read a bounded page of recent messages from a current-project OpenCode session.`, args: { sessionID: tool.schema.string().min(1), cursor: tool.schema.string().optional(), @@ -669,7 +708,7 @@ export function createNavigatorTools( }), session_send: tool({ - description: "Steer a prompt for an existing current-project OpenCode session, optionally switching agent or model first.", + description: `${explicitNavigatorUse} Steer a prompt for an existing current-project OpenCode session, optionally switching agent or model first.`, args: { sessionID: tool.schema.string().min(1), prompt: tool.schema.string().min(1), @@ -695,6 +734,7 @@ export function createNavigatorTools( return json({ sessionID: args.sessionID, admitted: true }); } if (args.agent) { + await assertKnownV2Agent(client, session.location.directory, args.agent); const response = await client.v2.session.switchAgent({ sessionID: args.sessionID, agent: args.agent, @@ -718,7 +758,7 @@ export function createNavigatorTools( }), session_wait: tool({ - description: "Wait for the first of one to eight current-project OpenCode sessions to become idle.", + description: `${explicitNavigatorUse} Wait for the first of one to eight current-project OpenCode sessions to become idle.`, args: { targets: tool.schema.array(tool.schema.object({ sessionID: tool.schema.string().min(1) })).min(1).max(8), timeoutMs: tool.schema.number().int().nonnegative().optional(), @@ -762,7 +802,7 @@ export function createNavigatorTools( }), session_interrupt: tool({ - description: "Interrupt active execution in a current-project OpenCode session.", + description: `${explicitNavigatorUse} Interrupt active execution in a current-project OpenCode session.`, args: { sessionID: tool.schema.string().min(1) }, async execute(args, context) { assertNotCallingSession(args.sessionID, context, "interrupt"); @@ -776,7 +816,7 @@ export function createNavigatorTools( }), worktree_remove: tool({ - description: "Remove an idle managed OpenCode worktree from the current project without force.", + description: `${explicitNavigatorUse} Remove an idle managed OpenCode worktree from the current project without force.`, args: { directory: tool.schema.string().min(1) }, async execute(args) { if (sameDirectory(args.directory, navigator.checkout)) { @@ -852,7 +892,9 @@ export async function getNavigatorCompatibilityWarning( protocol: NavigatorProtocol, legacyClient?: NavigatorLegacyClient, ) { - const v2Metadata = hasMethods(client.worktree, ["list"]) && hasMethods(client.v2?.session, ["list", "get"]); + const v2Metadata = hasMethods(client.worktree, ["list"]) + && hasMethods(client.v2?.agent, ["list"]) + && hasMethods(client.v2?.session, ["list", "get"]); const compatible = protocol === "v1" ? v2Metadata && hasMethods(legacyClient?.session, ["create", "promptAsync", "status", "messages", "abort"]) : v2Metadata && hasMethods(client.v2.session, ["create", "messages", "prompt", "switchAgent", "switchModel", "active", "interrupt"]); diff --git a/packages/opencode/test/navigator.test.ts b/packages/opencode/test/navigator.test.ts index f3817de..10b2940 100644 --- a/packages/opencode/test/navigator.test.ts +++ b/packages/opencode/test/navigator.test.ts @@ -34,6 +34,9 @@ function createClient(overrides: Record = {}) { remove: async () => response(true), }, v2: { + agent: { + list: async () => response({ location: { directory: "/repo" }, data: [{ id: "build" }, { id: "reviewer" }, { id: "worker" }] }), + }, session: { active: async () => response({ data: {} }), get: async ({ sessionID }: { sessionID: string }) => response({ @@ -59,6 +62,7 @@ function createClient(overrides: Record = {}) { }; for (const [key, value] of Object.entries(overrides)) { if (key === "worktree") Object.assign(client.worktree, value); + else if (key === "agent") Object.assign(client.v2.agent, value); else if (key === "session") Object.assign(client.v2.session, value); else if (key === "legacySession") Object.assign(client.session, value); else client[key] = value; @@ -82,6 +86,14 @@ function context(sessionID = "caller", abort = new AbortController().signal) { } describe("Kompass Navigator", () => { + test("reserves Navigator tools for explicit native-session workflows", () => { + for (const definition of Object.values(tools())) { + assert.match(definition.description, /explicitly asks/); + assert.match(definition.description, /Do not use for subagent delegation/); + assert.match(definition.description, /built-in task tool/); + } + }); + test("matches Desktop protocol detection", async () => { const legacy = createClient({ global: { health: async () => response({ healthy: true }) }, @@ -172,6 +184,58 @@ describe("Kompass Navigator", () => { assert.equal(prompts[0].prompt.text, "implement it"); }); + test("inherits the calling session agent, model, and variant", async () => { + const creates: any[] = []; + const client = createClient({ + session: { + get: async ({ sessionID }: { sessionID: string }) => response({ + data: { + ...session(sessionID), + agent: "reviewer", + model: { providerID: "openai", id: "gpt-5.6-sol", variant: "xhigh" }, + }, + }), + create: async (args: any) => { + creates.push(args); + return response({ data: session("created", args.location.directory) }); + }, + }, + }); + + await (tools(client).session_create as any).execute({ + prompt: "review it", + environment: { type: "checkout" }, + }, context()); + + assert.equal(creates[0].agent, "reviewer"); + assert.deepEqual(creates[0].model, { + providerID: "openai", + id: "gpt-5.6-sol", + variant: "xhigh", + }); + }); + + test("rejects an unknown V2 agent before creating a worktree or session", async () => { + let worktreeCreates = 0; + let sessionCreates = 0; + const client = createClient({ + agent: { list: async () => response({ location: { directory: "/repo" }, data: [{ id: "reviewer" }] }) }, + worktree: { create: async () => { worktreeCreates += 1; return response({ directory: "/repo-new", name: "new" }); } }, + session: { create: async () => { sessionCreates += 1; return response({ data: session("created") }); } }, + }); + + await assert.rejects( + (tools(client).session_create as any).execute({ + prompt: "review it", + agent: "review", + environment: { type: "new_worktree" }, + }, context()), + /Unknown OpenCode agent "review".*reviewer/, + ); + assert.equal(worktreeCreates, 0); + assert.equal(sessionCreates, 0); + }); + test("uses one legacy transcript path when Desktop selects V1", async () => { const prompts: any[] = []; const client = createClient({ @@ -602,6 +666,13 @@ describe("Kompass Navigator", () => { }); test("reports incompatible OpenCode runtime versions", async () => { + const missingAgentList = createClient(); + delete missingAgentList.v2.agent.list; + assert.match( + await getNavigatorCompatibilityWarning(missingAgentList as never, "v2") ?? "", + /requires OpenCode 1\.17\.12 or newer/, + ); + const client = createClient({ global: { health: async () => response({ version: "1.17.11" }) }, }); diff --git a/packages/opencode/test/tool-registration.test.ts b/packages/opencode/test/tool-registration.test.ts index 62d733c..19751bb 100644 --- a/packages/opencode/test/tool-registration.test.ts +++ b/packages/opencode/test/tool-registration.test.ts @@ -225,7 +225,7 @@ describe("createOpenCodeTools", () => { await mkdir(path.join(tempDir, ".opencode"), { recursive: true }); await writeFile(path.join(tempDir, ".opencode", "kompass.jsonc"), `{ "tools": { - "session_create": { "name": "delegate_session" }, + "session_create": { "name": "start_workflow_session" }, "session_interrupt": { "enabled": false } } }`); @@ -243,7 +243,7 @@ describe("createOpenCodeTools", () => { }); assert.ok(tools.kompass_worktree_list); - assert.ok(tools.delegate_session); + assert.ok(tools.start_workflow_session); assert.ok(tools.kompass_session_list); assert.ok(tools.kompass_session_read); assert.ok(tools.kompass_session_send); diff --git a/packages/web/src/content/docs/docs/adapters/opencode.mdx b/packages/web/src/content/docs/docs/adapters/opencode.mdx index 04bb31c..74597aa 100644 --- a/packages/web/src/content/docs/docs/adapters/opencode.mdx +++ b/packages/web/src/content/docs/docs/adapters/opencode.mdx @@ -33,7 +33,7 @@ You can use overrides to: ## Kompass Navigator -Navigator follows OpenCode Desktop's protocol detection so session creation, prompts, reads, status, and interrupts stay on the same compatible API in the current checkout or managed Git worktrees. Until OpenCode implements V2 wait, Navigator waits by polling the active-session API locally. It requires OpenCode `1.17.12` or newer and is enabled by default. +Navigator is for explicitly requested native-session and managed-worktree workflows. It is not a subagent mechanism; ordinary delegation should use OpenCode's built-in `task` tool. Navigator follows OpenCode Desktop's protocol detection so session creation, prompts, reads, status, and interrupts stay on the same compatible API in the current checkout or managed Git worktrees. Until OpenCode implements V2 wait, Navigator waits by polling the active-session API locally. It requires OpenCode `1.17.12` or newer and is enabled by default. ```jsonc { @@ -50,14 +50,14 @@ Navigator follows OpenCode Desktop's protocol detection so session creation, pro }, "tools": { "session_interrupt": { "enabled": false }, - "session_create": { "name": "delegate_session" } + "session_create": { "name": "start_workflow_session" } } } ``` -Navigator registers all eight logical tools unless the feature or an individual tool is disabled. Default names receive the `kompass_` prefix; configured aliases such as `delegate_session` are registered exactly. +Navigator registers all eight logical tools unless the feature or an individual tool is disabled. Default names receive the `kompass_` prefix; configured aliases such as `start_workflow_session` are registered exactly. -Navigator is scoped to the current project. Session IDs are ownership-checked, directories must be native managed worktrees, and lifecycle calls cannot target the calling session. `session_send` can switch the target session's agent or model before admitting a steered prompt. Waits default to `maxWaitMs`, cap requested timeouts at `maxWaitMs`, and use `timeoutMs: 0` for an immediate snapshot. Removal rejects the checkout, unmanaged worktrees, and worktrees containing active sessions. Navigator does not force removal, merge branches, create pull requests, or maintain a separate job database. +Navigator is scoped to the current project. New sessions inherit the calling session's agent, model, and variant unless explicitly overridden. Session IDs are ownership-checked, directories must be native managed worktrees, and lifecycle calls cannot target the calling session. `session_send` can switch the target session's agent or model before admitting a steered prompt. Waits default to `maxWaitMs`, cap requested timeouts at `maxWaitMs`, and use `timeoutMs: 0` for an immediate snapshot. Removal rejects the checkout, unmanaged worktrees, and worktrees containing active sessions. Navigator does not force removal, merge branches, create pull requests, or maintain a separate job database. When OpenCode exposes experimental workspace adapters, Kompass registers a `rift` workspace adapter for OpenCode's workspace API using its bundled `rift-snapshot` dependency. Navigator automatically uses Rift for `new_worktree` sessions when no `startCommand` is requested, falling back to Git worktrees otherwise. diff --git a/packages/web/src/content/docs/docs/reference/tools/index.mdx b/packages/web/src/content/docs/docs/reference/tools/index.mdx index a9c9acb..de32e78 100644 --- a/packages/web/src/content/docs/docs/reference/tools/index.mdx +++ b/packages/web/src/content/docs/docs/reference/tools/index.mdx @@ -50,7 +50,7 @@ Creates or updates GitHub issues, renders checklist sections, and can append iss ## OpenCode Navigator tools -Navigator tools are enabled by default and are available only through the OpenCode adapter. Their default runtime names use the `kompass_` prefix. See [Kompass Navigator](./navigator/) for arguments and safety behavior. +Navigator tools are enabled by default and are available only through the OpenCode adapter. Use them only for explicitly requested native-session or managed-worktree workflows, not for subagent delegation; OpenCode's built-in `task` tool owns subagent lifecycle and waiting. Their default runtime names use the `kompass_` prefix. See [Kompass Navigator](./navigator/) for arguments and safety behavior. ### `worktree_list` @@ -58,7 +58,7 @@ Lists the current checkout explicitly and all native OpenCode-managed worktrees. ### `session_create` -Creates a native session in the checkout, an existing managed workspace, or a newly created workspace; admits its initial prompt and returns immediately. New workspaces prefer the registered Rift adapter when available and fall back to Git worktrees. +Creates a native session in the checkout, an existing managed workspace, or a newly created workspace; inherits the calling session's agent, model, and variant unless overridden, admits its initial prompt, and returns immediately. New workspaces prefer the registered Rift adapter when available and fall back to Git worktrees. ### `session_list` diff --git a/packages/web/src/content/docs/docs/reference/tools/navigator.mdx b/packages/web/src/content/docs/docs/reference/tools/navigator.mdx index ef54167..146d0fd 100644 --- a/packages/web/src/content/docs/docs/reference/tools/navigator.mdx +++ b/packages/web/src/content/docs/docs/reference/tools/navigator.mdx @@ -3,12 +3,12 @@ title: Kompass Navigator description: Native OpenCode session and managed-worktree orchestration tools. --- -Navigator is enabled by default in the OpenCode adapter. Default runtime names use the `kompass_` prefix; set `adapters.opencode.navigator.enabled` to `false` to disable all eight tools. +Navigator is enabled by default in the OpenCode adapter. Use it only when the user explicitly requests native-session, managed-worktree, or multi-session workflow orchestration. Do not use it for subagent delegation: OpenCode's built-in `task` tool creates child sessions, waits for foreground tasks, and reports background completion automatically. Default runtime names use the `kompass_` prefix; set `adapters.opencode.navigator.enabled` to `false` to disable all eight tools. | Logical tool | Purpose | | --- | --- | | `worktree_list` | List the checkout and native managed worktrees. | -| `session_create` | Create a native session in the checkout, an existing managed workspace, or a newly created workspace and admit its first prompt asynchronously. New workspaces prefer Rift when available. | +| `session_create` | Create a native session in the checkout, an existing managed workspace, or a newly created workspace, inheriting the caller's agent, model, and variant unless overridden, and admit its first prompt asynchronously. New workspaces prefer Rift when available. | | `session_list` | List paginated sessions filtered to the current project. | | `session_read` | Read a bounded page of recent messages with optional tool outputs. | | `session_send` | Send a steered follow-up through the detected session API, optionally switching agent or model first. | @@ -23,6 +23,7 @@ Navigator is enabled by default in the OpenCode adapter. Default runtime names u - Send, wait, and interrupt reject the calling session. - Reads default to ten recent messages, exclude tool outputs, and enforce configured per-item and total character limits. - Navigator uses the same V1-or-V2 protocol choice as OpenCode Desktop so created sessions remain visible there. +- V2 create and send operations reject unknown agent names before admitting a prompt. - Worktree removal rejects the main checkout, unmanaged worktrees, and worktrees containing active sessions. - Partial creation errors identify resources already created and never automatically delete them.