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) =>