Add per-project settings #2567
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review Diff is too large for automated approval analysis. A human reviewer should evaluate this PR. You can customize Macroscope's approvability policy. Learn more. |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Key vcs action commands by environment and cwd again so all operations on a worktree share one serial lock; the project context rides along from the requesting target instead of forking the key - Make ResolvedVcsActionTarget.projectId optional to match - Log a warning when a settings read failure skips the override lookup - Seed the canonical default model when neither a project default nor a sticky selection exists - Resolve project script keybindings from the project's own environment config instead of always using the primary environment - Roll back the optimistic settings draft when a commit RPC fails so the UI does not present rejected edits as saved Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The command cache is keyed by [environmentId, cwd], so a projectId captured from the first requester leaked into later invocations from other project views. Carry it on RunVcsStackedActionInput instead so every call sends its own project context, and widen the PR resolution input helper for exactOptionalPropertyTypes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Refresh all sibling cache entries (bare-cwd and project-scoped) on any status refresh instead of only project entries on bare-cwd refreshes, and clear project-settings draft keys only after the post-commit refresh lands so server-normalized values are not shadowed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # apps/mobile/app.config.ts # apps/mobile/src/features/agent-awareness/remoteRegistration.ts # apps/mobile/src/features/settings/SettingsRouteScreen.tsx # apps/server/src/git/GitManager.ts # apps/server/src/provider/providerSnapshot.ts # apps/server/src/vcs/VcsStatusBroadcaster.ts # apps/web/src/components/ChatMarkdown.tsx # apps/web/src/components/ChatView.tsx # apps/web/src/components/ProjectScriptsControl.tsx # apps/web/src/components/Sidebar.tsx # apps/web/src/components/chat/ChatComposer.tsx # apps/web/src/components/chat/MessagesTimeline.test.tsx # apps/web/src/components/chat/OpenInPicker.tsx # apps/web/src/composerDraftStore.ts # apps/web/src/hooks/useHandleNewThread.ts # apps/web/src/providerInstances.ts # apps/web/src/routeTree.gen.ts # apps/web/src/routes/_chat.$environmentId.$threadId.tsx # packages/client-runtime/src/operations/projects.test.ts # packages/contracts/src/model.ts
| <ServerIcon className="size-3.5 shrink-0" /> | ||
| <span className="truncate">{currentEnvironmentLabel}</span> | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
Switcher hidden on details failure
Medium Severity
The new environment Select only renders after projectDetails.data loads. Sidebar V2 always opens the representative member first, and projectLocations already comes from local grouping state. When that representative’s details RPC fails, sibling environments never appear, so users cannot switch to a working entry.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 23eb95e. Configure here.
| }); | ||
| }, | ||
| [], | ||
| [router], |
There was a problem hiding this comment.
Grouped bulk remove removed
Medium Severity
The sidebar project dialog’s “Remove all entries” flow was deleted and not re-homed. Project settings only call deleteProject for the current route member, so V2 users with a multi-environment group must switch and remove each entry separately, with no remaining bulk cleanup path.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 23eb95e. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
There are 5 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8e497de. Configure here.
| toDispatchCommandError(cause, "Failed to dispatch orchestration command"), | ||
| toDispatchCommandError(cause, "Failed to read thread project settings"), | ||
| ), | ||
| ); |
There was a problem hiding this comment.
Provider check still uses getSettings
Medium Severity
Some functions, like validateProjectProviderAccess and automaticGitFetchIntervalForProject, still fetch project settings via getSettings. This path materializes provider secrets, causing thread.turn.start commands to be rejected if secret materialization fails. These settings, such as the disabled provider list and project-specific fetch interval, don't actually require secrets.
Reviewed by Cursor Bugbot for commit 8e497de. Configure here.
| title: "Failed to remove grouped project", | ||
| description: error instanceof Error ? error.message : "An error occurred.", | ||
| }), | ||
| ); |
There was a problem hiding this comment.
Partial grouped project delete
Medium Severity
The removeProjectEverywhere function deletes grouped projects concurrently. If any deletion fails, successful ones are not rolled back, leading to an inconsistent state where some projects are removed and others remain. The UI also stays on a project that may no longer exist.
Reviewed by Cursor Bugbot for commit 8e497de. Configure here.
| ), | ||
| { concurrency: "unbounded", discard: true }, | ||
| ); | ||
| return result; |
There was a problem hiding this comment.
Sibling refresh fails primary poller
Medium Severity
After a successful primary remote refresh, sibling cache updates run inside the same effect with no error isolation. A failure refreshing one sibling project fails the whole refreshRemoteStatus, so the remote poller treats the refresh as failed and applies backoff even though the initiating project's cache was already updated.
Reviewed by Cursor Bugbot for commit 8e497de. Configure here.


Summary
Adds a project settings page for configuring behavior that belongs to one project without changing global server settings or renaming the folder on disk.
Project settings are persisted by the server and applied throughout source-control detection, VCS status, provider selection, thread startup, setup scripts, and project actions.
What changed
Project settings UI
T3CODE_*keys.Runtime integration
projects.getDetailsandprojects.updateSettingsRPCs backed by per-project settings inServerSettings.thread.turn.startwhen the selected provider is disabled for that project.Save and refresh safeguards
UI
Grouped project environments
General settings and provider availability
Custom remote, fetch interval, and project actions
Action environment
Validation
Checklist
Note
High Risk
Large changes to Git status caching, provider resolution, and orchestration dispatch gates affect core workflows; incorrect override or cache behavior could mis-attribute PRs/remotes or block turns.
Overview
Adds persisted per-project settings (remote override, disabled providers, action env, fetch interval) with
projects.getDetailsandprojects.updateSettingsRPCs that return detected Git state plus an effective remote (override when valid, otherwise detected).Source control and Git status now accept optional
projectId: overrides drive provider resolution (with cache invalidation on settings changes), status/PR caches are keyed by(cwd, projectId), and refreshes fan out to sibling cache entries for the same repo. Hosting provider on status prefers project overrides, then the branch’s configured remote, then detected context. Turn start is rejected when the chosen provider is disabled for that project; setup scripts mergeactionEnvironmentwhen settings load.Supporting changes include
getProjectSettings/updateProjectSettingson server settings (semaphore-backed merges), sharedplatformErrorhelpers for looserPlatformErrortyping in tests/CLI paths, and small tooling fixes (CLI entry cast,@pierre/diffsimport, Vitestwsinterop).Reviewed by Cursor Bugbot for commit fa95fdc. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add per-project settings with dedicated route, VCS provider overrides, and project-scoped caches
/projects/$environmentId/$projectIdroute with a full project settings UI covering model/provider selection, remote overrides, action environment variables, script management, and git fetch intervals.projects.getDetailsandprojects.updateSettingsWebSocket RPC endpoints; server settings now store per-project settings keyed byProjectId.VcsStatusBroadcasterandGitManagercaches are now segmented by(cwd, projectId)so project-scoped status entries are isolated; refreshes propagate to sibling project entries on the same repository.SourceControlProviderRegistryresolution accepts an optionalprojectIdand applies project-specific remote overrides (or infers the active project), invalidating the cache when server settings change.thread.turn.startdispatch at the RPC layer.actionEnvironmentvariables;T3CODE_*keys supplied viaextraEnvare stripped so runtime values always take precedence.Macroscope summarized fa95fdc.