diff --git a/src/live-worktree.ts b/src/live-worktree.ts index 86b85a1c..6f3738be 100644 --- a/src/live-worktree.ts +++ b/src/live-worktree.ts @@ -31,9 +31,12 @@ * `workingDir`. * * For an outside worktree {@link findOutsideWorktree} IS the confinement decision for the second - * root. Its vouching, home, Docker and `allowRoot` rules run only when the pane moves. The routes - * re-check on each request only that the folder still realpaths to the recorded path - * (`outsideWorktreeRootFor()`, `canWalkOutsideWorktree()`). + * root. Its vouching, home and Docker rules, and the multi-user half of `allowRoot`, run only when + * the pane moves. The routes re-check two things on each request: that the folder still realpaths + * to the recorded path (`outsideWorktreeRootFor()`, `canWalkOutsideWorktree()`), and the attachment + * guard half of `allowRoot` (workspace confinement, blocked and sensitive trees: + * `isOutsideWorktreeRootRefused()` through `withGuardedOutsideWorktree()` in file-routes.ts), so a + * guard setting changed later applies at once. * * Probes are bounded (#516). The folder can sit on a mount that stopped answering, and an * `unknown` answer stops the walk rather than being read as "no `.git` here". diff --git a/src/web/server.ts b/src/web/server.ts index a50b314f..1dbcbb00 100644 --- a/src/web/server.ts +++ b/src/web/server.ts @@ -3054,12 +3054,14 @@ export class WebServer extends EventEmitter { * * Codeman judges these rules when the pane moves. The file routes judge the two guard rules * again on every request (`isOutsideWorktreeRootRefused()`), so a setting changed later applies - * at once. The Docker and multi-user rules are judged only when the pane moves. Undefined for a remote or Docker session, - * whose pane directory is not a path the agent works in on this host (it has no `paneCwd` - * either, so this is belt and braces). + * at once. The Docker and multi-user rules are judged only when the pane moves. Undefined for a remote, Docker or + * adopted session, whose pane directory is not a path the agent works in on this host (an + * adopted session's pane runs our tmux attach client). None of the three gets a `paneCwd` + * either (`paneExitApplies`), so this is belt and braces; an adopted session needs its own + * test because `session.remote` and `session.docker` are undefined on one. */ private outsideWorktreeOptions(session: Session): OutsideWorktreeOptions | undefined { - if (session.remote || session.docker) return undefined; + if (session.remote || session.docker || session.isAdopted) return undefined; return { dockerWorkspaces: defaultDockerWorkspaces, allowRoot: async (root: string): Promise => {