2026-08-23 -- Phase 2 batch C: permission controls in one place, settings IO off the delta path
This content is not available in your language yet.
UXIA-3/4: the auto-approve level moved next to the permission mode
Section titled “UXIA-3/4: the auto-approve level moved next to the permission mode”Three same-axis controls — when to ask (permission mode), what
auto-approves (auto-approve level), skip everything (danger-zone
bypass) — lived in two sections, with the level buried at the very
bottom of UapOps behind module toggles. The level’s PopupField
construction is extracted into BuildAutoApproveLevelField (internal;
exactly ONE construction site, pinned by source scan) and called from
BuildConversationSection directly after the permission mode, with
BuildDangerZone moved up to follow it — so the permission cluster
reads as one block, then the composer preference and the tool lists.
Nothing about the field changed: same AutoApproveLevelLabels
Ordered/Describe as the header chip, purely live (still absent from
SettingsChangeDetector.RequiresReconnect), same warning help, same
OnAutoApproveLevelChanged escalation confirm (UXA-3).
UapOps — its old home, and the section whose tools the level governs — keeps a one-line cross-reference hint (new EN+JA pair SettingsAutoApproveMovedHint/Tooltip) so a user who looks there is pointed to the field instead of concluding the setting is gone.
UICODE-4: hub-driven settings refreshes coalesce; disk probes gated
Section titled “UICODE-4: hub-driven settings refreshes coalesce; disk probes gated”SettingsView.OnHubChanged ran synchronously on every AgentHub.Changed raise — per streaming delta — and its refresh chain contained two disk touches: RefreshCliStatus (ICliPathProbe.Resolve statting CLI candidate paths) and RefreshUloopSection (UloopDetector.DetectInProject reading manifest.json). With the Settings tab visible during a turn, that was disk IO per delta.
Three layers, house patterns only:
- Coalesce: OnHubChanged now only sets
_hubDirty; a scheduled loop (RefreshIfHubDirty, 250 ms — the ChatView/HistoryView pattern) does the work at most 4x/second, paused in OnDeactivate. - CLI stat gate: on the coalesced tick, RefreshCliStatus runs only
when the manual path setting changed since the last resolve (pure
ShouldResolveCliStatus(lastResolvedFor, current), null sentinel = never resolved). The explicit actions (path field change, Re-detect, reconnect, RefreshAll) still call RefreshCliStatus unconditionally. - Manifest scan floor: on the coalesced tick, RefreshUloopSection
runs at most at 2 Hz (
_uloopDetectLastEvalAttwin of the existing install-progress throttle). Explicit paths keep calling it directly.
In-memory label refreshes (model, account, diagnostics…) ride the coalesced tick unchanged.
SettingsView cannot be constructed in EditMode tests (RefreshAll’s account refresh reaches the auth probe, which the standing test rule forbids), so the structural facts are pinned by source scans in SettingsViewLogicTests: OnHubChanged only marks dirty (no disk-touching call in its body), the coalesced tick uses the gated refreshes, the level field is built in Conversation and absent from UapOps with the cross-reference present, and exactly one PopupField construction site exists. ShouldResolveCliStatus is pinned directly as a pure table. L10nTests’ parity covers the new strings.