Phase 2 of PRD 0016. New module
claude_bottle/backend/docker/capability_apply.py:
- apply_capability_change(slug, new_dockerfile): snapshot transcript
→ push working tree → write per-bottle Dockerfile → teardown.
Returns (before, after) for the dashboard's audit/diff render.
- fetch_current_dockerfile(slug): per-bottle Dockerfile if set,
else the repo's Dockerfile.
- Internal helpers _snapshot_transcript, _push_working_tree are
best-effort (log + return on failure); _teardown_bottle is
idempotent (force-rm + network rm silently ignore missing names).
Fire-and-forget from the agent's perspective: by the time the
dashboard writes the response file the supervise sidecar is already
gone (it was torn down), so the agent's tool call connection drops
without receiving the response. The replacement agent (next manual
`cli.py start <agent>`) sees the new per-bottle Dockerfile and the
transcript snapshot for resume. v1 does not auto-relaunch.
Tests cover sequencing (snapshot → push → teardown order), the
per-bottle vs repo Dockerfile fallback chain, empty-input rejection,
and the per-bottle-Dockerfile write. The docker exec / cp / rm
plumbing is covered by the Phase 4 integration test.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>