fix(desktop): keep Settings stable during Runtime Host refresh - #3450
fix(desktop): keep Settings stable during Runtime Host refresh#3450chihumyum wants to merge 3 commits into
Conversation
jackwener
left a comment
There was a problem hiding this comment.
Automated review of exact head 54651d6b0aeca844f527f75cfe00f4a8d6b6c9fc against current main@d62857a8357e9160926726a2a13096bc2dc2b91d.
The defect remains on main: every Settings mount starts the Runtime Host catalog/settings/connections resources cold, so the mixed-ownership General page briefly renders defaults/loading feedback before Host data arrives. The patch keeps only masked read snapshots in renderer memory, keys Host data by profileId:hostId, prunes an old epoch when the catalog changes, and keeps cached Host controls inert until the current mount verifies the target. The separate read/write tickets also prevent a late old-Host result from populating the newly selected Host. The reopen E2E observes the transient DOM, so it would catch the original flash rather than only asserting the settled page. I found no actionable P0-P2 defect; git diff --check is clean.
Required conclusions:
- Optimal for the actual problem: yes. The implementation is larger than the symptom, but stable cross-unmount rendering requires a cache, and the masking, epoch key, verification bit, and interaction fence are necessary to avoid turning stale UI into write authority.
- Production code to delete: the PR replaces the older parallel resource unions/ticket refs; none further identified.
- Tests to delete/replace: none identified. The helper tests and transient-DOM E2E cover distinct contracts.
- Deeper refactor: no; keeping the cache outside AppShell avoids lifting Settings-only state into a broader owner.
- Ready to merge: not yet. No hosted
testcheck is reported on this exact head, and automated review is not approval. - Residual risks/gaps: this changes user-visible loading/error behavior and the security-sensitive Host write boundary across General, Projects, and Data. The supplied tests cover cache epochs and the default General reopen, but independent human review should still exercise non-default Host selection and failure/retry behavior.
This affects user-visible behavior and Runtime Host authority fencing, so CONTRIBUTING.md requires independent human judgment on the exact head.
54651d6 to
43e53f7
Compare
jackwener
left a comment
There was a problem hiding this comment.
Automated re-review of exact head 43e53f751ba9b604b994d75bf88c8a2781972e08 against main@f1f4e71a9540a4da23159052c924fee72202e989.
No new actionable implementation defect was found relative to the previously reviewed revision. git range-diff shows the same one-commit settings stabilization adapted onto the newer base; the keyed snapshot/cache/request-authority structure still keeps one Host's data from being exposed through another, retains last-ready content during revalidation, and fences mutations until the selected Host is freshly verified.
The head is not mergeable, however. Current main and this PR both modify apps/desktop/e2e/settings.spec.ts, settings-surface.tsx, and nav-sidebar.css; the E2E conflict specifically places main's “wide settings gutters scroll the whole main pane” test against this PR's reopen-stability test. Rebase and preserve both behavioral contracts rather than choosing one side. Re-run the exact-head check after resolution.
Required conclusions:
- Optimal for the actual problem: yes; the cache remains renderer-memory, keyed by bridge/Host identity, and mutations stay behind fresh authority.
- Production code to delete: none identified.
- Tests to delete/replace: none; preserve both the main scroll-ownership E2E and this PR's reopen-stability E2E.
- Deeper refactor: no.
- Ready to merge: no while conflicting; there is also no hosted
testresult or independent human approval on this head. - Residual risks: conflict resolution is the primary regression risk, particularly losing main's newly merged settings scroll ownership or this PR's revalidation coverage.
This changes user-visible Settings behavior. Independent human review is required; this automated review is not approval.
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks — the cache ownership and Runtime Host fencing are thoughtfully structured, and I did not find a cross-Host authority or stale-write correctness issue on exact head 43e53f751ba9b604b994d75bf88c8a2781972e08. I found two non-blocking user-facing gaps below.
Since this head currently conflicts with main in the same Settings surface, please preserve these final-state requirements while rebasing. After the semantic rebase, these findings remain P2 and do not by themselves block approval.
AI-assisted review disclosure: Codex delegated independent review passes; I verified the reported paths and conclusions against this exact head.
43e53f7 to
fa01d91
Compare
|
@Astro-Han Thanks for the careful review. I rebased onto the current
The semantic rebase also preserves both #3453 scroll ownership and this PR’s reopen-stability contract. Exact-head verification: desktop tests 1076/1076, Storybook smoke 169/169, Settings E2E 4/4, and full Electron E2E 41 passed / 1 skipped. Could you please take another look when convenient? |
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for the substantial cleanup of the settings cache and intent flow. The exact-head test is green, and the earlier findings are improved, but the current page-level boundary still mixes Desktop-owned and Host-owned availability, and the refresh generation does not yet revoke write authority. I left the two final-state requirements inline.\n\nAI-assisted review disclosure: Codex delegated independent state and test reviews; I reconciled the conflicting conclusions against the exact-head control flow and live PR state before posting.
fa01d91 to
1ac77bf
Compare
|
@Astro-Han Thanks for the follow-up review. I rebased the branch onto The follow-up binds Runtime Host reads and writes to lifecycle epoch as well as Exact-head local verification is green: lint, format, build, typecheck, both knip workspaces, Astryx inventory (191 files), Desktop tests (1118/1118), Storybook build/render smoke (172/172), and Electron E2E (41 passed, 1 repository-defined skip). The new hosted CI run is awaiting maintainer approval before its jobs can start. Could you please re-review the new exact head when convenient? — Codex, posting on behalf of @chihumyum |
de55a42 to
29153de
Compare
Generated-by: Codex
Generated-by: Codex
29153de to
280d833
Compare
Astro-Han
left a comment
There was a problem hiding this comment.
Re-reviewed at the new head 280d833a after the rebase. We re-verified each of our earlier findings against this head rather than carrying them forward, and one of them does not survive.
Withdrawing our P1 about the ownership seam — you were right and we were wrong. Our claim was that the outer RuntimeHostInteractionBoundary renders the whole SettingsPageBody inert and so blocks desktop-side controls on pages that mix client and Host concerns. That premise does not hold: requiresRuntimeHost is sectionScope === 'runtime-host', and SETTINGS_SECTION_SCOPES marks general, projects and data as 'mixed', so isInteractive={!requiresRuntimeHost || runtimeHostContentVerified} evaluates to true on exactly the pages we were worried about. The inert branch is unreachable there. We should have traced the scope table before filing it.
Two P2 from the earlier rounds are confirmed fixed. The write-authority/epoch one: settings-request-authority.ts now binds each ticket to (key, targetEpoch, targetRevision, generation) and selectTarget bumps every generation when the key or epoch changes, so a superseded mutation response is rejected before commit. The catalog-intent one: the parent now waits for the child's onInitialProviderCatalogConsumed callback before clearing providerCatalogRequested (settings-surface.tsx:998-1000).
One P2 from the earlier round is still open — the boundary is invisible. RuntimeHostInteractionBoundary still applies only inert plus aria-busy. Assistive technology is informed; a sighted user is not. During a slow reconnect the page looks fully usable and silently swallows clicks. A muted/loading treatment on the wrapper would close it.
One new P2, inline — and it is worth noting that this is where the risk our withdrawn P1 was gesturing at actually lives. The mechanism we described was wrong, but there is a real gap on the mixed pages; it is just an inconsistency between them rather than an outer-boundary problem.
Everything else on the rebase increment checks out — the epoch fix survived intact.
This review was AI-assisted. Findings were verified against the exact head listed above; any mistakes are ours to correct — please push back where we got it wrong.
Generated-by: Codex
Summary
ProvidersPanelconsumes it, and visibly mute cached Host pages while their authority fence is active.Behaviour
Before fixing, the yellow banner flashes each time the settings page is opened.
before.mp4
After fixing, no yellow banner was ever shown.
after.mp4
Verification
npm run lintnpm run format:checknpm run buildnpm run typechecknpm --workspace @maka/desktop test— 1118/1118 passednpm --workspace @maka/desktop run build-storybooknpm --workspace @maka/desktop run smoke:storybook— 172/172 passednpx knip --workspace apps/desktopnpx knip --workspace packages/uinpm run astryx:surface-inventory— 191 files, 1 documented exclusionnpm --workspace @maka/desktop run e2e— 41 passed, 1 skippedReview focus
AI use
Select exactly one:
Tool(s) and scope: Codex — implementation, race analysis, unit/Storybook/Electron
E2E coverage, regression verification, and pull request preparation. The human
contributor reviewed the contribution and accepts responsibility for it.
Checklist
Does this PR entail a change in behavior?