88 lines
3.0 KiB
Markdown
88 lines
3.0 KiB
Markdown
# PRD 0040: Backend-Aware Resume and Dashboard Reattach
|
|
|
|
- **Status:** Active
|
|
- **Author:** didericis-codex
|
|
- **Created:** 2026-06-02
|
|
- **Issue:** #137
|
|
|
|
## Summary
|
|
|
|
Persist the backend name in `BottleMetadata` and thread it through `resume` and
|
|
dashboard reattach so both flows construct the correct backend bottle without
|
|
relying on env overrides or defaulting to Docker.
|
|
|
|
## Problem
|
|
|
|
`BottleMetadata` records identity, agent, cwd, started_at, and compose project,
|
|
but not the backend name. Without it:
|
|
|
|
- `cli/resume.py` cannot select the right backend from a preserved state dir
|
|
alone; operators must remember to set `BOT_BOTTLE_BACKEND=smolmachines`
|
|
separately.
|
|
- `cli/dashboard.py` `_bottle_for_slug` constructs a `DockerBottle` for any
|
|
externally discovered slug, so reattaching to a live smolmachines agent
|
|
from the dashboard sends Docker commands to a smolvm machine.
|
|
|
|
## Goals / Success Criteria
|
|
|
|
- `BottleMetadata` includes the backend name, written at bottle creation time
|
|
for both Docker and smolmachines.
|
|
- `cli resume` reads the persisted backend name and constructs the correct
|
|
bottle type without requiring an env override.
|
|
- Dashboard reattach (`_bottle_for_slug`) reads the persisted backend name and
|
|
constructs the correct bottle type.
|
|
- Existing Docker bottles without a persisted backend name fall back to Docker
|
|
(backward-compatible default).
|
|
- Unit tests cover write, read, backward-compatible fallback, and both
|
|
resume/reattach code paths.
|
|
|
|
## Non-goals
|
|
|
|
- No changes to manifest or egress configuration.
|
|
- No new CLI flags (backend selection at resume time should be automatic).
|
|
- No smolmachines capability-apply implementation (see PRD 0039).
|
|
|
|
## Scope
|
|
|
|
In scope:
|
|
|
|
- `bot_bottle/backend/docker/bottle_state.py` `BottleMetadata` schema and
|
|
write path.
|
|
- `bot_bottle/backend/docker/bottle.py` and
|
|
`bot_bottle/backend/smolmachines/bottle.py` metadata write at creation.
|
|
- `bot_bottle/cli/resume.py` backend selection from metadata.
|
|
- `bot_bottle/cli/dashboard.py` `_bottle_for_slug` backend selection.
|
|
- Unit tests covering the above.
|
|
|
|
Out of scope:
|
|
|
|
- Migration tooling for existing state dirs.
|
|
- Integration tests that exercise full resume across process restarts.
|
|
|
|
## Design
|
|
|
|
Add a `backend` field to `BottleMetadata` with a default of `"docker"` for
|
|
backward compatibility. Both `DockerBottle` and `SmolmachinesBottle` write
|
|
their backend name into metadata at creation time.
|
|
|
|
`resume` reads the metadata before constructing the bottle object and selects
|
|
the appropriate backend class. `_bottle_for_slug` does the same. A helper
|
|
function in the metadata module can encapsulate the backend-name-to-class
|
|
mapping so the logic is not duplicated.
|
|
|
|
## Testing Strategy
|
|
|
|
- Unit tests for `BottleMetadata` serialisation with and without the backend
|
|
field.
|
|
- Unit tests for the backward-compatible default.
|
|
- Unit tests for `resume` selecting smolmachines vs Docker from metadata.
|
|
- Unit tests for `_bottle_for_slug` selecting smolmachines vs Docker.
|
|
|
|
Run:
|
|
|
|
- `python3 -m unittest discover -s tests/unit`
|
|
|
|
## Open Questions
|
|
|
|
None.
|