agent pane: permission UI keeps its last state across a chat switch (no blink)
The agent pane's permission UI blinked on every tab or workspace switch, and on every workspace create or close. Two pieces of permission state were emptied whenever the selected chat changed, then refilled by an async read:
- Folder trust (
useFolderTrustAsk): the hook reset to "reading" and waited onacp.trust.get, for up to 1.5 s. While it read,blockedwas set, so the bottom stack took the permission panel, asks, secret and tool cards out of the tree, Send was off, and the access chip lost its folder grant. - Grouped permissions (
PermissionGroupClient.select): the pending groups and the "allowed for this chat" grant were cleared until_acpmux/permission_groupsanswered.
Both now keep the last known value until the new one arrives:
- Trust keeps the last answer per folder (in memory, and in
localStorageso the next page from the pool has it, up to 200 folders). A chat change draws from it in the same render and reads only a folder it has never read. The read refreshes the answer and changes nothing on screen when it agrees. acpmux still refuses a prompt the folder's current trust doesn't allow (trust_gate.rs), and that refusal reads the folder again. - The permission client keeps each chat's last authoritative groups and grant (64 chats). It shows them again on reselect with
ready: false, so the buttons stay off until the refresh replaces them and a stale ask can't be answered.
Evidence
Each fix comes after a failing test:
webviews/test/folder-trust-switch-no-blank.test.tsxrecords every committed render (layout effect, before paint). Switching back to a chat in a folder already read renderedblocked: true, trusted: falsebefore the fix (red at b8f0ba7) and has no such render after (green at 0387ba8).webviews/test/permission-groups-switch-keeps-last.test.tsfailed withchatAllowancefalse on reselect (red at 560cc47) and passes after (7a66f73).
What ran, on Linux, at 7a66f73:
bun teston every webviews test that mentions permission or trust: 140 pass, 0 fail.- Full
bun test test/: the same 89 failures as the base, pluspalette-eval, which also fails on the base when run alone. tsc --noEmit: 0 errors.vp fmtandvp lintare clean on the changed files.
Not done: no frame-1 capture (scripts/cmux-next/perceived-speed-slot.sh). It needs a capture slot from big-red, and this ran on huge-blue. No live dogfood either.
Follow-up (taking over the lane)
- A read in flight no longer hides the asks. Even with the cache, a folder the page had never read still blanked the permission panel, asks and tool cards for its first read.
useFolderTrustAsknow returnsholdsAsks: only an open trust question or Don't trust holds them. Send still waits on the read, and a secret card still waits for it. - Greptile P1: an answer saved in one folder dropped another folder's read in flight. Answers are now counted per folder.
- Review: a remote or peer chat's answer is not cached by path, since that path can match a local folder. A refresh that fails the session check also drops restored groups.
webviews/test/trust-read-keeps-permission.test.tsx was red at b7eb667b9fd8 and at the commit before 02b0063c8df4. It was green locally on 02b0063c8df4, along with the two tests above and tsc. The last commit (f962603e64dd) is verified by CI only, because local runs were stopped on this machine.
- Same folder, no recheck (Leo): switching to another chat or agent in the same folder keeps that folder's last read or answer. It doesn't read the folder again and doesn't draw an unread frame. Only a different folder, a refusal or an answer reads again. The test
another chat in the same folder keeps the folder's answer without reading it againwas committed red at 8bb4143b980a (expected 1 read, got 3).
Observed (webview tests run by hand)
CI's web / react-apps-check stops at the base's eager-JS budget step before it reaches the webview tests, so I ran them on big-red against an export of the merged head f965a6a239f6:
cd webviews && bun install --frozen-lockfile && node scripts/pages/gen-strings.mjs
bunx tsc --noEmit -p . # exit 0
CMUX_BROWSER_TESTS=1 bun test $(ls test | grep -iE "permission|trust" | sed "s#^#test/#")
# 19 pass, 2 skip, 0 fail (21 tests, 11 files)
At the red commit 8bb4143b980a, bun test test/trust-read-keeps-permission.test.tsx gave 3 pass and 1 fail. The new same-folder test was the one that failed.
Not run
permission-ask-row-lookandpermission-ask-row-narrowskip on big-red because WebKit's system libraries are missing. They screenshot the ask row, which this PR doesn't restyle.- No live dogfood and no frame capture.
Changelog
Fixed: the agent chat's permission controls no longer blink when you switch tabs or workspaces, or create or close a workspace.
🤖 Generated with Claude Code