* fix(web): preserve manual task selection during archive/delete
When the user archived (or deleted) a task and then immediately picked
another task, the in-flight archive flow would auto-switch to a third
task, clobbering the manual selection.
The shared `removeTaskFromBoard` was honoring the pre-API captured
`wasActiveTaskId` unconditionally. That capture exists to survive the
WS `task.deleted` / `task.updated(archived_at)` handler clearing
`activeTaskId` to null. But it also overrode the legitimate case where
the current store value reflected a user-initiated navigation, so the
equality check still passed and `switchToNextTask` ran.
New guard: switch only when (a) the store still points at the removed
task, or (b) the store has been WS-cleared to null AND the captured
pre-API id matches the removed task. Any other state means the user
moved on — leave them where they chose to go.
* chore(web): tighten null check + no-opts test in use-task-removal
Addresses non-blocking suggestions from claude bot review on #1286.
- Use strict `=== null` in `shouldSwitchAfterRemoval` for consistency
with the surrounding strict-equality comparison.
- Add unit test documenting that a no-opts caller skips the auto-switch
when the WS handler has already cleared `activeTaskId` to null.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat(backend): key user shells by TaskEnvironmentID
Sessions in the same task share a TaskEnvironment. Re-key the user shell
runner so terminals are scoped per env, not per session — switching between
sessions of the same task now sees the same shell list.
- Add TaskEnvironmentID to AgentExecution / LaunchRequest / ExecutorCreateRequest
/ executor.LaunchAgentRequest, propagated through ToAgentExecution and the
orchestrator launch path.
- Add Manager.ResolveScopeKey(sessionID) — returns env when execution carries
it, falls back to sessionID for legacy paths.
- Rename runner param sessionID -> scopeID in interactive_shells.go; map keys
are now scopeID:terminalID.
- Shell handlers + WS terminal handler resolve sid -> scopeID via
ResolveScopeKey before calling the runner.
* feat(web): key dockview layout + portals to TaskEnvironmentID
Switching between sessions of the same task no longer rebuilds the dockview
layout — terminals and panels persist because layouts are env-scoped, not
session-scoped. The bottom terminal also reuses a stable sessionId across
same-env switches so it doesn't reconnect to a different shell.
- Rename layout persistence: setSessionLayout/getSessionLayout/*SessionMaximizeState
-> setEnvLayout/getEnvLayout/*EnvMaximizeState (kandev.dockview.env-layout. prefix).
- Rename dockview-session-switch.ts -> dockview-env-switch.ts; performSessionSwitch
-> performEnvSwitch with oldEnvId/newEnvId/activeSessionId.
- dockview-store.ts: currentLayoutSessionId -> currentLayoutEnvId; switchSessionLayout
-> switchEnvLayout(oldEnvId, newEnvId, activeSessionId). Same-env switches no-op.
Drop _skipLayoutSwitchForSession + consumeSkipFlag — env-keyed action handles it
structurally.
- panel-portal-manager: PortalEntry.envId; releaseBySession -> releaseByEnv.
ENV_SCOPED_COMPONENTS in dockview-desktop-layout (renamed from SESSION_SCOPED).
- useEnvSwitchCleanup replaces useSessionSwitchCleanup; tracks env changes only.
- All performLayoutSwitch callers (sidebar, dropdown, header, dialog) resolve
sid -> envId via environmentIdBySessionId before switching.
- bottom-terminal-panel: drop sessionId prop, use useEnvironmentSessionId().
- cleanupTaskStorage now takes envIds[] alongside sessionIds[] for env-scoped
layout/maximize cleanup.
* test: add coverage for env-keyed terminals + layout
Playwright e2e (terminal-env-keyed.spec.ts) — switching between sessions of
the same task keeps terminal scrollback intact and asserts both sessions
share one task_environment_id. Update the comment in
sessionless-task-switch.spec.ts to reference performEnvSwitch.
* fix: address env layout PR feedback
* test: fix flaky handshake auth check
* fix: address env scope review findings