Przeglądaj źródła

chore: generate

opencode-agent[bot] 2 miesięcy temu
rodzic
commit
e4d3b81b0e

+ 11 - 10
packages/core/src/config.ts

@@ -32,17 +32,21 @@ export class Info extends Schema.Class<Info>("Config.Info")({
   model: Schema.String.pipe(Schema.optional).annotate({
     description: "Default model to use when no session or agent model is selected",
   }),
-  autoupdate: Schema.Union([Schema.Boolean, Schema.Literal("notify")]).pipe(Schema.optional).annotate({
-    description: "Automatically update or notify when a new version is available",
-  }),
+  autoupdate: Schema.Union([Schema.Boolean, Schema.Literal("notify")])
+    .pipe(Schema.optional)
+    .annotate({
+      description: "Automatically update or notify when a new version is available",
+    }),
   share: Schema.Literals(["manual", "auto", "disabled"]).pipe(Schema.optional).annotate({
     description: "Control whether sessions may be shared manually, automatically, or not at all",
   }),
   enterprise: Schema.Struct({
     url: Schema.String.pipe(Schema.optional),
-  }).pipe(Schema.optional).annotate({
-    description: "Enterprise sharing service configuration",
-  }),
+  })
+    .pipe(Schema.optional)
+    .annotate({
+      description: "Enterprise sharing service configuration",
+    }),
   username: Schema.String.pipe(Schema.optional).annotate({
     description: "Username displayed in conversations and used for telemetry identity",
   }),
@@ -196,7 +200,4 @@ export const layer = Layer.effect(
   }),
 )
 
-export const defaultLayer = layer.pipe(
-  Layer.provide(AppFileSystem.defaultLayer),
-  Layer.provide(Global.defaultLayer),
-)
+export const defaultLayer = layer.pipe(Layer.provide(AppFileSystem.defaultLayer), Layer.provide(Global.defaultLayer))

+ 7 - 1
packages/core/src/plugin/boot.ts

@@ -18,7 +18,13 @@ import { ProviderPlugins } from "./provider"
 type Plugin = {
   id: PluginV2.ID
   effect: PluginV2.Effect<
-    Catalog.Service | AccountV2.Service | AgentV2.Service | Npm.Service | EventV2.Service | PluginV2.Service | Config.Service
+    | Catalog.Service
+    | AccountV2.Service
+    | AgentV2.Service
+    | Npm.Service
+    | EventV2.Service
+    | PluginV2.Service
+    | Config.Service
   >
 }
 

+ 1 - 5
packages/core/src/state.ts

@@ -15,11 +15,7 @@ export interface Options<State extends Objectish, Editor> {
 
 export interface Interface<State extends Objectish, Editor> {
   readonly get: () => State
-  readonly transform: () => Effect.Effect<
-    (transform: Transform<Editor>) => Effect.Effect<void>,
-    never,
-    Scope.Scope
-  >
+  readonly transform: () => Effect.Effect<(transform: Transform<Editor>) => Effect.Effect<void>, never, Scope.Scope>
   readonly update: (update: (editor: Editor) => Effect.Effect<void>, reason?: string) => Effect.Effect<void>
 }
 

+ 1 - 3
packages/core/test/agent.test.ts

@@ -94,9 +94,7 @@ describe("AgentV2", () => {
       const id = AgentV2.ID.make("custom")
 
       yield* agent.update((editor) => Effect.sync(() => editor.update(id, () => {})))
-      expect(yield* agent.get(id)).toEqual(
-        AgentV2.Info.empty(id),
-      )
+      expect(yield* agent.get(id)).toEqual(AgentV2.Info.empty(id))
 
       yield* agent.update((editor) => Effect.sync(() => editor.remove(id)))
       expect(yield* agent.get(id)).toBeUndefined()

+ 13 - 4
packages/core/test/config/config.test.ts

@@ -194,9 +194,14 @@ describe("Config", () => {
                 },
                 snapshots: false,
                 watcher: { ignore: ["node_modules/**", "dist/**", ".git"] },
-                formatter: { prettier: { disabled: true }, custom: { command: ["custom-fmt", "$FILE"], extensions: [".foo"] } },
+                formatter: {
+                  prettier: { disabled: true },
+                  custom: { command: ["custom-fmt", "$FILE"], extensions: [".foo"] },
+                },
                 lsp: { typescript: { disabled: true }, custom: { command: ["custom-lsp"], extensions: [".foo"] } },
-                attachments: { image: { auto_resize: false, max_width: 1200, max_height: 900, max_base64_bytes: 1048576 } },
+                attachments: {
+                  image: { auto_resize: false, max_width: 1200, max_height: 900, max_base64_bytes: 1048576 },
+                },
                 tool_output: { max_lines: 1000, max_bytes: 32768 },
                 mcp: {
                   timeout: 5000,
@@ -370,11 +375,15 @@ describe("Config", () => {
             await fs.mkdir(global, { recursive: true })
             await fs.writeFile(
               path.join(global, "opencode.json"),
-              JSON.stringify({ experimental: { policies: [{ effect: "deny", action: "provider.use", resource: "openai" }] } }),
+              JSON.stringify({
+                experimental: { policies: [{ effect: "deny", action: "provider.use", resource: "openai" }] },
+              }),
             )
             await fs.writeFile(
               path.join(tmp.path, "opencode.json"),
-              JSON.stringify({ experimental: { policies: [{ effect: "allow", action: "provider.use", resource: "openai" }] } }),
+              JSON.stringify({
+                experimental: { policies: [{ effect: "allow", action: "provider.use", resource: "openai" }] },
+              }),
             )
           })
 

+ 1 - 6
packages/opencode/test/provider/header-timeout.test.ts

@@ -17,12 +17,7 @@ afterEach(async () => {
 })
 
 const it = testEffect(
-  Layer.mergeAll(
-    Provider.defaultLayer,
-    Env.defaultLayer,
-    Plugin.defaultLayer,
-    CrossSpawnSpawner.defaultLayer,
-  ),
+  Layer.mergeAll(Provider.defaultLayer, Env.defaultLayer, Plugin.defaultLayer, CrossSpawnSpawner.defaultLayer),
 )
 
 it.live("headerTimeout does not abort delayed SSE body after headers arrive", () =>

+ 26 - 7
packages/sdk/js/src/v2/gen/types.gen.ts

@@ -77,6 +77,7 @@ export type Event =
   | EventSessionNextCompactionStarted
   | EventSessionNextCompactionDelta
   | EventSessionNextCompactionEnded
+  | EventPluginAdded
   | EventCatalogModelUpdated
   | EventModelsDevRefreshed
   | EventAccountAdded
@@ -878,6 +879,7 @@ export type GlobalEvent = {
     | EventSessionNextCompactionStarted
     | EventSessionNextCompactionDelta
     | EventSessionNextCompactionEnded
+    | EventPluginAdded
     | EventCatalogModelUpdated
     | EventModelsDevRefreshed
     | EventAccountAdded
@@ -1316,6 +1318,7 @@ export type Config = {
     primary_tools?: Array<string>
     continue_loop_on_deny?: boolean
     mcp_timeout?: number
+    policies?: Array<ConfigV2ExperimentalPolicy>
   }
 }
 
@@ -2137,7 +2140,7 @@ export type SyncEventSessionNextModelSwitched = {
     model: {
       id: string
       providerID: string
-      variant: string
+      variant?: string
     }
   }
 }
@@ -2209,7 +2212,7 @@ export type SyncEventSessionNextStepStarted = {
     model: {
       id: string
       providerID: string
-      variant: string
+      variant?: string
     }
     snapshot?: string
   }
@@ -2890,7 +2893,7 @@ export type EventSessionNextModelSwitched = {
     model: {
       id: string
       providerID: string
-      variant: string
+      variant?: string
     }
   }
 }
@@ -2978,7 +2981,7 @@ export type EventSessionNextStepStarted = {
     model: {
       id: string
       providerID: string
-      variant: string
+      variant?: string
     }
     snapshot?: string
   }
@@ -3252,6 +3255,14 @@ export type EventSessionNextCompactionEnded = {
   }
 }
 
+export type EventPluginAdded = {
+  id: string
+  type: "plugin.added"
+  properties: {
+    id: string
+  }
+}
+
 export type ModelV2Info = {
   id: string
   apiID: string
@@ -3416,6 +3427,14 @@ export type EventAccountSwitched = {
   }
 }
 
+export type PolicyEffect = "allow" | "deny"
+
+export type ConfigV2ExperimentalPolicy = {
+  action: "provider.use"
+  effect: PolicyEffect
+  resource: string
+}
+
 export type SessionInfo = {
   id: string
   parentID?: string
@@ -3426,7 +3445,7 @@ export type SessionInfo = {
   model?: {
     id: string
     providerID: string
-    variant: string
+    variant?: string
   }
   cost: number
   tokens: {
@@ -3472,7 +3491,7 @@ export type SessionMessageModelSwitched = {
   model: {
     id: string
     providerID: string
-    variant: string
+    variant?: string
   }
 }
 
@@ -3607,7 +3626,7 @@ export type SessionMessageAssistant = {
   model: {
     id: string
     providerID: string
-    variant: string
+    variant?: string
   }
   content: Array<SessionMessageAssistantText | SessionMessageAssistantReasoning | SessionMessageAssistantTool>
   snapshot?: {

+ 64 - 7
packages/sdk/openapi.json

@@ -10698,6 +10698,9 @@
           {
             "$ref": "#/components/schemas/EventSessionNextCompactionEnded"
           },
+          {
+            "$ref": "#/components/schemas/EventPluginAdded"
+          },
           {
             "$ref": "#/components/schemas/EventCatalogModelUpdated"
           },
@@ -13124,6 +13127,9 @@
               {
                 "$ref": "#/components/schemas/EventSessionNextCompactionEnded"
               },
+              {
+                "$ref": "#/components/schemas/EventPluginAdded"
+              },
               {
                 "$ref": "#/components/schemas/EventCatalogModelUpdated"
               },
@@ -14330,6 +14336,12 @@
               "mcp_timeout": {
                 "type": "integer",
                 "exclusiveMinimum": 0
+              },
+              "policies": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/components/schemas/ConfigV2ExperimentalPolicy"
+                }
               }
             },
             "additionalProperties": false
@@ -16969,7 +16981,7 @@
                     "type": "string"
                   }
                 },
-                "required": ["id", "providerID", "variant"],
+                "required": ["id", "providerID"],
                 "additionalProperties": false
               }
             },
@@ -17201,7 +17213,7 @@
                     "type": "string"
                   }
                 },
-                "required": ["id", "providerID", "variant"],
+                "required": ["id", "providerID"],
                 "additionalProperties": false
               },
               "snapshot": {
@@ -19307,7 +19319,7 @@
                     "type": "string"
                   }
                 },
-                "required": ["id", "providerID", "variant"],
+                "required": ["id", "providerID"],
                 "additionalProperties": false
               }
             },
@@ -19570,7 +19582,7 @@
                     "type": "string"
                   }
                 },
-                "required": ["id", "providerID", "variant"],
+                "required": ["id", "providerID"],
                 "additionalProperties": false
               },
               "snapshot": {
@@ -20386,6 +20398,30 @@
         "required": ["id", "type", "properties"],
         "additionalProperties": false
       },
+      "EventPluginAdded": {
+        "type": "object",
+        "properties": {
+          "id": {
+            "type": "string"
+          },
+          "type": {
+            "type": "string",
+            "enum": ["plugin.added"]
+          },
+          "properties": {
+            "type": "object",
+            "properties": {
+              "id": {
+                "type": "string"
+              }
+            },
+            "required": ["id"],
+            "additionalProperties": false
+          }
+        },
+        "required": ["id", "type", "properties"],
+        "additionalProperties": false
+      },
       "ModelV2Info": {
         "type": "object",
         "properties": {
@@ -20900,6 +20936,27 @@
         "required": ["id", "type", "properties"],
         "additionalProperties": false
       },
+      "PolicyEffect": {
+        "type": "string",
+        "enum": ["allow", "deny"]
+      },
+      "ConfigV2ExperimentalPolicy": {
+        "type": "object",
+        "properties": {
+          "action": {
+            "type": "string",
+            "enum": ["provider.use"]
+          },
+          "effect": {
+            "$ref": "#/components/schemas/PolicyEffect"
+          },
+          "resource": {
+            "type": "string"
+          }
+        },
+        "required": ["action", "effect", "resource"],
+        "additionalProperties": false
+      },
       "SessionInfo": {
         "type": "object",
         "properties": {
@@ -20937,7 +20994,7 @@
                 "type": "string"
               }
             },
-            "required": ["id", "providerID", "variant"],
+            "required": ["id", "providerID"],
             "additionalProperties": false
           },
           "cost": {
@@ -21065,7 +21122,7 @@
                 "type": "string"
               }
             },
-            "required": ["id", "providerID", "variant"],
+            "required": ["id", "providerID"],
             "additionalProperties": false
           }
         },
@@ -21444,7 +21501,7 @@
                 "type": "string"
               }
             },
-            "required": ["id", "providerID", "variant"],
+            "required": ["id", "providerID"],
             "additionalProperties": false
           },
           "content": {

+ 3 - 3
packages/web/src/content/docs/policies.mdx

@@ -42,9 +42,9 @@ A provider denied by policy is not available for model selection or model use, e
 
 OpenCode currently supports one policy action:
 
-| Action         | Resource                       | Description                                |
-| -------------- | ------------------------------ | ------------------------------------------ |
-| `provider.use` | Provider ID, such as `openai` | Allow or deny use of an LLM provider.      |
+| Action         | Resource                      | Description                           |
+| -------------- | ----------------------------- | ------------------------------------- |
+| `provider.use` | Provider ID, such as `openai` | Allow or deny use of an LLM provider. |
 
 More policy actions may be added in the future.
 

+ 1 - 5
specs/v2/catalog-config-plugin-lifecycle.md

@@ -192,11 +192,7 @@ Plugins register replayable catalog transforms. Each transform receives a `Catal
 
 ```ts
 interface Catalog {
-  transform(): Effect.Effect<
-    (update: (catalog: Catalog.Editor) => void) => Effect.Effect<void>,
-    never,
-    Scope.Scope
-  >
+  transform(): Effect.Effect<(update: (catalog: Catalog.Editor) => void) => Effect.Effect<void>, never, Scope.Scope>
 }
 ```
 

+ 54 - 53
specs/v2/config.md

@@ -36,12 +36,12 @@ Settings that affect process startup, shell execution, or network serving. Revie
 
 Configuration that introduces location-scoped project resources or discoverable content.
 
-| Field          | Current Purpose                         | Status | Notes                                                                                                         |
-| -------------- | --------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------- |
-| `command`      | User-defined commands                   | remove | Do not port as v2 config; named reusable user workflows belong to skills.                                   |
-| `skills`       | Additional skill locations              | redesign | Replace `{ paths?, urls? }` with a single array of local path or remote URL discovery sources.                           |
-| `reference`    | Named git or local directory references | redesign | Rename to plural `references`; retain named local path and Git repository external-context entries.        |
-| `instructions` | Additional ambient instruction sources  | keep     | Keep as one array of local paths, glob patterns, or remote URLs supplying automatically included context.   |
+| Field          | Current Purpose                         | Status   | Notes                                                                                                     |
+| -------------- | --------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
+| `command`      | User-defined commands                   | remove   | Do not port as v2 config; named reusable user workflows belong to skills.                                 |
+| `skills`       | Additional skill locations              | redesign | Replace `{ paths?, urls? }` with a single array of local path or remote URL discovery sources.            |
+| `reference`    | Named git or local directory references | redesign | Rename to plural `references`; retain named local path and Git repository external-context entries.       |
+| `instructions` | Additional ambient instruction sources  | keep     | Keep as one array of local paths, glob patterns, or remote URLs supplying automatically included context. |
 
 V2 does not expose separate user-authored command configuration. Skills should cover named reusable prompt workflows, whether invoked directly by the user or loaded by an agent. Internal command routing and built-in commands may remain runtime concerns without creating a `command` or `commands` config field.
 
@@ -59,7 +59,12 @@ Keep ambient instructions separate from skills. Instructions are automatically i
 
 ```jsonc
 {
-  "instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md", "https://example.com/shared-rules.md"],
+  "instructions": [
+    "CONTRIBUTING.md",
+    "docs/guidelines.md",
+    ".cursor/rules/*.md",
+    "https://example.com/shared-rules.md",
+  ],
 }
 ```
 
@@ -80,9 +85,9 @@ Retain the compact string entry form as well: values starting with `.`, `/`, or
 
 Plugin loading has source-path and scope-sensitive behavior, so it should be reviewed separately from other project resources.
 
-| Field    | Current Purpose               | Status   | Notes                                                                                                                 |
-| -------- | ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
-| `plugin` | User-specified plugin modules | redesign | Rename to plural `plugins`; retain ordered loading with package strings or `{ package, options? }` entries.         |
+| Field    | Current Purpose               | Status   | Notes                                                                                                       |
+| -------- | ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
+| `plugin` | User-specified plugin modules | redesign | Rename to plural `plugins`; retain ordered loading with package strings or `{ package, options? }` entries. |
 
 Plugin order remains part of the v2 configuration contract because hook registration and execution can depend on load order. Replace legacy option tuples with readable object entries:
 
@@ -106,14 +111,14 @@ The configured `plugins` list represents package-loaded plugins only. Local plug
 
 Settings controlling local file observation, snapshots, language tooling, and tool output behavior.
 
-| Field         | Current Purpose                         | Status  | Notes |
-| ------------- | --------------------------------------- | ------- | ----- |
-| `watcher`     | Ignore patterns for filesystem watching | keep     | Keep `{ ignore?: string[] }`; this configures the filesystem watcher subsystem. |
-| `snapshot`    | Enable filesystem snapshot tracking     | redesign | Rename to plural `snapshots`; controls creation of snapshots used for undo and revert behavior. |
-| `formatter`   | Configure formatters                    | keep     | Keep singular `boolean \| Record<string, entry>` shape; it configures built-in enablement and named formatter overrides. |
-| `lsp`         | Configure language servers              | keep     | Keep singular `boolean \| Record<string, entry>` shape; custom servers need commands and file extensions. |
+| Field         | Current Purpose                         | Status   | Notes                                                                                                                                             |
+| ------------- | --------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `watcher`     | Ignore patterns for filesystem watching | keep     | Keep `{ ignore?: string[] }`; this configures the filesystem watcher subsystem.                                                                   |
+| `snapshot`    | Enable filesystem snapshot tracking     | redesign | Rename to plural `snapshots`; controls creation of snapshots used for undo and revert behavior.                                                   |
+| `formatter`   | Configure formatters                    | keep     | Keep singular `boolean \| Record<string, entry>` shape; it configures built-in enablement and named formatter overrides.                          |
+| `lsp`         | Configure language servers              | keep     | Keep singular `boolean \| Record<string, entry>` shape; custom servers need commands and file extensions.                                         |
 | `attachment`  | Configure attachment/image processing   | redesign | Rename to plural `attachments`; retain `{ image?: { auto_resize?, max_width?, max_height?, max_base64_bytes? } }` for input normalization limits. |
-| `tool_output` | Configure tool output truncation limits | keep     | Keep `{ max_lines?, max_bytes? }`; both positive thresholds apply to saved-preview truncation behavior. |
+| `tool_output` | Configure tool output truncation limits | keep     | Keep `{ max_lines?, max_bytes? }`; both positive thresholds apply to saved-preview truncation behavior.                                           |
 
 `formatter` and `lsp` configure one project tooling subsystem each, so their singular names remain appropriate. `true` enables the built-in registrations, `false` disables them, and a keyed object enables built-ins while applying named overrides or custom registrations. Custom language servers must declare `extensions` so runtime file attachment is deterministic; validation of known built-in server IDs belongs with the eventual v2 LSP integration rather than the aggregate core config schema.
 
@@ -140,12 +145,12 @@ Rename legacy `attachment` to `attachments` in v2. This setting controls process
 
 Settings affecting sharing behavior or user/account identity rather than model execution.
 
-| Field        | Current Purpose                                 | Status  | Notes                           |
-| ------------ | ----------------------------------------------- | ------- | ------------------------------- |
-| `share`      | Session sharing behavior                        | keep   | Keep `"manual" \| "auto" \| "disabled"`; it controls manual sharing permission and automatic sharing of new sessions. |
-| `autoshare`  | Legacy automatic sharing flag                   | remove | Do not port deprecated alias; use `share: "auto"`. |
+| Field        | Current Purpose                                 | Status | Notes                                                                                                                  |
+| ------------ | ----------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------- |
+| `share`      | Session sharing behavior                        | keep   | Keep `"manual" \| "auto" \| "disabled"`; it controls manual sharing permission and automatic sharing of new sessions.  |
+| `autoshare`  | Legacy automatic sharing flag                   | remove | Do not port deprecated alias; use `share: "auto"`.                                                                     |
 | `enterprise` | Enterprise URL configuration                    | keep   | Keep `{ url?: string }`; currently selects the legacy sharing service endpoint when no organization account is active. |
-| `username`   | Display username in conversations and telemetry | keep   | Keep string identity override; runtime may otherwise resolve an operating-system username. |
+| `username`   | Display username in conversations and telemetry | keep   | Keep string identity override; runtime may otherwise resolve an operating-system username.                             |
 
 Retain `share` as the single session-sharing setting. `"manual"` permits explicit sharing, `"auto"` shares newly created top-level sessions, and `"disabled"` prevents sharing. Legacy `autoshare: true` is only an alias for `share: "auto"`, so v2 does not expose it.
 
@@ -163,13 +168,13 @@ Retain `enterprise.url` for legacy enterprise share hosting selection and `usern
 
 Provider catalog customization and model-choice configuration. The new core work has started here.
 
-| Field                | Current Purpose                                   | Status   | Notes                                                                                                                   |
-| -------------------- | ------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------- |
+| Field                | Current Purpose                                   | Status   | Notes                                                                                                                        |
+| -------------------- | ------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
 | `provider`           | Custom provider configuration and model overrides | redesign | Rename to plural `providers` in v2; do not preserve the legacy singular key. Review nested provider/model fields separately. |
-| `disabled_providers` | Disable automatically loaded providers            | redesign | Replace with `experimental.policies: [{ effect: "deny", action: "provider.use", resource: "..." }]`.               |
-| `enabled_providers`  | Restrict enabled providers to an allowlist        | redesign | Replace with ordered `provider.use` allow/deny statements and wildcard resources.                                       |
-| `model`              | Default model selection                           | keep     | Keep as the fallback model when an active session or agent does not specify a model.                                   |
-| `small_model`        | Small/utility model selection                     | remove   | Do not port; its only runtime consumer is title generation, which can use an explicit `title` agent model override.    |
+| `disabled_providers` | Disable automatically loaded providers            | redesign | Replace with `experimental.policies: [{ effect: "deny", action: "provider.use", resource: "..." }]`.                         |
+| `enabled_providers`  | Restrict enabled providers to an allowlist        | redesign | Replace with ordered `provider.use` allow/deny statements and wildcard resources.                                            |
+| `model`              | Default model selection                           | keep     | Keep as the fallback model when an active session or agent does not specify a model.                                         |
+| `small_model`        | Small/utility model selection                     | remove   | Do not port; its only runtime consumer is title generation, which can use an explicit `title` agent model override.          |
 
 Provider selection rules belong in `experimental.policies` rather than provider entries or repeated top-level provider fields. Initial proposed shape:
 
@@ -221,9 +226,7 @@ Do not port legacy provider model `reasoning`, `temperature`, or `interleaved` f
           "api_id": "upstream-chat-model",
           "limit": { "output": 32768 },
           "cost": { "input": 1.25, "output": 10 },
-          "variants": [
-            { "id": "high", "aisdk": { "request": { "reasoningEffort": "high" } } },
-          ],
+          "variants": [{ "id": "high", "aisdk": { "request": { "reasoningEffort": "high" } } }],
         },
       },
     },
@@ -235,13 +238,13 @@ Do not port legacy provider model `reasoning`, `temperature`, or `interleaved` f
 
 Agent behavior and tool-access policy. Review together because agent configuration can contain permissions and model choices.
 
-| Field           | Current Purpose                                     | Status  | Notes                                       |
-| --------------- | --------------------------------------------------- | ------- | ------------------------------------------- |
-| `default_agent` | Choose default primary agent                        | remove | Do not retain a separate top-level selector; default choice should be designed with the v2 agent configuration model. |
-| `mode`          | Legacy agent configuration alias                    | remove | Do not port deprecated alias; configure agents through the v2 agent surface only. |
-| `agent`         | Configure primary, subagent, and specialized agents | redesign | Rename to plural `agents`; retain a named map of built-in overrides and custom agent definitions. |
+| Field           | Current Purpose                                     | Status   | Notes                                                                                                                          |
+| --------------- | --------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
+| `default_agent` | Choose default primary agent                        | remove   | Do not retain a separate top-level selector; default choice should be designed with the v2 agent configuration model.          |
+| `mode`          | Legacy agent configuration alias                    | remove   | Do not port deprecated alias; configure agents through the v2 agent surface only.                                              |
+| `agent`         | Configure primary, subagent, and specialized agents | redesign | Rename to plural `agents`; retain a named map of built-in overrides and custom agent definitions.                              |
 | `permission`    | Tool permission rules                               | redesign | Rename to plural `permissions`; replace legacy map shorthand with an ordered array of `{ permission, pattern, action }` rules. |
-| `tools`         | Legacy tool enable/disable map                      | remove | Do not port boolean enable/disable alias; express tool access through permissions. |
+| `tools`         | Legacy tool enable/disable map                      | remove   | Do not port boolean enable/disable alias; express tool access through permissions.                                             |
 
 Do not port `default_agent` ahead of the v2 agent design. The legacy runtime uses it to choose a visible, non-subagent fallback instead of `build`, but exposing that selection as an isolated top-level field would pre-commit v2 to the legacy agent model before agents and their policy surface are defined together.
 
@@ -278,9 +281,7 @@ Retain `description`, `hidden`, and `steps`; they define an agent's discoverabil
       "color": "warning",
       "steps": 12,
       "disabled": false,
-      "permissions": [
-        { "permission": "edit", "pattern": "*", "action": "deny" },
-      ],
+      "permissions": [{ "permission": "edit", "pattern": "*", "action": "deny" }],
     },
   },
 }
@@ -303,8 +304,8 @@ Rename legacy `permission` to `permissions` and expose the normalized ordered ru
 
 External protocol and server integration configuration.
 
-| Field | Current Purpose                       | Status  | Notes |
-| ----- | ------------------------------------- | ------- | ----- |
+| Field | Current Purpose                       | Status   | Notes                                                                                                                                             |
+| ----- | ------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
 | `mcp` | MCP server definitions and enablement | redesign | Keep opencode's explicit local/remote server entry format, nested under `mcp.servers`; use `disabled` for inactive entries and move timeout here. |
 
 Keep the opencode MCP server entry format instead of adopting the common `mcpServers` copy/paste shape. Local servers remain explicit `type: "local"` entries with command arrays and `environment`; remote servers remain explicit `type: "remote"` entries with `url`, `headers`, and optional `oauth`. Nest the server map under `mcp.servers` so protocol-wide settings such as default timeout can live under the same subsystem.
@@ -343,8 +344,8 @@ Keep the opencode MCP server entry format instead of adopting the common `mcpSer
 
 Behavior affecting long-running conversations and context management.
 
-| Field        | Current Purpose                                             | Status  | Notes |
-| ------------ | ----------------------------------------------------------- | ------- | ----- |
+| Field        | Current Purpose                                             | Status   | Notes                                                                                 |
+| ------------ | ----------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------- |
 | `compaction` | Automatic compaction, pruning, and context reserve settings | redesign | Group retained verbatim history under `keep` and rename context headroom to `buffer`. |
 
 Retain the compaction capability but redesign the less clear limits. `keep.turns` is the maximum number of recent user turns to preserve verbatim after compaction, and `keep.tokens` is the token budget for those retained turns. `buffer` is the token headroom reserved so automatic compaction triggers before the input window is exhausted.
@@ -367,15 +368,15 @@ Retain the compaction capability but redesign the less clear limits. `keep.turns
 
 Fields that should not be ported by inertia; each needs an explicit justification.
 
-| Field                                | Current Purpose                         | Status  | Notes                                                               |
-| ------------------------------------ | --------------------------------------- | ------- | ------------------------------------------------------------------- |
-| `layout`                             | Legacy layout selection                 | remove | Do not port deprecated option; stretch layout is always used.       |
-| `experimental.disable_paste_summary` | Disable pasted-content summary behavior | remove | Do not port; pasted-input presentation behavior belongs to the client/UI surface. |
-| `experimental.batch_tool`            | Enable batch tool                       | remove | Do not port; batch tool is no longer a supported feature.          |
-| `experimental.openTelemetry`         | Enable AI SDK telemetry spans           | remove | Do not port; observability is process-level and should use standard OpenTelemetry environment or declarative configuration. |
-| `experimental.primary_tools`         | Restrict tools to primary agents        | remove | Do not port obsolete gating; agent tool access is configured through permissions. |
-| `experimental.continue_loop_on_deny` | Continue loop after denied tool call    | remove | Do not port legacy denied-tool loop behavior.                       |
-| `experimental.mcp_timeout`           | MCP request timeout                     | redesign | Move to `mcp.timeout` for the default and `mcp.servers.<name>.timeout` for per-server overrides. |
+| Field                                | Current Purpose                         | Status   | Notes                                                                                                                       |
+| ------------------------------------ | --------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- |
+| `layout`                             | Legacy layout selection                 | remove   | Do not port deprecated option; stretch layout is always used.                                                               |
+| `experimental.disable_paste_summary` | Disable pasted-content summary behavior | remove   | Do not port; pasted-input presentation behavior belongs to the client/UI surface.                                           |
+| `experimental.batch_tool`            | Enable batch tool                       | remove   | Do not port; batch tool is no longer a supported feature.                                                                   |
+| `experimental.openTelemetry`         | Enable AI SDK telemetry spans           | remove   | Do not port; observability is process-level and should use standard OpenTelemetry environment or declarative configuration. |
+| `experimental.primary_tools`         | Restrict tools to primary agents        | remove   | Do not port obsolete gating; agent tool access is configured through permissions.                                           |
+| `experimental.continue_loop_on_deny` | Continue loop after denied tool call    | remove   | Do not port legacy denied-tool loop behavior.                                                                               |
+| `experimental.mcp_timeout`           | MCP request timeout                     | redesign | Move to `mcp.timeout` for the default and `mcp.servers.<name>.timeout` for per-server overrides.                            |
 
 ## Review Order