From 73ab3026fda4439021df1e50aae5d1c3f22fadcb Mon Sep 17 00:00:00 2001 From: Cameron Date: Tue, 20 Oct 2026 11:18:27 +0000 Subject: [PATCH] fix(settings): new threads stay in Full access unless you choose Auto The built-in default permission mode for new threads goes back to Full access, as upstream, so no one's new threads change on update. Choosing Auto as the default still starts providers without their own reviewer in Full access. --- .github/fork-features.yml | 10 ++++------ docs/user/permission-modes.md | 2 +- docs/user/styal-differences.md | 8 ++++---- packages/contracts/src/providerPolicy.ts | 7 ------- packages/contracts/src/settings.test.ts | 6 +++--- packages/contracts/src/settings.ts | 10 ++-------- 6 files changed, 14 insertions(+), 29 deletions(-) diff --git a/.github/fork-features.yml b/.github/fork-features.yml index d95b2f8bf60b..a302f562c9f2 100644 --- a/.github/fork-features.yml +++ b/.github/fork-features.yml @@ -3114,16 +3114,16 @@ features: retire_when: Upstream preserves project scope across sidebar state and every new-thread entry point. - id: provider-auto-default - title: Start new threads in Auto where the provider reviews actions + title: Apply an Auto default only where the provider reviews actions status: maintained prs: [928, 930] invariants: - - The built-in default permission mode for new threads is Auto. Configs that never chose a mode, including those that kept the old Full access default, use it. + - The built-in default permission mode for new threads stays Full access, as upstream; Auto as the default is the user's choice. - With Auto as the default, a new thread on a provider whose snapshot does not report its own Auto reviewer (reviewsAutoMode) starts in Full access; Claude, Codex, and Grok report one. An unloaded snapshot or an older server counts as no reviewer. - Web and mobile drafts follow their selected provider until the user picks a mode; the server's bootstrap thread uses the same resolution. Picking Auto for one thread keeps Auto on every provider. - The provider canary's auto scenario fails a release whose Auto turn asks for approval of a routine workspace write, or whose provider does not report applying Auto; providers without reviewsAutoMode skip it. - provider.turn.completed reports approvalRequests, the command, file, and permission approvals the turn raised, alongside its runtimeMode. - rationale: Auto is the safer default where a reviewer approves routine actions, but on a provider without one Auto asks about every action, which would stall threads nobody is watching. + rationale: Auto is the safer default where a reviewer approves routine actions, but on a provider without one Auto asks about every action, which would stall threads nobody is watching. Making Auto the built-in default for everyone was withdrawn before release; approval counts from opted-in users are meant to inform that decision. implementation_paths: - apps/mobile/src/features/threads/new-task-flow-provider.tsx - apps/server/scripts/verify-provider-live.ts @@ -3134,7 +3134,6 @@ features: - apps/web/src/components/ChatView.tsx - packages/contracts/src/providerPolicy.ts - packages/contracts/src/server.ts - - packages/contracts/src/settings.ts - packages/provider-core/src/server/snapshotProbe.ts - packages/provider-grok/src/server/status.ts upstream_paths: @@ -3142,14 +3141,13 @@ features: - apps/server/src/orchestration-v2/ProviderEventIngestor.ts - apps/web/src/components/ChatView.tsx - packages/contracts/src/providerPolicy.ts - - packages/contracts/src/settings.ts tests: - apps/server/src/orchestration-v2/ProviderEventIngestor.test.ts - packages/contracts/src/settings.test.ts upstream: status: unassessed tracking: [] - retire_when: Upstream defaults new threads to Auto on providers with their own reviewer, or styal returns to a Full access default. + retire_when: Upstream starts new threads in Full access on providers without their own reviewer when Auto is the default. - id: provider-auto-updates title: styal managed updates install canary-verified provider versions diff --git a/docs/user/permission-modes.md b/docs/user/permission-modes.md index c658e5985f6f..5628a97e0f39 100644 --- a/docs/user/permission-modes.md +++ b/docs/user/permission-modes.md @@ -5,7 +5,7 @@ composer; it applies to that thread. Set the default for new threads in **Settings → General → New threads → Permissions**. Projects can override the environment default. New threads use this setting rather than the -mode of the thread you were viewing. The initial default is **Auto**. With **Auto** as the +mode of the thread you were viewing. The initial default is **Full access**. With **Auto** as the default, new threads on a provider without automatic review, such as OpenCode or Antigravity, start in **Full access** instead of asking about every action; choose **Auto** in the composer to keep it for one thread. Existing threads and modes you choose in a draft keep their permissions. diff --git a/docs/user/styal-differences.md b/docs/user/styal-differences.md index e33e3dd30661..65cd0ccc6af5 100644 --- a/docs/user/styal-differences.md +++ b/docs/user/styal-differences.md @@ -65,10 +65,10 @@ works. This overview focuses on desktop and web; the mobile app is a work in pro [revision adb0420](https://github.com/pingdotgg/t3code/tree/adb04202b25c1c45255e76be9f03f0b346b9c5c4). [Send while the agent is working](./composer.md#send-while-the-agent-is-working). -- **New threads default to Auto.** Claude, Codex, and Grok threads start in **Auto**, where the - provider's own reviewer approves routine actions and asks about the rest. Providers without - automatic review start in **Full access**. A default you chose yourself still applies. T3 Code - starts new threads in **Full access** as of +- **An Auto default fits each provider.** With **Auto** as the default for new threads, Claude, + Codex, and Grok threads start in **Auto**, where the provider's own reviewer approves routine + actions, and providers without automatic review start in **Full access** instead of asking about + every action. In T3 Code an Auto default makes those providers ask, as of [revision 30afc56](https://github.com/pingdotgg/t3code/tree/30afc56076c86580d5d913897280bea660d44c79). [Permission modes](./permission-modes.md). diff --git a/packages/contracts/src/providerPolicy.ts b/packages/contracts/src/providerPolicy.ts index 8db50c982714..b4bfbbc6a89f 100644 --- a/packages/contracts/src/providerPolicy.ts +++ b/packages/contracts/src/providerPolicy.ts @@ -31,13 +31,6 @@ export const RuntimeMode = Schema.Literals([ export type RuntimeMode = typeof RuntimeMode.Type; export const DEFAULT_RUNTIME_MODE: RuntimeMode = "full-access"; -/** - * The built-in default for new threads. A provider whose Auto mode has no - * reviewer of its own starts in Full access instead; see - * `resolveNewThreadRuntimeMode`. - */ -export const DEFAULT_NEW_THREAD_RUNTIME_MODE: RuntimeMode = "auto"; - /** * The mode a new thread starts in from the default-permissions setting. Auto * relies on the provider's own reviewer to approve actions; a provider without diff --git a/packages/contracts/src/settings.test.ts b/packages/contracts/src/settings.test.ts index 05a811bc6a99..d832ca5d72aa 100644 --- a/packages/contracts/src/settings.test.ts +++ b/packages/contracts/src/settings.test.ts @@ -133,9 +133,9 @@ describe("ClientSettings rich text composer", () => { }); describe("ServerSettings default permissions", () => { - it("defaults settings that never chose a mode to Auto", () => { - expect(decodeServerSettings({}).defaultRuntimeMode).toBe("auto"); - expect(DEFAULT_SERVER_SETTINGS.defaultRuntimeMode).toBe("auto"); + it("keeps full access for settings saved before a default was configured", () => { + expect(decodeServerSettings({}).defaultRuntimeMode).toBe("full-access"); + expect(DEFAULT_SERVER_SETTINGS.defaultRuntimeMode).toBe("full-access"); }); it("starts a default of Auto in Full access when the provider has no Auto reviewer", () => { diff --git a/packages/contracts/src/settings.ts b/packages/contracts/src/settings.ts index a1ec05ed30ff..aa4d17acd11b 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -31,7 +31,7 @@ import { } from "./model.ts"; import { ModelSelection } from "./modelSelection.ts"; import { ProjectScript, type ProjectMutation } from "./project.ts"; -import { DEFAULT_NEW_THREAD_RUNTIME_MODE, RuntimeMode } from "./providerPolicy.ts"; +import { DEFAULT_RUNTIME_MODE, RuntimeMode } from "./providerPolicy.ts"; import { BrowserProfile, BrowserProfileId, DEFAULT_BROWSER_PROFILE_ID } from "./browserProfile.ts"; import { DEFAULT_PREVIEW_APPEARANCE, @@ -1195,14 +1195,8 @@ export const ServerSettings = Schema.Struct({ defaultModelSelection: Schema.NullOr(ModelSelection).pipe( Schema.withDecodingDefault(Effect.succeed(null)), ), - /** - * The mode new threads start in, resolved per provider by - * `resolveNewThreadRuntimeMode`. The old built-in Full access was never - * persisted (defaults are stripped on write), so configs that never chose a - * mode move to the new built-in. - */ defaultRuntimeMode: RuntimeMode.pipe( - Schema.withDecodingDefault(Effect.succeed(DEFAULT_NEW_THREAD_RUNTIME_MODE)), + Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE)), ), /** * Per-project overrides of the keys in `PROJECT_SCOPED_SERVER_SETTING_KEYS`.