[codex] add configurable automatic git fetch interval#2605
[codex] add configurable automatic git fetch interval#2605juliusmarminge merged 11 commits intomainfrom
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 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)
Comment |
| @@ -253,6 +266,7 @@ export const layer = Layer.effect( | |||
|
|
|||
| const retainRemotePoller = Effect.fn("VcsStatusBroadcaster.retainRemotePoller")(function* ( | |||
There was a problem hiding this comment.
🟢 Low vcs/VcsStatusBroadcaster.ts:267
When retainRemotePoller finds an existing poller for a cwd, it increments the subscriber count but ignores the new caller's automaticRemoteRefreshEnabled preference. The first subscriber's effect controls refresh behavior for all subsequent subscribers to the same cwd, so callers expecting different refresh settings receive the wrong behavior silently.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/server/src/vcs/VcsStatusBroadcaster.ts around line 267:
When `retainRemotePoller` finds an existing poller for a `cwd`, it increments the subscriber count but ignores the new caller's `automaticRemoteRefreshEnabled` preference. The first subscriber's effect controls refresh behavior for all subsequent subscribers to the same `cwd`, so callers expecting different refresh settings receive the wrong behavior silently.
Evidence trail:
apps/server/src/vcs/VcsStatusBroadcaster.ts lines 267-290: `retainRemotePoller` function definition showing the `existing` branch (lines 273-279) ignores `automaticRemoteRefreshEnabled` while the new-poller branch (line 285) uses it. apps/server/src/vcs/VcsStatusBroadcaster.ts lines 47-49: `StreamStatusOptions` interface defines `automaticRemoteRefreshEnabled` as an optional public option. apps/server/src/ws.ts lines 958-963: production caller passes `automaticGitFetchesEnabled`. apps/server/src/vcs/VcsStatusBroadcaster.test.ts lines 300-302: test caller passes `Effect.succeed(false)` showing the API is intended to accept different values.
|
I would suggest adding something like |
b00598c to
328f8a2
Compare
328f8a2 to
fe4dda6
Compare
fe4dda6 to
58a2775
Compare
58a2775 to
f6156b8
Compare
f6156b8 to
09c3632
Compare
09c3632 to
f47db47
Compare
f47db47 to
099bd6f
Compare
There was a problem hiding this comment.
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: layerTest deepMerge corrupts Duration when overrides include interval
- Destructured automaticGitFetchInterval out of overrides before calling deepMerge, then applied it atomically afterward, mirroring the same protection used in applyServerSettingsPatch.
Or push these changes by commenting:
@cursor push c9ba6464c7
Preview (c9ba6464c7)
diff --git a/apps/server/src/serverSettings.ts b/apps/server/src/serverSettings.ts
--- a/apps/server/src/serverSettings.ts
+++ b/apps/server/src/serverSettings.ts
@@ -139,9 +139,14 @@
Layer.effect(
ServerSettingsService,
Effect.gen(function* () {
- const initialSettings = yield* normalizeServerSettings(
- deepMerge(DEFAULT_SERVER_SETTINGS, overrides),
- );
+ const { automaticGitFetchInterval, ...overridesForMerge } = overrides;
+ const merged = deepMerge(DEFAULT_SERVER_SETTINGS, overridesForMerge);
+ const initialSettings = yield* normalizeServerSettings({
+ ...merged,
+ ...(automaticGitFetchInterval !== undefined
+ ? { automaticGitFetchInterval: automaticGitFetchInterval as Duration.Duration }
+ : {}),
+ });
const currentSettingsRef = yield* Ref.make<ServerSettings>(initialSettings);
return {You can send follow-ups to the cloud agent here.
ApprovabilityVerdict: Needs human review New feature adding configurable Git fetch interval with UI controls and runtime behavior changes. An unresolved review comment identifies a bug where multiple subscribers to the same directory receive incorrect refresh settings. You can customize Macroscope's approvability policy. Learn more. |
The layerTest method called deepMerge(DEFAULT_SERVER_SETTINGS, overrides) without excluding automaticGitFetchInterval from the merge. Since Duration values are internally structured objects, deepMerge would recurse into them and produce a corrupted plain object instead of a valid Duration. Mirror the same protection used in applyServerSettingsPatch: destructure automaticGitFetchInterval out before merging, then apply it atomically.
- Add expandable Git details row in source control settings - Keep fetch interval controls alongside Git discovery info
The layerTest method called deepMerge(DEFAULT_SERVER_SETTINGS, overrides) without excluding automaticGitFetchInterval from the merge. Since Duration values are internally structured objects, deepMerge would recurse into them and produce a corrupted plain object instead of a valid Duration. Mirror the same protection used in applyServerSettingsPatch: destructure automaticGitFetchInterval out before merging, then apply it atomically. Applied via @cursor push command
There was a problem hiding this comment.
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: Manual field conversion in
settingsInputForDecodeis fragile- Replaced the fragile manual
settingsInputForDecodefunction with the already-availableencodeServerSettingsSyncwhich properly encodes all fields, makingnormalizeServerSettingsrobust against future schema changes.
- Replaced the fragile manual
Or push these changes by commenting:
@cursor push 6294961d2c
Preview (6294961d2c)
diff --git a/apps/server/src/serverSettings.ts b/apps/server/src/serverSettings.ts
--- a/apps/server/src/serverSettings.ts
+++ b/apps/server/src/serverSettings.ts
@@ -55,17 +55,10 @@
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
-function settingsInputForDecode(settings: ServerSettings): unknown {
- return {
- ...settings,
- automaticGitFetchInterval: Duration.toMillis(settings.automaticGitFetchInterval),
- };
-}
-
const normalizeServerSettings = (
settings: ServerSettings,
): Effect.Effect<ServerSettings, ServerSettingsError> =>
- decodeServerSettings(settingsInputForDecode(settings)).pipe(
+ decodeServerSettings(encodeServerSettingsSync(settings)).pipe(
Effect.mapError(
(cause) =>
new ServerSettingsError({You can send follow-ups to the cloud agent here.
… in normalizeServerSettings settingsInputForDecode manually converted only automaticGitFetchInterval to millis while spreading the rest of the decoded object. This is fragile because any future field with a non-identity encoding (e.g. another DurationFromMillis) would need to be added manually, with no type-level safety net. Use the already-available encodeServerSettingsSync which properly handles all fields, making normalizeServerSettings robust against future schema changes. Applied via @cursor push command
- Switch archived thread state to `effect/Cause`, `effect/Effect`, and `effect/Option` imports
- Replace `new Date(0).toISOString()` with the canonical epoch string - Keep server tests aligned with the snapshot fallback
- Encode settings through schema effects before persisting - Emit sparse settings as pretty JSON when saving
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue. You can view the agent here.
Reviewed by Cursor Bugbot for commit f27a9aa. Configure here.
- Normalize provider and settings string fields - Add tests for trimmed patch decoding and encoded output
- Write sparse server settings directly from the default-stripped object - Extend tests to cover automatic Git fetch interval serialization




Summary
Adds a Source Control setting for configuring the background Git fetch interval. The default remains 30 seconds, and setting the interval to
0disables automatic fetches while preserving explicit Git actions.What changed
automaticGitFetchesboolean withautomaticGitFetchInterval, stored as an Effect duration setting with millisecond JSON encoding.Fetch intervalnumber field to the Source Control settings page, with0 secondsshown as disabled.git fetch.SSH_ASKPASS_REQUIRE=neveron background upstream status fetches so OpenSSH askpass dialogs are not triggered by passive refreshes.Why
Background
git fetchcan trigger SSH agent, passphrase, Touch ID, security-key, or Windows GCM prompts for users with secure Git setups. Making the interval configurable lets users reduce that background activity, and0lets those prompts happen only on explicit Git actions. The OpenSSHSSH_ASKPASS_REQUIRE=neverguard also prevents passive refreshes from opening askpass UI when a fetch still runs.Closes #356
Closes #1190
Closes #1418
Closes #1467
Closes #1965
Closes #2285
Refs #1921
Validation
bun fmtbun lint(passes with existing warnings)bun typecheckbun run test --filter=t3 -- src/vcs/VcsStatusBroadcaster.test.tsbun run test --filter=t3 -- src/vcs/GitVcsDriverCore.test.tsbun run test --filter=t3 -- src/serverSettings.test.tsbun run test --filter=@t3tools/web -- src/rpc/wsTransport.test.tsbun run test:browser src/components/settings/SettingsPanels.browser.tsxbun run test:browser src/components/ChatView.browser.tsxbun run test:browser src/components/KeybindingsToast.browser.tsxbun run test:browserNote
Medium Risk
Touches server settings normalization/persistence and VCS background polling behavior; misconfiguration could change remote status refresh cadence or settings serialization, but the change is scoped and covered by tests.
Overview
Adds a new
ServerSettings.automaticGitFetchInterval(default 30s,0disables) and threads it through thesubscribeVcsStatusWebSocket flow so background remote status refresh/polling respects the configured interval.Updates Git background upstream fetches to run with
SSH_ASKPASS_REQUIRE=neverto avoid triggering askpass prompts during passive refreshes, and extends the Source Control settings UI with a per-Git collapsible “Fetch interval” control (including reset-to-default behavior).Refactors settings patching/serialization to round-trip normalize settings via schema encode/decode, persist sparse settings via schema JSON encoding, treat
automaticGitFetchIntervalas an atomic key, and broadens string normalization by makingTrimmedStringtrim on both decode and encode (with test updates to expect encoded wire shapes).Reviewed by Cursor Bugbot for commit 8c99160. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add configurable automatic Git fetch interval to server settings
automaticGitFetchInterval(default 30s) toServerSettingsandServerSettingsPatchin settings.ts, stored asDurationFromMillis.ServerSettingsServiceand passes it toVcsStatusBroadcaster.streamStatus, falling back to the default on read failure.Duration.zeroand uses the configured interval per subscription.SSH_ASKPASS_REQUIRE=nevervia a new env override in GitVcsDriverCore.ts to prevent interactive prompts.Macroscope summarized 8c99160.