6cd50ab841
Backend: - service_task_environments: fail closed when checkAnySessionRunning errors so a transient DB hiccup can't bypass the running-session guard and tear down a live container/sandbox; teardown is now truly best-effort with errors.Join across container/sandbox/worktree, so a failed Docker call doesn't permanently orphan the worktree on retry. Adds tests for the running-check error path and the multi-resource best-effort path. - executor_execute: propagate GetTaskEnvironmentByTaskID errors instead of silently launching a fresh environment that orphans existing containers/worktrees; gate environment reuse on matching ExecutorType so a profile switch doesn't pass stale PreviousExecutionID/container IDs to the wrong backend. - task_environment_handlers: reject malformed JSON on POST /tasks/:id/environment/reset (still allow empty body) so a destructive endpoint doesn't silently proceed with a bad payload. - worktree (PushEnvironmentBranch): bound git push with a 30s context timeout and disable interactive prompts via GIT_TERMINAL_PROMPT=0 so a stalled remote can't hang the request thread. - manager_environment: explicitly call ensureClient() before ContainerMgr() in DestroyContainer/GetContainerLiveStatus so a missing Docker daemon surfaces as "docker unavailable" rather than the generic "container manager not initialized". - container: WorkingDir always uses the in-container /workspace path rather than the host workspace path (Docker would happily start in an unrelated directory in host bind-mount mode); bootstrap now logs the prepare-script exit code so failures show up in container logs. - docker/client: CreateContainerInteractive honors ContainerConfig.Entrypoint so the same config struct produces consistent behavior on both creation paths. Frontend: - executor-settings-button: extract useTaskEnvironment hook (component shrinks below the 100-line limit); only treat 404 as empty env (other errors no longer wipe a valid environment); track "loaded once" via a ref so loadEnv doesn't depend on env state — that dep was creating a new function identity on every successful poll, cancelling the 3-second interval and turning the popover into a tight loop hammering /environment/live; copy-shell command uses sh instead of bash so it works on user-built minimal images. - task-reset-env-confirm-dialog: AlertDialogAction onClick calls e.preventDefault() so Radix's auto-close doesn't dismiss the dialog before the async reset completes (loading spinner now visible; close is parent-controlled via onOpenChange). - remote-credentials-card: track env method in selectedIds the same way files/gh_cli_token are tracked, and let initialChoice match either selectedIds OR envSecretId. First-time env-credential setup for an agent that exposes both files+env was broken: clicking the env radio never updated state, choice re-derived to "none", and the secret picker disappeared before the user could pick anything. - e2e/executor-reuse: select the acknowledge checkbox by label, not by positional last(), so adding another checkbox to the dialog can't silently target the wrong control. Format pass on prettier-flagged files; gofmt fixed two whitespace nits in lifecycle files.