Skip to content

[4 of 4] tui: route startup and onboarding config writes through app server#22916

Closed
etraut-openai wants to merge 4 commits into
mainfrom
etraut/tui-config-app-server-4-startup-bookkeeping
Closed

[4 of 4] tui: route startup and onboarding config writes through app server#22916
etraut-openai wants to merge 4 commits into
mainfrom
etraut/tui-config-app-server-4-startup-bookkeeping

Conversation

@etraut-openai

@etraut-openai etraut-openai commented May 15, 2026

Copy link
Copy Markdown
Collaborator

Why

The remaining local writes happen during startup, onboarding, and prompt bookkeeping. They are less common than interactive settings changes, but they are still real config mutations and should follow the same app-server ownership model instead of reaching around it.

This is [4 of 4] in a stacked series that moves TUI-owned config mutations onto app-server APIs.

What changed

  • Deferred OSS provider persistence until the app server is available, then wrote it through config/batchWrite.
  • Moved onboarding project-trust persistence out of the TUI widget and into an app-server-backed config write after the trust decision is made.
  • Routed startup tooltip counts, warning dismissals, model-migration acknowledgements, and external-config-migration prompt bookkeeping through app-server config writes.

Config keys affected

  • oss_provider
  • projects.<project_key>.trust_level
  • tui.model_availability_nux.<model_slug>
  • notice.hide_full_access_warning
  • notice.hide_world_writable_warning
  • notice.hide_rate_limit_model_nudge
  • notice.model_migrations.<from_model>
  • notice.external_config_migration_prompts.home
  • notice.external_config_migration_prompts.home_last_prompted_at
  • notice.external_config_migration_prompts.projects.<project_key>
  • notice.external_config_migration_prompts.project_last_prompted_at.<project_key>

Suggested manual validation

  • Launch with --oss when no OSS provider is configured, pick a provider manually, and confirm oss_provider is persisted through the app-server path.
  • Run the trust-directory onboarding flow in embedded app-server mode and confirm the trusted project lands under projects.<project_key>.trust_level.
  • Exercise one startup bookkeeping flow, such as a model availability NUX tooltip or a model migration acknowledgement, and confirm the corresponding notice key updates remotely.
  • Dismiss one warning prompt and one external-config-migration prompt, then relaunch and confirm the app-server-owned prompt state suppresses the repeat prompt.

Stack

  1. #22913 [1 of 4] primary settings writes
  2. #22914 [2 of 4] app and skill enablement
  3. #22915 [3 of 4] feature and memory toggles
  4. #22916 [4 of 4] startup and onboarding bookkeeping

@etraut-openai etraut-openai marked this pull request as ready for review May 15, 2026 22:40
@etraut-openai etraut-openai force-pushed the etraut/tui-config-app-server-4-startup-bookkeeping branch from fb52e01 to 8cac60f Compare May 15, 2026 22:45
@etraut-openai etraut-openai force-pushed the etraut/tui-config-app-server-3-feature-toggles branch 2 times, most recently from d8375c8 to d5f9063 Compare May 15, 2026 22:50
@etraut-openai etraut-openai force-pushed the etraut/tui-config-app-server-4-startup-bookkeeping branch from 8cac60f to 6ea4edd Compare May 15, 2026 22:50
etraut-openai added a commit that referenced this pull request May 16, 2026
## Why
The TUI can run against a remote app server, but several high-traffic
settings still persisted by editing the local config file. That sends
remote sessions' preference writes to the wrong machine and lets local
disk state drift from the app-server-owned config.

This is **[1 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Added a small TUI helper for typed app-server config writes.
- Routed primary interactive preference writes through
`config/batchWrite`.
- Preserved existing profile scoping for settings that already support
`profiles.<profile>.*` overrides.

## Config keys affected
- `model`
- `model_reasoning_effort`
- `personality`
- `service_tier`
- `plan_mode_reasoning_effort`
- `approvals_reviewer`
- `notice.fast_default_opt_out`
- Profile-scoped equivalents under `profiles.<profile>.*`

## Suggested manual validation
- Connect the TUI to a remote app server, change `model` and
`model_reasoning_effort`, reconnect, and confirm the remote config
retained both values while the local `config.toml` did not change.
- Change `personality`, `plan_mode_reasoning_effort`, and the explicit
auto-review selection, then reconnect and confirm those choices persist
through the app server.
- Clear the service tier back to default and confirm `service_tier` is
cleared while `notice.fast_default_opt_out = true` is persisted
remotely.
- Repeat one setting change with an active profile and confirm the write
lands under `profiles.<profile>.*`.

## Stack
1. [#22913](#22913) `[1 of 4]`
primary settings writes
2. [#22914](#22914) `[2 of 4]` app
and skill enablement
3. [#22915](#22915) `[3 of 4]`
feature and memory toggles
4. [#22916](#22916) `[4 of 4]`
startup and onboarding bookkeeping
etraut-openai added a commit that referenced this pull request May 19, 2026
## Why
App and skill toggles are user config mutations too. When the TUI is
attached to a remote app server, writing those toggles into the local
`config.toml` makes the UI report success without updating the server
that actually owns the session.

This is **[2 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Routed app enable/disable persistence through app-server config batch
writes.
- Routed skill enable/disable persistence through `skills/config/write`.
- Avoided refreshing local config from disk after these writes when the
TUI is connected to a remote app server.

## Config keys affected
- `apps.<app_id>.enabled`
- `apps.<app_id>.disabled_reason`
- `[[skills.config]]` entries keyed by `path`, with `enabled = false`
used for persisted disables

## Suggested manual validation
- Connect the TUI to a remote app server, disable an app, reconnect, and
confirm the app remains disabled from remote config rather than local
disk state.
- Re-enable the same app and confirm both `apps.<app_id>.enabled` and
`apps.<app_id>.disabled_reason` are cleared remotely.
- Disable a skill in the manage-skills UI and confirm a remote
`[[skills.config]]` disable entry appears.
- Re-enable that skill and confirm the disable entry is removed and the
effective enabled state updates without relying on local config reloads.

## Stack
1. [#22913](#22913) `[1 of 4]`
primary settings writes
2. [#22914](#22914) `[2 of 4]` app
and skill enablement
3. [#22915](#22915) `[3 of 4]`
feature and memory toggles
4. [#22916](#22916) `[4 of 4]`
startup and onboarding bookkeeping
@etraut-openai etraut-openai force-pushed the etraut/tui-config-app-server-3-feature-toggles branch from f0e5a0e to 61beab3 Compare May 19, 2026 17:35
etraut-openai added a commit that referenced this pull request May 21, 2026
…2915)

## Why
Experimental feature toggles and memory settings can update several
related config values in one interaction. Keeping those writes local in
a remote TUI session is especially dangerous because the UI can diverge
from the app-server config while also leaving behind partially stale
supporting keys.

This is **[3 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Routed feature flag persistence through app-server batch writes,
including the supporting reviewer and permission updates used by
guardian approval.
- Routed Windows sandbox mode persistence and legacy Windows feature
cleanup through app-server writes.
- Routed memory settings through app-server batch writes and updated the
TUI tests to exercise the embedded app-server path.

## Config keys affected
- `features.<feature_key>`
- `profiles.<profile>.features.<feature_key>`
- `approval_policy`
- `sandbox_mode`
- `approvals_reviewer`
- `windows.sandbox`
- `features.experimental_windows_sandbox`
- `features.elevated_windows_sandbox`
- `features.enable_experimental_windows_sandbox`
- Profile-scoped Windows legacy feature variants under
`profiles.<profile>.features.*`
- `memories.use_memories`
- `memories.generate_memories`
- Profile-scoped memory variants under `profiles.<profile>.memories.*`

## Suggested manual validation
- Connect the TUI to a remote app server, toggle guardian approval on
and off, and confirm the remote config updates
`features.guardian_approval`, reviewer state, approval policy, and
sandbox mode coherently.
- Toggle a default-false experimental feature at the root level, disable
it again, and confirm the key clears instead of lingering as an
unnecessary explicit `false`.
- Change memory settings and confirm the remote config updates both
memory keys while the running TUI reflects the new state.
- On Windows, switch sandbox mode through the TUI and confirm
`windows.sandbox` is updated while the legacy Windows feature keys are
cleared.

## Stack
1. [#22913](#22913) `[1 of 4]`
primary settings writes
2. [#22914](#22914) `[2 of 4]` app
and skill enablement
3. [#22915](#22915) `[3 of 4]`
feature and memory toggles
4. [#22916](#22916) `[4 of 4]`
startup and onboarding bookkeeping
Base automatically changed from etraut/tui-config-app-server-3-feature-toggles to main May 21, 2026 23:03
@etraut-openai etraut-openai force-pushed the etraut/tui-config-app-server-4-startup-bookkeeping branch from 2ec355f to 91d4b25 Compare May 21, 2026 23:23

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91d4b257b2

ℹ️ 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 codex-rs/tui/src/lib.rs Outdated
Comment thread codex-rs/tui/src/lib.rs Outdated
etraut-openai added a commit that referenced this pull request May 25, 2026
## Summary

The TUI `/mcp` inventory flow should reflect the app server’s MCP status
response. It was also joining those results with the TUI process’s local
`config.mcp_servers`, which can diverge once MCP state is owned by a
remote app server and cause stale local command, URL, status, or
empty-state details to render.

This change removes the local config join from the app-server-backed
inventory renderer. The TUI now renders directly from the existing
`mcpServerStatus/list` payload and treats an empty status response as
the empty MCP inventory state.

## Known limitation

The existing `mcpServerStatus/list` payload does not include
disabled-state or disabled-reason fields. To preserve the current
app-server API, this PR does not try to infer that state from
client-local config. If remote `/mcp` needs to show disabled/reason
details again, that should come from app-server-owned status data in a
follow-up.

Related to #22914, #22915, and #22916.
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
## Why
The TUI can run against a remote app server, but several high-traffic
settings still persisted by editing the local config file. That sends
remote sessions' preference writes to the wrong machine and lets local
disk state drift from the app-server-owned config.

This is **[1 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Added a small TUI helper for typed app-server config writes.
- Routed primary interactive preference writes through
`config/batchWrite`.
- Preserved existing profile scoping for settings that already support
`profiles.<profile>.*` overrides.

## Config keys affected
- `model`
- `model_reasoning_effort`
- `personality`
- `service_tier`
- `plan_mode_reasoning_effort`
- `approvals_reviewer`
- `notice.fast_default_opt_out`
- Profile-scoped equivalents under `profiles.<profile>.*`

## Suggested manual validation
- Connect the TUI to a remote app server, change `model` and
`model_reasoning_effort`, reconnect, and confirm the remote config
retained both values while the local `config.toml` did not change.
- Change `personality`, `plan_mode_reasoning_effort`, and the explicit
auto-review selection, then reconnect and confirm those choices persist
through the app server.
- Clear the service tier back to default and confirm `service_tier` is
cleared while `notice.fast_default_opt_out = true` is persisted
remotely.
- Repeat one setting change with an active profile and confirm the write
lands under `profiles.<profile>.*`.

## Stack
1. [#22913](openai/codex#22913) `[1 of 4]`
primary settings writes
2. [#22914](openai/codex#22914) `[2 of 4]` app
and skill enablement
3. [#22915](openai/codex#22915) `[3 of 4]`
feature and memory toggles
4. [#22916](openai/codex#22916) `[4 of 4]`
startup and onboarding bookkeeping
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
## Why
App and skill toggles are user config mutations too. When the TUI is
attached to a remote app server, writing those toggles into the local
`config.toml` makes the UI report success without updating the server
that actually owns the session.

This is **[2 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Routed app enable/disable persistence through app-server config batch
writes.
- Routed skill enable/disable persistence through `skills/config/write`.
- Avoided refreshing local config from disk after these writes when the
TUI is connected to a remote app server.

## Config keys affected
- `apps.<app_id>.enabled`
- `apps.<app_id>.disabled_reason`
- `[[skills.config]]` entries keyed by `path`, with `enabled = false`
used for persisted disables

## Suggested manual validation
- Connect the TUI to a remote app server, disable an app, reconnect, and
confirm the app remains disabled from remote config rather than local
disk state.
- Re-enable the same app and confirm both `apps.<app_id>.enabled` and
`apps.<app_id>.disabled_reason` are cleared remotely.
- Disable a skill in the manage-skills UI and confirm a remote
`[[skills.config]]` disable entry appears.
- Re-enable that skill and confirm the disable entry is removed and the
effective enabled state updates without relying on local config reloads.

## Stack
1. [#22913](openai/codex#22913) `[1 of 4]`
primary settings writes
2. [#22914](openai/codex#22914) `[2 of 4]` app
and skill enablement
3. [#22915](openai/codex#22915) `[3 of 4]`
feature and memory toggles
4. [#22916](openai/codex#22916) `[4 of 4]`
startup and onboarding bookkeeping
monkeycode-ai Bot pushed a commit to agogo233/Ecode that referenced this pull request Jun 8, 2026
…2915)

## Why
Experimental feature toggles and memory settings can update several
related config values in one interaction. Keeping those writes local in
a remote TUI session is especially dangerous because the UI can diverge
from the app-server config while also leaving behind partially stale
supporting keys.

This is **[3 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Routed feature flag persistence through app-server batch writes,
including the supporting reviewer and permission updates used by
guardian approval.
- Routed Windows sandbox mode persistence and legacy Windows feature
cleanup through app-server writes.
- Routed memory settings through app-server batch writes and updated the
TUI tests to exercise the embedded app-server path.

## Config keys affected
- `features.<feature_key>`
- `profiles.<profile>.features.<feature_key>`
- `approval_policy`
- `sandbox_mode`
- `approvals_reviewer`
- `windows.sandbox`
- `features.experimental_windows_sandbox`
- `features.elevated_windows_sandbox`
- `features.enable_experimental_windows_sandbox`
- Profile-scoped Windows legacy feature variants under
`profiles.<profile>.features.*`
- `memories.use_memories`
- `memories.generate_memories`
- Profile-scoped memory variants under `profiles.<profile>.memories.*`

## Suggested manual validation
- Connect the TUI to a remote app server, toggle guardian approval on
and off, and confirm the remote config updates
`features.guardian_approval`, reviewer state, approval policy, and
sandbox mode coherently.
- Toggle a default-false experimental feature at the root level, disable
it again, and confirm the key clears instead of lingering as an
unnecessary explicit `false`.
- Change memory settings and confirm the remote config updates both
memory keys while the running TUI reflects the new state.
- On Windows, switch sandbox mode through the TUI and confirm
`windows.sandbox` is updated while the legacy Windows feature keys are
cleared.

## Stack
1. [#22913](openai/codex#22913) `[1 of 4]`
primary settings writes
2. [#22914](openai/codex#22914) `[2 of 4]` app
and skill enablement
3. [#22915](openai/codex#22915) `[3 of 4]`
feature and memory toggles
4. [#22916](openai/codex#22916) `[4 of 4]`
startup and onboarding bookkeeping
wangjiecloud pushed a commit to wangjiecloud/codex that referenced this pull request Jun 27, 2026
…i#22913)

## Why
The TUI can run against a remote app server, but several high-traffic
settings still persisted by editing the local config file. That sends
remote sessions' preference writes to the wrong machine and lets local
disk state drift from the app-server-owned config.

This is **[1 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Added a small TUI helper for typed app-server config writes.
- Routed primary interactive preference writes through
`config/batchWrite`.
- Preserved existing profile scoping for settings that already support
`profiles.<profile>.*` overrides.

## Config keys affected
- `model`
- `model_reasoning_effort`
- `personality`
- `service_tier`
- `plan_mode_reasoning_effort`
- `approvals_reviewer`
- `notice.fast_default_opt_out`
- Profile-scoped equivalents under `profiles.<profile>.*`

## Suggested manual validation
- Connect the TUI to a remote app server, change `model` and
`model_reasoning_effort`, reconnect, and confirm the remote config
retained both values while the local `config.toml` did not change.
- Change `personality`, `plan_mode_reasoning_effort`, and the explicit
auto-review selection, then reconnect and confirm those choices persist
through the app server.
- Clear the service tier back to default and confirm `service_tier` is
cleared while `notice.fast_default_opt_out = true` is persisted
remotely.
- Repeat one setting change with an active profile and confirm the write
lands under `profiles.<profile>.*`.

## Stack
1. [openai#22913](openai#22913) `[1 of 4]`
primary settings writes
2. [openai#22914](openai#22914) `[2 of 4]` app
and skill enablement
3. [openai#22915](openai#22915) `[3 of 4]`
feature and memory toggles
4. [openai#22916](openai#22916) `[4 of 4]`
startup and onboarding bookkeeping
wangjiecloud pushed a commit to wangjiecloud/codex that referenced this pull request Jun 27, 2026
…ai#22914)

## Why
App and skill toggles are user config mutations too. When the TUI is
attached to a remote app server, writing those toggles into the local
`config.toml` makes the UI report success without updating the server
that actually owns the session.

This is **[2 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Routed app enable/disable persistence through app-server config batch
writes.
- Routed skill enable/disable persistence through `skills/config/write`.
- Avoided refreshing local config from disk after these writes when the
TUI is connected to a remote app server.

## Config keys affected
- `apps.<app_id>.enabled`
- `apps.<app_id>.disabled_reason`
- `[[skills.config]]` entries keyed by `path`, with `enabled = false`
used for persisted disables

## Suggested manual validation
- Connect the TUI to a remote app server, disable an app, reconnect, and
confirm the app remains disabled from remote config rather than local
disk state.
- Re-enable the same app and confirm both `apps.<app_id>.enabled` and
`apps.<app_id>.disabled_reason` are cleared remotely.
- Disable a skill in the manage-skills UI and confirm a remote
`[[skills.config]]` disable entry appears.
- Re-enable that skill and confirm the disable entry is removed and the
effective enabled state updates without relying on local config reloads.

## Stack
1. [openai#22913](openai#22913) `[1 of 4]`
primary settings writes
2. [openai#22914](openai#22914) `[2 of 4]` app
and skill enablement
3. [openai#22915](openai#22915) `[3 of 4]`
feature and memory toggles
4. [openai#22916](openai#22916) `[4 of 4]`
startup and onboarding bookkeeping
wangjiecloud pushed a commit to wangjiecloud/codex that referenced this pull request Jun 27, 2026
…enai#22915)

## Why
Experimental feature toggles and memory settings can update several
related config values in one interaction. Keeping those writes local in
a remote TUI session is especially dangerous because the UI can diverge
from the app-server config while also leaving behind partially stale
supporting keys.

This is **[3 of 4]** in a stacked series that moves TUI-owned config
mutations onto app-server APIs.

## What changed
- Routed feature flag persistence through app-server batch writes,
including the supporting reviewer and permission updates used by
guardian approval.
- Routed Windows sandbox mode persistence and legacy Windows feature
cleanup through app-server writes.
- Routed memory settings through app-server batch writes and updated the
TUI tests to exercise the embedded app-server path.

## Config keys affected
- `features.<feature_key>`
- `profiles.<profile>.features.<feature_key>`
- `approval_policy`
- `sandbox_mode`
- `approvals_reviewer`
- `windows.sandbox`
- `features.experimental_windows_sandbox`
- `features.elevated_windows_sandbox`
- `features.enable_experimental_windows_sandbox`
- Profile-scoped Windows legacy feature variants under
`profiles.<profile>.features.*`
- `memories.use_memories`
- `memories.generate_memories`
- Profile-scoped memory variants under `profiles.<profile>.memories.*`

## Suggested manual validation
- Connect the TUI to a remote app server, toggle guardian approval on
and off, and confirm the remote config updates
`features.guardian_approval`, reviewer state, approval policy, and
sandbox mode coherently.
- Toggle a default-false experimental feature at the root level, disable
it again, and confirm the key clears instead of lingering as an
unnecessary explicit `false`.
- Change memory settings and confirm the remote config updates both
memory keys while the running TUI reflects the new state.
- On Windows, switch sandbox mode through the TUI and confirm
`windows.sandbox` is updated while the legacy Windows feature keys are
cleared.

## Stack
1. [openai#22913](openai#22913) `[1 of 4]`
primary settings writes
2. [openai#22914](openai#22914) `[2 of 4]` app
and skill enablement
3. [openai#22915](openai#22915) `[3 of 4]`
feature and memory toggles
4. [openai#22916](openai#22916) `[4 of 4]`
startup and onboarding bookkeeping
wangjiecloud pushed a commit to wangjiecloud/codex that referenced this pull request Jun 27, 2026
## Summary

The TUI `/mcp` inventory flow should reflect the app server’s MCP status
response. It was also joining those results with the TUI process’s local
`config.mcp_servers`, which can diverge once MCP state is owned by a
remote app server and cause stale local command, URL, status, or
empty-state details to render.

This change removes the local config join from the app-server-backed
inventory renderer. The TUI now renders directly from the existing
`mcpServerStatus/list` payload and treats an empty status response as
the empty MCP inventory state.

## Known limitation

The existing `mcpServerStatus/list` payload does not include
disabled-state or disabled-reason fields. To preserve the current
app-server API, this PR does not try to infer that state from
client-local config. If remote `/mcp` needs to show disabled/reason
details again, that should come from app-server-owned status data in a
follow-up.

Related to openai#22914, openai#22915, and openai#22916.
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