PRD: Commit bottle state to an image #240
Reference in New Issue
Block a user
Delete Branch "commit-bottle-state"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #194.
PRD
Summary
./cli.py commit [<slug>]to snapshot a running Docker bottle's container state viadocker commit~/.bot-bottle/state/<slug>/committed-image) so the next./cli.py resumeboots from the snapshot instead of rebuilding99b23db16cto8eea8f83a28eea8f83a2toc6e976fa7dWould like to implement this for macos containers and smolmachines as well. I know it's possible for smolmachines at least, not sure about macos.
For smolmachines, the local registry machinery already exists in
local_registry.py— the implementation path is: docker-commit the running container, push it to the ephemeral registry, and repack viasmolvm pack create. That reuses exactly the same docker→smolmachine conversion pipelinelaunch.pyalready runs at start time. The main open question is whethersmolvmexposes a way to identify which docker container backs a running machine (so we know what to commit), or whether we need to track that mapping ourselves in bottle state.For macOS containers, it depends on whether Apple's
containerCLI has acommitsubcommand. Theutil.pypattern is already there (build_image,save,image_exists), so ifcontainer commit <name> <tag>works it's a small addition. Worth checking the Apple container release notes — if the subcommand exists, the implementation is straightforward; if not, the export path (container image save→ retag → reload) may still work but with a larger snapshot.Happy to open a follow-up issue tracking both once we know the smolvm container-name mapping answer.
@didericis-codex implement the smolmachines backend commit flow
Implemented the smolmachines backend commit flow in
02b38b63f5.Summary:
./cli.py commit <slug>now usessmolvm pack create --from-vmfor smolmachines bottles and stores the resulting.smolmachineartifact path in per-bottle state.Verification:
.venv/bin/pyright .python3 -m unittest discover -t . -s tests/unit -v02b38b63f5to16020a6a09There's a catch 22 here: when we try to commit a running bottle, it asks for the bottle to be stopped
But when we stop it, it gets cleaned up.
We should make it so committing does the following:
Fixed in
3cd4a7a.container exportrequires the container to be stopped. The commit command now:container list --quiet)container stop <name>on confirmation./cli.py resume <slug>Changes:
macos_container/util.pygainscontainer_is_running+stop_container;cli/commit.pywires the stop-confirm flow before the export step. Two new unit tests cover the yes/no paths.@didericis-claude I'd like you to create an
Freezerclass with a shared between all the backends that's responsible for taking an activeAgentandBottleclass and "freezing" them via acommitmethod. This should follow the same pattern we follow for backends: a genericFreezeclass with the shared logic in the base class, and backend specific methods in the backend specific classes.Done in
8ab2472.Added a
FreezerABC (backend/freeze.py) following the same pattern asBottleBackend:Freezer.commit(agent: ActiveAgent, bottle: Bottle)— primary entry point for use within a live launch context; calls_freeze, then owns the shared post-commit steps (write_committed_image,mark_preserved, resume hint)Freezer.commit_slug(slug)— convenience entry forcmd_commitwhen no liveBottleis available; constructs a name-only_NamedBottlestub and delegates tocommitget_freezer(backend_name) -> Freezer— factory, analogous toget_bottle_backendCommitCancelled— raised when the user declines a stop promptBackend subclasses:
backend/docker/freezer.py—DockerFreezer:docker commitbackend/macos_container/freezer.py—MacosContainerFreezer: stop-confirm flow +container exportbackend/smolmachines/freezer.py—SmolmachinesFreezer:smolvm pack create --from-vmcmd_commitno longer branches on backend names — it reads the backend from metadata, callsget_freezer(backend).commit_slug(slug), and catchesCommitCancelled.828101412ctoe74a5e0219Adds a Freezer ABC (backend/freeze.py) that encapsulates the stop-commit-mark-preserved flow for all backends, following the same pattern as BottleBackend. Each backend gets its own Freezer subclass: DockerFreezer — docker commit MacosContainerFreezer — container export + image rebuild; prompts to stop if the container is running SmolmachinesFreezer — smolvm pack create --from-vm The base class owns write_committed_image, mark_preserved, and the resume hint. Subclasses implement _freeze() and optionally override _export_hint() for migration instructions. Freezer.commit(agent, bottle) is the primary entry point for use within a live launch context. Freezer.commit_slug(slug) is a convenience wrapper for cmd_commit, which no longer branches on backend names itself. get_freezer(backend_name) is the factory, analogous to get_bottle_backend(). CommitCancelled is raised by MacosContainerFreezer when the user declines the stop prompt; cmd_commit catches it and returns 0.Freezer._freeze only ever used bottle.name, which is always f"bot-bottle-{agent.slug}". Remove the Bottle parameter from commit() and _freeze(), derive the container name from agent.slug directly in each subclass, and delete the _NamedBottle stub that existed solely to paper over this.e74a5e0219toc48c3688b8