Skip to content

Propagate runtime approval policy and sandbox mode to thread turn startup#100

Merged
juliusmarminge merged 10 commits intomainfrom
codething/2c75aea7
Feb 27, 2026
Merged

Propagate runtime approval policy and sandbox mode to thread turn startup#100
juliusmarminge merged 10 commits intomainfrom
codething/2c75aea7

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Feb 27, 2026

Summary

  • Add approvalPolicy and sandboxMode to thread.turn.start command and thread.turn-start-requested payload contracts.
  • Forward runtime approval/sandbox settings through decider and provider command reactor when creating/starting provider sessions.
  • Update ChatView to derive runtime settings from runtimeMode (full-access => never + danger-full-access, otherwise on-request + workspace-write).
  • Extend server orchestration tests to verify approval/sandbox fields are emitted and passed into session startup.

Testing

  • apps/server/src/orchestration/decider.projectScripts.test.ts: verifies thread.turn-start-requested includes approvalPolicy and sandboxMode.
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts: verifies startSession receives approvalPolicy and sandboxMode.
  • Project lint scripts: Not run.

Note

Medium Risk
Touches turn-start/session lifecycle and persistence (contracts, provider session management, projections, and a DB migration), so regressions could break turn dispatch or session reuse/restart behavior; changes are scoped and covered by updated tests.

Overview
Propagates runtime controls by making approvalPolicy and sandboxMode required on thread.turn.start and carrying them into thread.turn-start-requested and OrchestrationSession so the values are visible end-to-end.

Updates ProviderCommandReactor to pass these settings into providerService.startSession, persist them onto the thread session, and restart the provider session when either setting changes (otherwise reuse the existing session).

Persists the new fields in projection_thread_sessions (adds columns via a new migration, projects them in ProjectionPipeline, and hydrates them in ProjectionSnapshotQuery). The web ChatView now derives the two fields from runtimeMode when dispatching turn start, and tests are updated/expanded to assert propagation and session restart behavior.

Written by Cursor Bugbot for commit 7d0226c. This will update automatically on new commits. Configure here.

Note

Propagate approvalPolicy and sandboxMode through thread.turn.start and persist them in projection-backed session reads across server and web dispatch paths

Add required approvalPolicy and sandboxMode to ThreadTurnStartCommand, forward them via decider into thread.turn-start-requested, ensure ProviderCommandReactor.make starts/restarts sessions based on these fields, and persist them via projection repositories and migration. Update UI dispatch to include these fields based on runtime mode.

📍Where to Start

Start with processTurnStartRequested and session handling in ProviderCommandReactor.ts, then review event emission in decider.ts and projection persistence in ProjectionThreadSessions.ts.

Macroscope summarized 7d0226c.

Summary by CodeRabbit

  • New Features
    • Provider sessions now include configurable approvalPolicy and sandboxMode that flow from runtime mode into session start and events.
    • Settings persist in session state and read models so UI and tooling observe policy and sandbox values.
  • Bug Fixes
    • Sessions will restart and rebind when approvalPolicy or sandboxMode change, preventing mismatched runtime behavior.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds optional approvalPolicy and sandboxMode fields across the orchestration stack: contract schemas, client dispatch, event payloads, provider session lifecycle (start/stop/rebind), runtime ingestion, projection/store mappings, and tests. Session restart occurs when policy or sandbox mode changes.

Changes

Cohort / File(s) Summary
Contract Definitions
packages/contracts/src/orchestration.ts
Added optional approvalPolicy and sandboxMode to OrchestrationSession, ThreadTurnStartCommand, and ThreadTurnStartRequestedPayload.
Provider Session Core
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
Extended ensureSessionForThread and sendTurnForThread signatures to accept approvalPolicy and sandboxMode; include them in start payloads; restart sessions when policy/mode change; propagate fields into provider events.
Runtime Ingestion
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
Include approvalPolicy and sandboxMode in thread.session.set and error paths; added default constants for both.
Persistence & Projections
apps/server/src/persistence/Migrations/005_Projections.ts, apps/server/src/persistence/Services/ProjectionThreadSessions.ts, apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts, apps/server/src/orchestration/Layers/ProjectionPipeline.ts
DB migration adds approval_policy and sandbox_mode columns; persistence layer upsert/select updated; projection snapshot and pipeline map new fields into read model session objects.
Event Routing / Decider / Client
apps/server/src/orchestration/decider.ts, apps/server/src/orchestration/decider.projectScripts.test.ts, apps/web/src/components/ChatView.tsx
thread.turn.start/thread.turn-start-requested payloads extended with approvalPolicy and sandboxMode; ChatView derives and sets these based on runtimeMode.
Tests & Integration
apps/server/.../*.test.ts, apps/server/integration/orchestrationEngine.integration.test.ts, apps/server/src/wsServer.test.ts, apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
Numerous tests and integration specs updated to include approvalPolicy and sandboxMode in fixtures and assertions; added session reuse/restart scenarios for mode changes.

Sequence Diagram(s)

sequenceDiagram
    participant Client as ChatView
    participant Decider as Decider
    participant Reactor as ProviderCommandReactor
    participant Provider as Provider Session
    participant Ingest as ProviderRuntimeIngestion

    Client->>Decider: dispatch thread.turn.start(approvalPolicy, sandboxMode)
    Decider->>Reactor: sendTurnForThread(..., approvalPolicy, sandboxMode)
    Reactor->>Provider: ensureSessionForThread -> check existing session
    alt session exists & policy/mode unchanged
        Reactor->>Provider: reuse session
    else session exists & policy/mode changed
        Reactor->>Provider: stop session
        Reactor->>Provider: start session(approvalPolicy, sandboxMode)
    else no session
        Reactor->>Provider: start session(approvalPolicy, sandboxMode)
    end
    Provider-->>Reactor: session details
    Reactor->>Ingest: emit thread.session.set(..., approvalPolicy, sandboxMode)
    Ingest->>Ingest: update projections / persistence with new fields
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and accurately describes the main change: adding approvalPolicy and sandboxMode propagation through the thread turn startup flow, which is the core objective of this PR.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codething/2c75aea7

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Existing session ignores runtime mode changes
    • Added in-memory tracking of per-thread session runtime settings (approvalPolicy/sandboxMode) so that when ensureSessionForThread detects the requested settings differ from the stored ones, it stops the old session and creates a new one with the updated configuration.

Create PR

Or push these changes by commenting:

@cursor push 9ee36a6e77
Preview (9ee36a6e77)
diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
--- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
+++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
@@ -127,6 +127,11 @@
     return readModel.threads.find((entry) => entry.id === threadId);
   });
 
+  const sessionRuntimeSettings = new Map<
+    string,
+    { approvalPolicy?: ProviderApprovalPolicy; sandboxMode?: ProviderSandboxMode }
+  >();
+
   const ensureSessionForThread = Effect.fnUntraced(function* (
     threadId: ThreadId,
     createdAt: string,
@@ -143,7 +148,15 @@
 
     const existingSessionId = thread.session?.providerSessionId;
     if (existingSessionId) {
-      return existingSessionId;
+      const stored = sessionRuntimeSettings.get(threadId);
+      const runtimeModeChanged =
+        (options?.approvalPolicy !== undefined &&
+          options.approvalPolicy !== stored?.approvalPolicy) ||
+        (options?.sandboxMode !== undefined && options.sandboxMode !== stored?.sandboxMode);
+      if (!runtimeModeChanged) {
+        return existingSessionId;
+      }
+      yield* providerService.stopSession({ sessionId: existingSessionId });
     }
 
     const preferredProvider: ProviderKind | undefined =
@@ -163,6 +176,11 @@
       ...(options?.sandboxMode !== undefined ? { sandboxMode: options.sandboxMode } : {}),
     });
 
+    sessionRuntimeSettings.set(threadId, {
+      approvalPolicy: options?.approvalPolicy,
+      sandboxMode: options?.sandboxMode,
+    });
+
     yield* setThreadSession({
       threadId,
       session: {
@@ -314,6 +332,8 @@
       yield* providerService.stopSession({ sessionId });
     }
 
+    sessionRuntimeSettings.delete(thread.id);
+
     yield* setThreadSession({
       threadId: thread.id,
       session: {

Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts Outdated
@juliusmarminge juliusmarminge force-pushed the codething/2c75aea7 branch 2 times, most recently from aedb803 to 5fdf30b Compare February 27, 2026 03:31
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Runtime keybindings file accidentally committed
    • Removed the entire apps/server/.t3/ runtime directory (keybindings.json, SQLite state, and log files) from git tracking and added .t3/ to .gitignore to prevent future accidental commits.

Create PR

Or push these changes by commenting:

@cursor push 03dd03cc9e
Preview (03dd03cc9e)
diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,5 @@
 .env.local
 build/
 .logs/
+.t3/
 release/

diff --git a/apps/server/.t3/keybindings.json b/apps/server/.t3/keybindings.json
deleted file mode 100644
--- a/apps/server/.t3/keybindings.json
+++ /dev/null
@@ -1,45 +1,0 @@
-[
-  {
-    "key": "mod+j",
-    "command": "terminal.toggle"
-  },
-  {
-    "key": "mod+d",
-    "command": "terminal.split",
-    "when": "terminalFocus"
-  },
-  {
-    "key": "mod+n",
-    "command": "terminal.new",
-    "when": "terminalFocus"
-  },
-  {
-    "key": "mod+w",
-    "command": "terminal.close",
-    "when": "terminalFocus"
-  },
-  {
-    "key": "mod+n",
-    "command": "chat.new",
-    "when": "!terminalFocus"
-  },
-  {
-    "key": "mod+shift+o",
-    "command": "chat.new",
-    "when": "!terminalFocus"
-  },
-  {
-    "key": "mod+shift+n",
-    "command": "chat.newLocal",
-    "when": "!terminalFocus"
-  },
-  {
-    "key": "mod+o",
-    "command": "editor.openFavorite"
-  },
-  {
-    "key": "mod+d",
-    "command": "diff.toggle",
-    "when": "!terminalFocus"
-  }
-]
\ No newline at end of file

diff --git a/apps/server/.t3/logs/providers/provider-canonical.ndjson b/apps/server/.t3/logs/providers/provider-canonical.ndjson
deleted file mode 100644

diff --git a/apps/server/.t3/logs/providers/provider-native.ndjson b/apps/server/.t3/logs/providers/provider-native.ndjson
deleted file mode 100644

diff --git a/apps/server/.t3/state.sqlite b/apps/server/.t3/state.sqlite
deleted file mode 100644
--- a/apps/server/.t3/state.sqlite
+++ /dev/null
@@ -1,196 +1,0 @@
-SQLite format 3������@  �������1�����������������������������������������������������������������.�������������-������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
����� ������s�D� ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������"���3#2026-02-27 03:19:21Projections-���392026-02-27 03:19:21ProviderSessionRuntime*���332026-02-27 03:19:21CheckpointDiffBlobs3���3E2026-02-27 03:19:21OrchestrationCommandReceipts*���332026-02-27 03:19:21OrchestrationEvents
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������m���U�U�+=U�U��=�872bca1f-73be-4346-8b52-570c4174f728project6d7b7d04-791e-4c47-812b-9f3dcdc91b83project.created2026-02-27T03:19:21.859Zd62dcca7-5310-4e5e-ba59-2602d655f203d62dcca7-5310-4e5e-ba59-2602d655f203client{"projectId":"6d7b7d04-791e-4c47-812b-9f3dcdc91b83","title":"server","workspaceRoot":"/Users/julius/.t3/worktrees/codething-mvp/codething-2c75aea7/apps/server","defaultModel":"gpt-5-codex","scripts":[],"createdAt":"2026-02-27T03:19:21.859Z","updatedAt":"2026-02-27T03:19:21.859Z"}{}
-�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'�U	872bca1f-73be-4346-8b52-570c4174f728
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������5	orchestration_events
-��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0��U�	project6d7b7d04-791e-4c47-812b-9f3dcdc91b83
-��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0��U		project6d7b7d04-791e-4c47-812b-9f3dcdc91b83
-�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'�U	d62dcca7-5310-4e5e-ba59-2602d655f203
-�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'�U	d62dcca7-5310-4e5e-ba59-2602d655f203
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������w��U�U=	��d62dcca7-5310-4e5e-ba59-2602d655f203project6d7b7d04-791e-4c47-812b-9f3dcdc91b832026-02-27T03:19:21.859Zaccepted
-�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'�U	d62dcca7-5310-4e5e-ba59-2602d655f203
... diff truncated: showing 80 of 284 lines

Comment thread apps/server/.t3/keybindings.json Outdated
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Read model left inconsistent when session restart fails
    • Added Effect.tapError to the startProviderSession call in the restart path to clear the read model session (set providerSessionId to null with error status) when the restart fails after the old session has been stopped, preventing subsequent turns from reusing a dead session ID.

Create PR

Or push these changes by commenting:

@cursor push 4505053a05
Preview (4505053a05)
diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
--- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
+++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
@@ -186,7 +186,8 @@
     const existingSessionId = thread.session?.providerSessionId;
     if (existingSessionId) {
       const approvalPolicyChanged =
-        options?.approvalPolicy !== undefined && options.approvalPolicy !== thread.session?.approvalPolicy;
+        options?.approvalPolicy !== undefined &&
+        options.approvalPolicy !== thread.session?.approvalPolicy;
       const sandboxModeChanged =
         options?.sandboxMode !== undefined && options.sandboxMode !== thread.session?.sandboxMode;
 
@@ -195,7 +196,26 @@
       }
 
       yield* providerService.stopSession({ sessionId: existingSessionId });
-      const restartedSession = yield* startProviderSession(thread.session?.providerThreadId ?? null);
+      const restartedSession = yield* startProviderSession(
+        thread.session?.providerThreadId ?? null,
+      ).pipe(
+        Effect.tapError(() =>
+          setThreadSession({
+            threadId,
+            session: {
+              threadId,
+              status: "error",
+              providerName: thread.session?.providerName ?? null,
+              providerSessionId: null,
+              providerThreadId: thread.session?.providerThreadId ?? null,
+              activeTurnId: null,
+              lastError: null,
+              updatedAt: createdAt,
+            },
+            createdAt,
+          }),
+        ),
+      );
       yield* bindSessionToThread(restartedSession);
       return restartedSession.sessionId;
     }

Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
juliusmarminge and others added 4 commits February 26, 2026 20:48
- Add `approvalPolicy` and `sandboxMode` to turn-start command and requested payload contracts
- Pass runtime mode-derived values from `ChatView` when dispatching `thread.turn.start`
- Thread provider options through decider/reactor into session startup, with tests updated
- Persist `approvalPolicy` and `sandboxMode` on orchestration sessions
- Reuse existing sessions when runtime mode is unchanged
- Stop and recreate provider sessions when runtime mode settings change
- Add reactor tests for reuse vs restart behavior
- add default `.t3/keybindings.json` for terminal/chat/editor/diff shortcuts
- include initial provider log files and SQLite state artifacts under `apps/server/.t3`
Use conditional spreading for these properties to handle undefined
values correctly with exactOptionalPropertyTypes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
- Around line 146-147: desiredApprovalPolicy and desiredSandboxMode currently
fallback to thread.session values, but after an explicit stop those properties
are missing; update the fallback logic so after options you check for
preserved/session-history values before using thread.session directly (e.g.,
options?.approvalPolicy ?? thread.session?.approvalPolicy ??
thread.previousSession?.approvalPolicy ?? defaultApprovalPolicy and similarly
for sandboxMode), and if no such history field exists add and use a stable store
on Thread (e.g., previousSession or sessionSnapshot set before stop) so
ProviderCommandReactor's desiredApprovalPolicy and desiredSandboxMode always
resolve to the last known policy/mode.
- Around line 197-201: The current restart sequence stops the old session via
providerService.stopSession(existingSessionId) before calling
startProviderSession and bindSessionToThread, which can leave the thread bound
to a stale/empty session if start/bind fails; change the flow to first call
startProviderSession(thread.session?.providerThreadId ?? null), then
bindSessionToThread(restartedSession), and only after successful bind call
providerService.stopSession(existingSessionId); alternatively (if stopping first
is required) wrap the startProviderSession/bindSessionToThread calls in a
try/catch and on failure attempt to restore the old session by
re-creating/re-binding existingSessionId so thread.session remains consistent.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0aff07 and 422160a.

📒 Files selected for processing (7)
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
  • apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
  • apps/server/src/orchestration/decider.projectScripts.test.ts
  • apps/server/src/orchestration/decider.ts
  • apps/web/src/components/ChatView.tsx
  • packages/contracts/src/orchestration.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
  • apps/server/src/orchestration/decider.ts
  • apps/server/src/orchestration/decider.projectScripts.test.ts

Comment on lines +146 to +147
const desiredApprovalPolicy = options?.approvalPolicy ?? thread.session?.approvalPolicy;
const desiredSandboxMode = options?.sandboxMode ?? thread.session?.sandboxMode;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fallback policy/mode continuity breaks after explicit session stops.

Line 146 and Line 147 fall back to values on thread.session, but the stop path writes a stopped session without approvalPolicy/sandboxMode, so those fallbacks become unavailable after a stop.

💡 Suggested fix
     yield* setThreadSession({
       threadId: thread.id,
       session: {
         threadId: thread.id,
         status: "stopped",
         providerName: thread.session?.providerName ?? null,
         providerSessionId: null,
         providerThreadId: null,
+        ...(thread.session?.approvalPolicy !== undefined
+          ? { approvalPolicy: thread.session.approvalPolicy }
+          : {}),
+        ...(thread.session?.sandboxMode !== undefined
+          ? { sandboxMode: thread.session.sandboxMode }
+          : {}),
         activeTurnId: null,
         lastError: thread.session?.lastError ?? null,
         updatedAt: now,
       },
       createdAt: now,
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/orchestration/Layers/ProviderCommandReactor.ts` around lines
146 - 147, desiredApprovalPolicy and desiredSandboxMode currently fallback to
thread.session values, but after an explicit stop those properties are missing;
update the fallback logic so after options you check for
preserved/session-history values before using thread.session directly (e.g.,
options?.approvalPolicy ?? thread.session?.approvalPolicy ??
thread.previousSession?.approvalPolicy ?? defaultApprovalPolicy and similarly
for sandboxMode), and if no such history field exists add and use a stable store
on Thread (e.g., previousSession or sessionSnapshot set before stop) so
ProviderCommandReactor's desiredApprovalPolicy and desiredSandboxMode always
resolve to the last known policy/mode.

Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.ts Outdated
- Make `approvalPolicy` and `sandboxMode` required in orchestration contracts and turn-start flow
- Add defaults in provider reactors/ingestion to guarantee values are always set
- Store and hydrate both fields in projection persistence, snapshots, and related tests
- Reorder restart flow to bind the new provider session before stopping the old one
- Log (and swallow) stop-session failures for superseded sessions
- Add regression test ensuring failed restart does not stop the active session
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts (1)

201-204: ⚠️ Potential issue | 🟠 Major

Restart sequence still has a failure window after the old session is stopped.

At Line 201, the old session is stopped before replacement startup/bind completes. If startup fails, the thread can be left without a recoverable active provider session.

Based on learnings: Keep behavior predictable under load and during failures (session restarts, reconnects, partial streams).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/orchestration/Layers/ProviderCommandReactor.ts` around lines
201 - 204, The current sequence calls
providerService.stopSession(existingSessionId) before starting and binding the
replacement session, which leaves the thread without a recoverable session if
startup fails; instead create the new session first (call
startProviderSession(thread.session?.providerThreadId ?? null) and bind it with
bindSessionToThread(restartedSession)), verify startup succeeded, then
atomically swap by stopping the old session via
providerService.stopSession(existingSessionId) (or schedule the old session for
teardown after confirming the new one is bound); also ensure to handle cleanup
on startProviderSession failure (do not stop the old session) and guard against
concurrent restarts by using the thread/session restart lock or flag used
elsewhere.
🧹 Nitpick comments (1)
apps/server/src/orchestration/projector.test.ts (1)

198-199: Add explicit assertions for the new session runtime fields.

This test now provides approvalPolicy/sandboxMode but does not verify they are projected. As this PR is about propagating these fields, asserting them here would prevent silent regressions.

Suggested test assertion patch
     const thread = afterRunning.threads[0];
     expect(thread?.latestTurnId).toBe("turn-1");
     expect(thread?.session?.status).toBe("running");
+    expect(thread?.session?.approvalPolicy).toBe("on-request");
+    expect(thread?.session?.sandboxMode).toBe("workspace-write");

Also applies to: 209-212

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/orchestration/projector.test.ts` around lines 198 - 199, The
test in projector.test.ts sets approvalPolicy and sandboxMode but never asserts
them; add explicit assertions that the projected session runtime contains
approvalPolicy === "on-request" and sandboxMode === "workspace-write" (e.g.
assert on the projected object's session.runtime.approvalPolicy and
session.runtime.sandboxMode) in the same two assertion blocks currently
validating the projection (the blocks around the existing checks for the
projected session), so regressions to propagating these fields are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts`:
- Around line 29-30: DEFAULT_APPROVAL_POLICY currently set to "never" causes
missing/unknown session policy to silently disable approvals; change the
constant DEFAULT_APPROVAL_POLICY to a fail-safe value (e.g., "explicit" or
whatever ProviderApprovalPolicy value means "require explicit approval") and
update the two fallback branches in ProviderRuntimeIngestion that currently
apply the old default so they either (a) use the new fail-safe default or (b)
throw/return an error when session state/policy is unknown; ensure you update
both places where DEFAULT_APPROVAL_POLICY is referenced in the fallback logic so
unknown policies no longer silently bypass approvals.

In `@apps/server/src/persistence/Migrations/005_Projections.ts`:
- Around line 68-69: Don't edit the existing migration 005_Projections.ts;
instead create a new rollout-safe migration that ALTER TABLEs
projection_thread_sessions to add the two new columns (approval_policy and
sandbox_mode) so existing DBs receive them; in the new migration use ALTER TABLE
... ADD COLUMN for each column, make them either nullable or provide reasonable
DEFAULT values, and include any necessary backfill/update statements and a safe
down migration to remove the columns; reference projection_thread_sessions,
approval_policy, and sandbox_mode when implementing the change.

---

Duplicate comments:
In `@apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
- Around line 201-204: The current sequence calls
providerService.stopSession(existingSessionId) before starting and binding the
replacement session, which leaves the thread without a recoverable session if
startup fails; instead create the new session first (call
startProviderSession(thread.session?.providerThreadId ?? null) and bind it with
bindSessionToThread(restartedSession)), verify startup succeeded, then
atomically swap by stopping the old session via
providerService.stopSession(existingSessionId) (or schedule the old session for
teardown after confirming the new one is bound); also ensure to handle cleanup
on startProviderSession failure (do not stop the old session) and guard against
concurrent restarts by using the thread/session restart lock or flag used
elsewhere.

---

Nitpick comments:
In `@apps/server/src/orchestration/projector.test.ts`:
- Around line 198-199: The test in projector.test.ts sets approvalPolicy and
sandboxMode but never asserts them; add explicit assertions that the projected
session runtime contains approvalPolicy === "on-request" and sandboxMode ===
"workspace-write" (e.g. assert on the projected object's
session.runtime.approvalPolicy and session.runtime.sandboxMode) in the same two
assertion blocks currently validating the projection (the blocks around the
existing checks for the projected session), so regressions to propagating these
fields are caught.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 422160a and 4d791fe.

📒 Files selected for processing (19)
  • apps/server/integration/orchestrationEngine.integration.test.ts
  • apps/server/src/orchestration/Layers/CheckpointReactor.test.ts
  • apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts
  • apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts
  • apps/server/src/orchestration/Layers/ProjectionPipeline.ts
  • apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts
  • apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
  • apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts
  • apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
  • apps/server/src/orchestration/commandInvariants.test.ts
  • apps/server/src/orchestration/decider.ts
  • apps/server/src/orchestration/projector.test.ts
  • apps/server/src/persistence/Layers/ProjectionThreadSessions.ts
  • apps/server/src/persistence/Migrations/005_Projections.ts
  • apps/server/src/persistence/Services/ProjectionThreadSessions.ts
  • apps/server/src/wsServer.test.ts
  • packages/contracts/src/orchestration.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/server/src/orchestration/decider.ts

Comment on lines +29 to +30
const DEFAULT_APPROVAL_POLICY: ProviderApprovalPolicy = "never";
const DEFAULT_SANDBOX_MODE: ProviderSandboxMode = "workspace-write";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fallback approval policy is overly permissive for unknown session state.

Line 29 defaults to "never", and that value is applied in both fallback paths (Line 378 and Line 488). When policy is missing, this silently disables approvals instead of failing safe.

Safer fallback
-const DEFAULT_APPROVAL_POLICY: ProviderApprovalPolicy = "never";
+const DEFAULT_APPROVAL_POLICY: ProviderApprovalPolicy = "on-request";

Also applies to: 378-379, 488-489

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts` around
lines 29 - 30, DEFAULT_APPROVAL_POLICY currently set to "never" causes
missing/unknown session policy to silently disable approvals; change the
constant DEFAULT_APPROVAL_POLICY to a fail-safe value (e.g., "explicit" or
whatever ProviderApprovalPolicy value means "require explicit approval") and
update the two fallback branches in ProviderRuntimeIngestion that currently
apply the old default so they either (a) use the new fail-safe default or (b)
throw/return an error when session state/policy is unknown; ensure you update
both places where DEFAULT_APPROVAL_POLICY is referenced in the fallback logic so
unknown policies no longer silently bypass approvals.

Comment thread apps/server/src/persistence/Migrations/005_Projections.ts Outdated
- Turn off `preferSchemaOverJson`
- Turn off `globalErrorInEffectFailure`
@juliusmarminge juliusmarminge merged commit f9752d7 into main Feb 27, 2026
4 checks passed
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Inconsistent default approval policy across modules
    • Changed DEFAULT_APPROVAL_POLICY in ProviderCommandReactor.ts from "never" to "on-request" to match ProviderRuntimeIngestion.ts, ensuring consistent and safe fallback behavior.
  • ✅ Fixed: Required schema fields break replay of old events
    • Made approvalPolicy and sandboxMode fields optional with decoding defaults in OrchestrationSession and ThreadTurnStartRequestedPayload schemas, so old events without these fields can be decoded during bootstrap replay.

Create PR

Or push these changes by commenting:

@cursor push 7491351d10
Preview (7491351d10)
diff --git a/apps/server/src/orchestration/Layers/ProjectionPipeline.ts b/apps/server/src/orchestration/Layers/ProjectionPipeline.ts
--- a/apps/server/src/orchestration/Layers/ProjectionPipeline.ts
+++ b/apps/server/src/orchestration/Layers/ProjectionPipeline.ts
@@ -473,8 +473,8 @@
         providerName: event.payload.session.providerName,
         providerSessionId: event.payload.session.providerSessionId,
         providerThreadId: event.payload.session.providerThreadId,
-        approvalPolicy: event.payload.session.approvalPolicy,
-        sandboxMode: event.payload.session.sandboxMode,
+        approvalPolicy: event.payload.session.approvalPolicy ?? "on-request",
+        sandboxMode: event.payload.session.sandboxMode ?? "workspace-write",
         activeTurnId: event.payload.session.activeTurnId,
         lastError: event.payload.session.lastError,
         updatedAt: event.payload.session.updatedAt,

diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
--- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
+++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts
@@ -64,7 +64,7 @@
 
 const HANDLED_TURN_START_KEY_MAX = 10_000;
 const HANDLED_TURN_START_KEY_TTL = Duration.minutes(30);
-const DEFAULT_APPROVAL_POLICY: ProviderApprovalPolicy = "never";
+const DEFAULT_APPROVAL_POLICY: ProviderApprovalPolicy = "on-request";
 const DEFAULT_SANDBOX_MODE: ProviderSandboxMode = "workspace-write";
 
 const make = Effect.gen(function* () {
@@ -279,8 +279,8 @@
       ...(message.attachments !== undefined ? { attachments: message.attachments } : {}),
       ...(event.payload.model !== undefined ? { model: event.payload.model } : {}),
       ...(event.payload.effort !== undefined ? { effort: event.payload.effort } : {}),
-      approvalPolicy: event.payload.approvalPolicy,
-      sandboxMode: event.payload.sandboxMode,
+      approvalPolicy: event.payload.approvalPolicy ?? DEFAULT_APPROVAL_POLICY,
+      sandboxMode: event.payload.sandboxMode ?? DEFAULT_SANDBOX_MODE,
       createdAt: event.payload.createdAt,
     });
   });

diff --git a/packages/contracts/src/orchestration.ts b/packages/contracts/src/orchestration.ts
--- a/packages/contracts/src/orchestration.ts
+++ b/packages/contracts/src/orchestration.ts
@@ -142,8 +142,12 @@
   providerName: Schema.NullOr(TrimmedNonEmptyString),
   providerSessionId: Schema.NullOr(ProviderSessionId),
   providerThreadId: Schema.NullOr(ProviderThreadId),
-  approvalPolicy: ProviderApprovalPolicy,
-  sandboxMode: ProviderSandboxMode,
+  approvalPolicy: Schema.optional(ProviderApprovalPolicy).pipe(
+    Schema.withDecodingDefault(() => "on-request" as ProviderApprovalPolicy),
+  ),
+  sandboxMode: Schema.optional(ProviderSandboxMode).pipe(
+    Schema.withDecodingDefault(() => "workspace-write" as ProviderSandboxMode),
+  ),
   activeTurnId: Schema.NullOr(TurnId),
   lastError: Schema.NullOr(TrimmedNonEmptyString),
   updatedAt: IsoDateTime,
@@ -500,8 +504,12 @@
   model: Schema.optional(TrimmedNonEmptyString),
   effort: Schema.optional(TrimmedNonEmptyString),
   assistantDeliveryMode: Schema.optional(AssistantDeliveryMode),
-  approvalPolicy: ProviderApprovalPolicy,
-  sandboxMode: ProviderSandboxMode,
+  approvalPolicy: Schema.optional(ProviderApprovalPolicy).pipe(
+    Schema.withDecodingDefault(() => "on-request" as ProviderApprovalPolicy),
+  ),
+  sandboxMode: Schema.optional(ProviderSandboxMode).pipe(
+    Schema.withDecodingDefault(() => "workspace-write" as ProviderSandboxMode),
+  ),
   createdAt: IsoDateTime,
 });

const HANDLED_TURN_START_KEY_MAX = 10_000;
const HANDLED_TURN_START_KEY_TTL = Duration.minutes(30);
const DEFAULT_APPROVAL_POLICY: ProviderApprovalPolicy = "never";
const DEFAULT_SANDBOX_MODE: ProviderSandboxMode = "workspace-write";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent default approval policy across modules

Medium Severity

DEFAULT_APPROVAL_POLICY is "never" in ProviderCommandReactor.ts but "on-request" in ProviderRuntimeIngestion.ts. Both are used as fallbacks when thread.session?.approvalPolicy is undefined. This means session status updates from runtime events (e.g., turn.started, session.exited, runtime.error) will record "on-request", while session stops from ProviderCommandReactor will record "never". The "never" default is the less safe option, allowing tools to run without user approval in fallback scenarios.

Additional Locations (1)

Fix in Cursor Fix in Web

providerSessionId: Schema.NullOr(ProviderSessionId),
providerThreadId: Schema.NullOr(ProviderThreadId),
approvalPolicy: ProviderApprovalPolicy,
sandboxMode: ProviderSandboxMode,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required schema fields break replay of old events

High Severity

Adding approvalPolicy and sandboxMode as required (non-optional) fields to OrchestrationSession and ThreadTurnStartRequestedPayload breaks backward compatibility with events already persisted in the event store. The engine bootstrap replays all events via Schema.decodeUnknownEffect(OrchestrationEvent), and old thread.session-set and thread.turn-start-requested events that lack these fields will fail schema validation, preventing the application from starting. These fields need Schema.optional with a default (or equivalent) to be decode-compatible with pre-existing events.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant