[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[2/5] feat(connection): persist environment activation - #5600

Closed
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation
Closed

[2/5] feat(connection): persist environment activation#5600
DominicVonk wants to merge 4 commits into
pingdotgg:mainfrom
DominicVonk:codex/environment-activation

Conversation

@DominicVonk

@DominicVonkDominicVonk commented Aug 7, 2026

Copy link
Copy Markdown

Problem

Saved environments are always treated as desired connections. Users can remove an environment, but they cannot temporarily disable it while preserving its endpoint, credentials, cached data, and identity.

Solution

Add persistent per-environment activation state to the shared connection runtime:

  • extend the version-1 catalog document with a backward-compatible disabledEnvironmentIds default;
  • add a platform ConnectionActivationStore implemented by web and mobile storage;
  • initialize supervisors without connecting disabled environments;
  • expose a serialized setEnabled runtime command;
  • reconnect on enable and release the active session on disable;
  • retain the catalog registration and environment-owned cached data;
  • reconcile stale disabled IDs and remove activation state when an environment is deleted.

The supervisor remains the sole owner of desired state and connection lifecycle; UI clients only dispatch the typed activation command.

Review feedback addressed

  • startup remains retryable when activation reconciliation fails;
  • reconciled disabled IDs are refreshed in memory before supervisors start;
  • enable/disable and removal are serialized by the per-environment lease;
  • activation state is reset before deleting the durable registration;
  • activation persistence failures carry accurate list, set, and reconcile operation labels;
  • platform environments still start enabled when cleanup of a shadowed persisted registration fails.

User impact

An environment can be disabled and later re-enabled without pairing it again or losing its cached workspace data.

Stack

This PR is 2/5. Depends on 1/5, #5597.

Please review and merge the upstream PRs in order from 1 through 5. Because this repository does not have native stacked PRs enabled and cross-fork branches cannot be upstream base refs, the upstream diffs are cumulative. The corresponding fork PRs use the true dependent bases and provide the clean per-layer diffs.

LayerUpstream PRClean stacked diff
1#5597 — network-status recoveryfork #1
2#5600 — persistent environment activationfork #2
3#5598 — environment-management UIfork #3
4#5596 — pasted pairing-link parsingfork #4
5#5599 — composer-pill activationfork #5

Validation

Focused activation tests
Test Files 4 passed (4)
Tests 34 passed (34)
Integrated stack tests
Test Files 14 passed (14)
Tests 124 passed (124)
Type checks
@t3tools/client-runtime passed
@t3tools/web passed
@t3tools/mobile passed
Fallow (PR 2 scope)
No issues in 9 changed files; 25 inherited findings excluded

Regression coverage includes retrying startup after reconciliation failure, refreshing reconciled activation state, serializing enable/disable with removal, preserving durable registration when activation reset fails, reporting activation-specific persistence operations, and preserving platform-environment startup when shadow cleanup fails.

The repository Vite+ formatter/linter currently fails before inspecting changed files because it attempts to load vite.config.ts as an Oxlint/Oxfmt configuration. git diff --check passes; this infrastructure failure is recorded here rather than hidden.

Final review pass

Registration and activation now persist in one catalog mutation. The global activation lock is released before supervisor construction, and registration updates can preserve the existing desired state without transiently connecting. Desktop legacy migration now initializes the activation field explicitly.

Latest verification: client-runtime 47 test files / 599 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed. fallow audit --base codex/network-status-refresh passed the new-only gate with inherited findings excluded.

Rebased onto upstream main at 5661c6116 on 2026-08-07. Post-rebase verification: client-runtime 47 test files / 603 tests passed; mobile 100 test files / 624 tests passed; desktop 58 test files / 447 tests passed; client-runtime, web, mobile, and desktop typechecks passed.

Model: GPT-5; harness: Codex.


Note

Medium Risk
Touches core connection startup, supervisor desired state, and catalog persistence across platforms; incorrect activation or locking could leave environments stuck disconnected or briefly connected when disabled.

Overview
Adds persistent per-environment activation so saved environments can stay registered but stay disconnected when disabled.

The connection catalog gains a backward-compatible disabledEnvironmentIds field, a ConnectionActivationStore on web/mobile storage, and registration now takes an enabled flag in one catalog mutation. EnvironmentRegistry loads disabled IDs at startup, reconciles stale entries, seeds supervisors with the right desired state (no auto-connect for disabled envs), and exposes setEnabled to connect or disconnect without removing credentials or cache.

Connectivity.followNetworkStatus centralizes network change + app-wakeup handling (revision/lock so in-flight reads don’t stomp newer reports); the registry, supervisor, and relay discovery switch to it. Mobile drops the extra AppState network probe on connectivity changes (wakeups still handle foreground refresh). Connection startup retries on activation reconciliation failure.

A serialized setEnabled command is wired through client state for UI callers.

Reviewed by Cursor Bugbot for commit 1306054. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Persist environment activation state across restarts in the connection registry

  • Adds a ConnectionActivationStore service (web and mobile storage layers) and extends ConnectionCatalogDocument with a disabledEnvironmentIds field to persist per-environment enabled/disabled state.
  • EnvironmentRegistry now loads activation state on start, reconciles it against current targets, and creates supervisors with initiallyDesired reflecting activation rather than always connecting eagerly.
  • Adds EnvironmentRegistry.setEnabled to toggle activation at runtime, immediately connecting or disconnecting the supervisor and persisting the choice.
  • Platform-managed environments are force-enabled in activation; removing an environment clears its disabled tracking both in-memory and in persistence.
  • Introduces Connectivity.followNetworkStatus helper (used by both the registry and EnvironmentSupervisor) that serializes status application, deduplicates in-flight refreshes, and handles wakeup-driven status recovery — fixing missed network transitions during app suspension.
  • Risk: EnvironmentRegistry.start now returns ConnectionPersistenceError on failure; callers that previously assumed infallible startup will need to handle this error type.

Macroscope summarized 1306054.

@coderabbitai

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 438a924d-9363-480e-a6a9-bb80ae716cf9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

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

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 7, 2026
@DominicVonkDominicVonk changed the title feat(connection): persist environment activation[2/5] feat(connection): persist environment activationAug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated

@macroscopeappmacroscopeappBot left a comment

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.

The activation-store work looks consistent with the service conventions in packages/client-runtime and apps/web, but apps/mobile/src/connection/storage.ts wires the new ConnectionPersistenceError operation literals to the wrong stores: target/registration failures now report activation operations, and the activation store reports target/registration operations. That breaks the stable operation diagnostic context the error is meant to carry (and diverges from the correct mapping in apps/web/src/connection/storage.ts).

Posted via Macroscope — Effect Service Conventions

Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
Comment threadapps/mobile/src/connection/storage.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from 4f7779c to f446ef5CompareAugust 7, 2026 10:45
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f446ef5 to 8024e7aCompareAugust 7, 2026 10:55
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 8024e7a to e691877CompareAugust 7, 2026 11:02
@DominicVonk
DominicVonk marked this pull request as ready for review August 7, 2026 11:08
Comment threadpackages/client-runtime/src/relay/discovery.ts
@macroscopeapp

macroscopeappBot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new feature for persisting environment activation state across sessions, with changes spanning multiple platforms and affecting connection startup/management behavior. A high-severity open review comment also identifies a potential backoff timing bug that should be addressed.

You can customize Macroscope's approvability policy. Learn more.

@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from e691877 to cdf68f5CompareAugust 7, 2026 11:27
Comment threadpackages/client-runtime/src/connection/connectivity.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from cdf68f5 to d1b7450CompareAugust 7, 2026 11:29
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch 3 times, most recently from b54f674 to f260154CompareAugust 7, 2026 11:44
Comment threadpackages/client-runtime/src/relay/discovery.ts Outdated
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from f260154 to fe0db84CompareAugust 7, 2026 12:00
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 7, 2026
Comment threadpackages/client-runtime/src/connection/registry.ts
Comment threadpackages/client-runtime/src/connection/registry.ts Outdated
Comment threadpackages/client-runtime/src/platform/storageDocument.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from fe0db84 to a1a984aCompareAugust 7, 2026 15:44
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from a1a984a to d310fdfCompareAugust 7, 2026 15:48
Comment threadpackages/client-runtime/src/connection/registry.ts
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from d310fdf to 77b68cfCompareAugust 7, 2026 16:11
@DominicVonk
DominicVonkforce-pushed the codex/environment-activation branch from 77b68cf to 1306054CompareAugust 7, 2026 16:34

@cursorcursorBot left a comment

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.

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

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

yield* existingScope.supervisor.connect;
} else if (options.initiallyDesired === false) {
yield* existingScope.supervisor.disconnect;
}

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.

Platform polls interrupt backoff

High Severity

Equivalent platform reconciles now always call supervisor.connect when initiallyDesired is true. Desktop/web platform sources re-emit the same registrations on a short poll interval, so every tick enqueues ConnectRequested. During backoff that signal ends waitForRetrySignal early without resetting the ladder, so platform environments retry about every poll instead of respecting the longer backoff delays.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 1306054. Configure here.

@DominicVonk

Copy link
Copy Markdown
Author

Superseded by #5598, which now contains the complete environment-availability behavior as a self-contained PR based directly on main. This removes the stack dependency and lets maintainers merge the remaining PRs in any order.

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

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@DominicVonk