feat(agents): ContainerLifecyclePort + DockerContainerLifecycle adapter #515

Closed
opened 2026-04-28 09:24:22 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As DefaultAgentDispatch, I want a port that owns container pre-flight, env binding, and exec setup, so that agent-runner orchestration is decoupled from Docker specifics and host-mode falls out as a no-op adapter.

Acceptance criteria

Port

  • apps/server/src/domain/ports/container-lifecycle-port.ts exports:
    • ensureReady(agent: AgentInstance): Promise<ContainerHandle>
    • buildExecEnv(agent: AgentInstance, req: AgentDispatchRequest): Record<string, string>
    • buildExecArgs(handle: ContainerHandle, env: Record<string, string>): ExecSpec
    • release(handle: ContainerHandle, reason: ReleaseReason): Promise<void>
  • No dockerode / child_process types leak through ContainerHandle

Adapter

  • apps/server/src/infrastructure/agents/docker-container-lifecycle.ts
    • Extracts buildDockerExecArgs() from infrastructure/agents/container.ts
    • Extracts pre-flight (image present, container running, settings.json written) from agent-runner.ts:543–548 host-mode branch
    • release() covers worktree cleanup paths used today
  • Host-mode foreman adapter: apps/server/src/infrastructure/agents/host-container-lifecycle.ts returns a no-op handle (cwd workdir, no exec wrap)

Tests

  • Unit test: docker adapter builds correct exec args for a fixture agent
  • Unit test: host adapter returns no-op handle, release() is idempotent

Out of scope

  • Wiring into DefaultAgentDispatch — separate issue
  • Watchdog / reconciliation behaviour changes — already covered by docs/containers.md

References

  • docs/containers.md
  • apps/server/src/infrastructure/agents/container.ts
  • apps/server/src/infrastructure/agents/agent-runner.ts:513–548
## User story As `DefaultAgentDispatch`, I want a port that owns container pre-flight, env binding, and exec setup, so that agent-runner orchestration is decoupled from Docker specifics and host-mode falls out as a no-op adapter. ## Acceptance criteria ### Port - [ ] `apps/server/src/domain/ports/container-lifecycle-port.ts` exports: - [ ] `ensureReady(agent: AgentInstance): Promise<ContainerHandle>` - [ ] `buildExecEnv(agent: AgentInstance, req: AgentDispatchRequest): Record<string, string>` - [ ] `buildExecArgs(handle: ContainerHandle, env: Record<string, string>): ExecSpec` - [ ] `release(handle: ContainerHandle, reason: ReleaseReason): Promise<void>` - [ ] No `dockerode` / `child_process` types leak through `ContainerHandle` ### Adapter - [ ] `apps/server/src/infrastructure/agents/docker-container-lifecycle.ts` - [ ] Extracts `buildDockerExecArgs()` from `infrastructure/agents/container.ts` - [ ] Extracts pre-flight (image present, container running, settings.json written) from `agent-runner.ts:543–548` host-mode branch - [ ] `release()` covers worktree cleanup paths used today - [ ] Host-mode foreman adapter: `apps/server/src/infrastructure/agents/host-container-lifecycle.ts` returns a no-op handle (cwd workdir, no exec wrap) ### Tests - [ ] Unit test: docker adapter builds correct exec args for a fixture agent - [ ] Unit test: host adapter returns no-op handle, `release()` is idempotent ## Out of scope - Wiring into `DefaultAgentDispatch` — separate issue - Watchdog / reconciliation behaviour changes — already covered by `docs/containers.md` ## References - `docs/containers.md` - `apps/server/src/infrastructure/agents/container.ts` - `apps/server/src/infrastructure/agents/agent-runner.ts:513–548`
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#515
No description provided.