Skip to content

🤖 refactor: settings, hooks and contexts keep shown data while reloading - #6351

Merged
ThomasK33 merged 15 commits into
stable-api/5a-panes-keep-datafrom
stable-api/5b-settings-keep-data
Oct 14, 2026
Merged

ThomasK33 merged 15 commits into
stable-api/5a-panes-keep-datafrom
stable-api/5b-settings-keep-data

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Summary

This PR is layer 5b of the reconnect stack (base: #6331). The settings sections, data hooks and contexts now keep what they show when Xum reconnects. Each new client re-runs their load effects. Before this PR, many of them first cleared their data, showed "Loading…" again or marked a section "not loaded" (which disables its controls). Now a re-run keeps the shown data and replaces it only on success. While there is no live client, kept settings controls that write are disabled or report the offline state. Nothing waits to be sent to a later client.

Like #6331, this is a declared behavior change before the switch (PR 6).

Rules

  1. A re-run keeps the shown data. "Loading" shows only when nothing is shown yet. A change of the selected scope (project, workspace, template, query) still clears the old data.
  2. Only a lost connection (isConnectionLostError) is ignored. A server cancel on a live socket is a plain AbortError and is still reported. Otherwise the pane would wait forever, because no new client comes.
  3. Settings forms never overwrite a value the user is editing, and a re-run never marks a loaded section "not loaded".
  4. Offline, a kept control that writes is disabled or reports the offline state.

Sites

Area Change
ProjectContext, WorkspaceContext loading counts only the first load. Reloads keep loaded. Lost-connection failures are ignored.
AgentContext, UILayoutsContext Agents clear only for another scope. Presets stay offline.
useAnalytics, useCoderWorkspace, useWorkflowRunById, useWorkspaceHeartbeat The data records which query it answers. Spinners show only on first load or a new scope. A window focus while offline no longer clears the Coder config.
useComposerSuggestions, useCreationWorkspace Plugin commands carry their workspace ID. A lost request is not cached as loaded. Branch loading returns only for a new project.
Backup, Experiments, General, Heartbeat, Tasks, Secrets, ServerAccess, MCP sections; SplashScreenProvider; App update channels Keep shown values. The rule 4 controls are disabled offline: ServerAccess revoke/refresh, Secrets Save, the General toggles and inputs, the Heartbeat fields, Experiments warning buttons, ConfigSwitchSetting. An offline Tasks edit stays pending with a message.

Not changed: AppLoader (already on the live client), SshPromptDialog (clearing is needed: the server owns the prompt queue), useGoalDefaults (nothing reads its loading flag).

Validation

  • Both-mode tests (null-gap today, kept-gap after the switch) for each changed family, in the contexts', hooks' and sections' test files. I reverted each production file and ran its test: each fails. Some fail in one mode only, because that mode never reaches the old reset.
  • One test checks that a server cancel while connected is still reported (ServerAccessSection.test.tsx).
  • make static-check, make crap-check and the touched tests pass. GeneralSection.test.tsx fails 2 tests that also fail on origin/main on my host (🤖 fix: double-failure rollbacks and API-server settings ordering after config write failures #4748 and one that varies).

Follow-ups

  • MCPSettingsSection.refresh() still resets its list on each client change.
  • loadGoalDefaults turns a lost-connection error into the default goal settings.

Risks

Medium. The main risk is data of one scope shown under another. The identity tests cover the project, workspace, template and query keys. WorkspaceContext.loading no longer goes back to true on a reconnect, so effects that waited for it now run with the old metadata until the new snapshot lands.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $109.50

…ancel is still reported

A server cancel on a live socket is a plain AbortError, and isAbortError()
matched it too. Swallowing it left the section stuck: no new client comes
to load again. The reloads now ignore only isConnectionLostError(); each
effect's own cleanup abort stays handled by its cancelled flag or request
check.
The settings sections keep their loaded values while Xum reconnects. Their
server-backed controls stayed interactive offline and dropped the write
without a word. Each one now reports the offline state or is disabled while
there is no live client:

- ServerAccess: Refresh and the revoke buttons are disabled.
- Secrets: Save is disabled (Reset stays: it is local).
- General: the archive selects, keep-awake, API debug logs, SSH host and
  default project directory are disabled. The transcript-width switch
  reports the failure through the live client.
- Heartbeat: the fields and ConfigSwitchSetting are disabled. A save the
  lost connection cut off clears the edit mark, so the reload shows the
  saved value instead of an unsaved one that looks saved.
- Tasks: a change made offline stays pending with an offline message, and
  the autosave sends it through the next client. A retry never takes the
  pending change while offline.
- Experiments: the Portable Desktop warning's buttons are disabled.

Backup already shows that its settings are unavailable while disconnected.
@ThomasK33
ThomasK33 added this pull request to stack #6296 October 13, 2026 15:44
@ThomasK33 ThomasK33 changed the title stable api/5b settings keep data 🤖 refactor: settings, hooks and contexts keep shown data while reloading Oct 13, 2026
@ThomasK33
ThomasK33 marked this pull request as ready for review October 13, 2026 15:44
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T02:09:35.750077Z 341d3a1 New commits
🔒 Security Review ✅ Completed 2026-10-14T02:06:30.038568Z 341d3a1 New commits

Security findings

Advisory findings (1)

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9a3c6fd809

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/SecretsSection.tsx Outdated
Comment thread src/browser/hooks/useCoderWorkspace.ts Outdated
Comment thread src/browser/features/Settings/Sections/TasksSection.tsx
Comment thread src/browser/contexts/WorkspaceContext.tsx Outdated
Four review findings on the kept-data Settings and context changes:

- Secrets: a reload reads the form's dirtiness when it answers, not when it
  started, so an edit typed while the reload is in flight survives it.
- Coder presets: another template clears the shown presets even offline, so
  the old template's presets are never selectable.
- Tasks: every control is disabled while offline. An offline edit lived only
  in the section's state and was lost when the user left the section before
  the reconnect.
- Workspaces: a new client shows the loader again while no snapshot has
  loaded, so a disconnect before the first snapshot does not leave the app
  with an empty metadata map.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 71ee55a8e3

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71ee55a8e3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/TasksSection.tsx
Comment thread src/browser/hooks/useCoderWorkspace.ts Outdated
Comment thread src/browser/features/ChatInput/useCreationWorkspace.ts
Comment thread src/browser/features/ChatInput/useComposerSuggestions.ts
…ntil it answers

Four review findings on the kept-data reloads:

- Tasks: the controls stay disabled until a load answers. The autosave does
  not track an edit made before the reload answers, so the answer would have
  replaced it.
- Coder presets: every online load sets `loadingPresets`, a reconnect reload
  too. ChatInput blocks a Coder send on it, so a send cannot use a preset the
  server removed while offline. The shown presets stay.
- Creation branches: every load clears `branchesLoaded`, the send barrier for
  a trunk branch (#6033). The shown branches stay.
- MCP prompts: a new client lists the prompts again, even inside the 30 s
  cache window, because they can change while offline.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 714dd37416

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 714dd37416

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/hooks/useCoderWorkspace.ts
Comment thread src/browser/contexts/WorkspaceContext.tsx
Comment thread src/browser/hooks/useWorkspaceHeartbeat.ts
Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx Outdated
Comment thread src/browser/features/Settings/Sections/BackupSection.tsx
Review findings on the kept-data reloads:

- Coder presets: a reload that no longer lists the selected preset selects
  a listed one, so a preset removed while offline is not sent.
- General: the two archive selects are disabled until each config read
  answers. They are written together, so a change before the read would
  send a stale value for the other one.
- Heartbeat: Save waits for the new client's read (`isReloading`): the kept
  form would overwrite changes made on the server while offline.
- Backup: Save waits for a pending settings read, for the same reason.

A test also pins that a drop before the first metadata snapshot keeps
the startup loader: the ConnectionLostError is not a load failure.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cce8c99764

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/SecretsSection.tsx Outdated
Comment thread src/browser/features/Settings/Sections/SecretsSection.tsx
Comment thread src/browser/hooks/useCoderWorkspace.ts
Comment thread src/browser/features/ChatInput/useCreationWorkspace.ts
Comment thread src/browser/hooks/useAnalytics.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: cce8c99764

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/browser/features/Settings/Sections/SecretsSection.tsx
A dirty Secrets form survives a reconnect, and Save was enabled as soon as the connection came back. Save writes the whole list, so a click before the new read answered could overwrite secrets changed on the server while offline (including injectAll). Save is now disabled while a read is pending.
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: fc4981ac8a

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc4981ac8a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/HeartbeatSection.tsx
@ThomasK33

Copy link
Copy Markdown
Member Author

Merge decision

Codex reviewed this head (Code Review and Security Review both Completed) with no unresolved findings, but posted no approval comment or 👍. This PR is past the review-round cap (rounds 4+ are blockers-only). A clean-context advisor checked the threads, the deferred findings and the Required checks, and recommended: ready with tracked follow-ups, merge on this silent completion without another round. I accept that recommendation.

Deferred findings are tracked in #6383. Required CI passes on this head.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $166.02

…ngs-keep-data

Resolve useCreationWorkspace against #6417 (branchesLoaded became branchLoad): keep main's per-load branch status, and keep the runtimes shown across a reconnect reload. The reconnect test reads branchLoad.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 341d3a197b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/hooks/useWorkspaceHeartbeat.ts
@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit e251110 Oct 14, 2026
64 of 85 checks passed
@ThomasK33
ThomasK33 deleted the stable-api/5b-settings-keep-data branch October 14, 2026 03:01
yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Oct 14, 2026
…, and cache a viewed wizard (T3 C step 2 PR 1b) (coder#6379)

## Summary

`SplashScreenProvider` removes the static first-run view (`#xum-pre`)
once its splash queue is known and the onboarding wizard is not first.
It also records a new paint cache, so the server's early script (a later
PR) can skip its API calls for a browser that has seen the wizard marked
viewed. Nothing inserts `#xum-pre` yet.

**Stack** (T3 coder#5971, Option C step 2, PR 1 split at the 300-line limit
into 3 layers, each inert without `#xum-pre`):
1. coder#6378: entry and connection guard (this stack's bottom)
2. coder#6379: splash queue and paint cache
3. coder#6381: wizard handoff

Plan: section 5.6 "C step 2: the static first-run view on `/` (P1)" of
the T3 Phase 3 plan. Nothing in this stack inserts `#xum-pre`: a later
PR (4b) makes `xum server` paint it for `/`. Until then every change
here is a no-op, and the gates (Lighthouse, page timing, first-load
bytes) run once on the stack's top against the merge base; their table
is on coder#6381.

## Implementation

- `useFirstRunViewQueueGuard(loaded, wizardIsFirst)` removes the view in
a layout effect when the queue is loaded and the wizard is not first:
already viewed, the viewed list could not be read, splash screens off or
no API, or another splash comes first.
- `onboardingWizardViewed` (`storage.ts`, registered as `"cache"` like
`uiTheme`): `cacheViewedWizard()` sets it when the loaded viewed list
contains the wizard id, and after `dismiss()` marks the wizard viewed.
- coder#6351 (open) changes the same file to keep a shown splash on a lost
connection. That rule stands: a lost connection is the `reconnecting`
status, where coder#6378's guard removes the static view, not the queue.

## Validation

| Test (jest, `tests/ui/onboarding/providerHandoff.test.ts`) | Mutation
that fails it |
|---|---|
| keeps the static view while the wizard is first | Q2: remove before
the queue is loaded |
| removes it when viewed / read failed / another splash first / no API |
Q1: no queue guard |
| caches a viewed wizard on load and on dismiss | Q3: no load-time
write. Q4: no dismiss write |

- `make crap-check` passes: the effect and the cache write are a named
hook and a function with two callers, so `SplashScreenProvider` keeps
its CC.
- The storage registry tests (`storage.test.ts`,
`persistedStateBudget.test.ts`, `legacyLocalStorageCleanup.test.ts`)
pass with the new key.

## Risks

Low. Without `#xum-pre` the only change is one new 4-byte localStorage
value per browser (`true`), written when the wizard is viewed.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking:
`high` • Cost: `$289.12`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high
costs=289.12 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant