fix(docker): verify the container workdir and end the probe with exit 0

Two defects that only a real container exposes.

The probe chained `command -v X && echo X` with semicolons, and a script's exit
status is its last command's. A container without the last probed CLI made the
whole `sh -lc` exit 1, so a perfectly healthy container with tmux and claude was
reported as "could not exec into the container". A missing CLI is data here, not
failure, so the script now ends with `exit 0`.

containerWorkdir defaulted to hostWorkspacePath. That default holds for an owned
container only because the create-time bind mount puts the host directory at that
exact path; attaching mounts nothing, so the two are independent facts. A host
path absent inside the container makes `docker exec --workdir` fail with an OCI
chdir error that surfaces in the pane as a bare "execvp failed". The preflight now
proves the directory exists inside the container and refuses at link time.
This commit is contained in:
d fei
2026-08-29 21:02:19 -07:00
parent bc55b6b0da
commit c98a59d709
5 changed files with 69 additions and 7 deletions
+11 -2
View File
@@ -837,7 +837,15 @@ export function registerCaseRoutes(app: FastifyInstance, ctx: EventPort & Config
availability.error || 'docker daemon is not available'
);
}
const probe = await probeAdoptableContainer(toSessionDocker(host, dockerCase), [...DOCKER_ADOPT_PROBE_MODES]);
// The container workdir is validated INSIDE the container. It defaults to
// hostWorkspacePath only because that is what an owned container's bind
// mount guarantees; adoption mounts nothing, so the probe has to prove it.
const adoptDocker = toSessionDocker(host, dockerCase);
const probe = await probeAdoptableContainer(
adoptDocker,
[...DOCKER_ADOPT_PROBE_MODES],
adoptDocker.containerWorkdir
);
if (!probe.ok) {
return createErrorResponse(ApiErrorCode.OPERATION_FAILED, probe.error || 'container is not adoptable');
}
@@ -871,7 +879,8 @@ export function registerCaseRoutes(app: FastifyInstance, ctx: EventPort & Config
daemonHost: host.daemonHost,
containerName: body.container,
},
[...DOCKER_ADOPT_PROBE_MODES]
[...DOCKER_ADOPT_PROBE_MODES],
body.containerWorkdir
);
return { success: true, data: probe };
});