Bottle was the only Protocol in an otherwise-ABC family
(BottlePlan, BottleCleanupPlan, BottlePlatform are all ABCs).
Convert to an ABC with abstract exec_claude / cp_in / close,
matching the rest of the hierarchy.
Rename _DockerBottle -> DockerBottle: the underscore was a
default-Python-private instinct that doesn't match the sibling
plan classes (DockerBottlePlan, DockerBottleCleanupPlan), all of
which are equally "only constructed by the platform" and yet
public-by-name.
Re-export DockerBottle from claude_bottle.bottles.docker.
The single docker/__init__.py grew to ~555 lines holding the platform,
its plan classes, the bottle handle, and the runsc probe. Split into:
- util.py : Docker subprocess primitives + runsc_available
- bottle_plan.py : DockerBottlePlan (+ its print method)
- bottle_cleanup_plan.py : DockerBottleCleanupPlan
- bottle.py : _DockerBottle handle class
- platform.py : DockerBottlePlatform (the bulk)
docker/__init__.py becomes a thin re-export shim so existing imports
(claude_bottle.bottles.docker.DockerBottlePlatform, etc.) keep working.
- claude_bottle/bottles/docker.py -> claude_bottle/bottles/docker/__init__.py
- claude_bottle/docker.py -> claude_bottle/bottles/docker/util.py
The host-side Docker primitives (require_docker, slugify, image_exists,
container_exists, build_image, build_image_with_cwd) lived at the top
of the package as if cross-cutting, but they are Docker-specific.
Moving them into bottles/docker/util.py colocates them with the
platform that uses them and clears the top-level namespace.
Imports in bottles/docker/__init__.py shift to `from . import util as
docker_mod` so the existing call sites (`docker_mod.require_docker()`,
etc.) keep working unchanged.