From e8a17f42c831230c071e0185f8210c3c46085de6 Mon Sep 17 00:00:00 2001 From: Guilhem Lemouel Date: Mon, 26 Oct 2026 11:21:24 -0700 Subject: [PATCH] fix: close only draft editors during a move, and say why Variable, resource and trigger editors save on click and write no draft, so closing them during a move protected nothing and lost a half-filled form when the move stopped. Only the editors that save drafts close, and the pipeline tab names the move instead of Use mode. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../lib/components/sessions/PreviewTabHost.svelte | 8 +++++--- .../sessions/sessionPermissions.svelte.ts | 14 ++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/frontend/src/lib/components/sessions/PreviewTabHost.svelte b/frontend/src/lib/components/sessions/PreviewTabHost.svelte index 33470fa261..2af69e8747 100644 --- a/frontend/src/lib/components/sessions/PreviewTabHost.svelte +++ b/frontend/src/lib/components/sessions/PreviewTabHost.svelte @@ -424,9 +424,11 @@ {:else}
- {permissions.readOnly - ? 'The pipeline editor saves drafts, which a session in Use mode cannot do.' - : 'The pipeline editor saves drafts, which your role cannot do in this workspace.'} + {permissions.moving + ? 'The pipeline editor reopens once the session has moved to its fork.' + : permissions.readOnly + ? 'The pipeline editor saves drafts, which a session in Use mode cannot do.' + : 'The pipeline editor saves drafts, which your role cannot do in this workspace.'}
{/if} diff --git a/frontend/src/lib/components/sessions/sessionPermissions.svelte.ts b/frontend/src/lib/components/sessions/sessionPermissions.svelte.ts index b8b8476f56..cd84eee925 100644 --- a/frontend/src/lib/components/sessions/sessionPermissions.svelte.ts +++ b/frontend/src/lib/components/sessions/sessionPermissions.svelte.ts @@ -51,7 +51,8 @@ type WorkModeHost = { readonly workMode: AIWorkMode; readonly moving?: boolean } * resolves: hiding every editor from a developer while `whoami` is in flight is the worse * mistake, and the server refuses an operator anyway. A session held in Use opens no editor: one * in a protected workspace, one whose role builds nothing there, or one whose chat is in Use - * mode — the chat `chat` returns, else the `aiChatManager` context's — and one moving into a fork. + * mode — the chat `chat` returns, else the `aiChatManager` context's. One moving into a fork opens + * no draft editor until the move ends, so nothing saves a draft in the workspace being left. * Reads context and registers an effect: call during component initialisation. */ export function useSessionPermissions( @@ -66,9 +67,9 @@ export function useSessionPermissions( const readOnly = $derived( protectedWorkspace.current || !buildsAnything(rights.capabilities) || - host?.workMode === AIWorkMode.USE || - !!host?.moving + host?.workMode === AIWorkMode.USE ) + const moving = $derived(!!host?.moving) const workspaces = fromStore(userWorkspaces) const entry = $derived(workspaces.current.find((w) => w.id === workspace())) @@ -77,11 +78,16 @@ export function useSessionPermissions( get readOnly() { return readOnly }, + /** The session is moving into a fork: its draft editors stay closed until it ends. */ + get moving() { + return moving + }, /** Whether this user can save the drafts the `kind` editor writes. */ - canOpenEditor: (kind: string) => !readOnly && rights.roleCanDraft(kind), + canOpenEditor: (kind: string) => !readOnly && !moving && rights.roleCanDraft(kind), /** The same, and this item's own permissions let them write it. */ canEditItem: (item: Pick) => !readOnly && + !moving && rights.canDraftItem(item.raw_app ? 'raw_app' : item.kind, item.path, item.extraPerms), /** Whether the page loads for this user rather than refusing them. */ pageAllowed: (page: PreviewPage) =>