Promote stable workspace product for 3.0.0

Freeze the current workspace-first surface as the stable 3.0 contract and reposition the
landing docs, CLI help, and public contract around the stable workspace path after the
one-shot proof.

Bump the package and catalog compatibility to 3.0.0, add a dedicated workspace walkthrough
tape/GIF, and mark the 3.0.0 roadmap milestone done while keeping runtime capability
unchanged in this release.

Validation: uv lock; UV_CACHE_DIR=.uv-cache make check; UV_CACHE_DIR=.uv-cache make dist-check;
UV_CACHE_DIR=.uv-cache uv build; UV_CACHE_DIR=.uv-cache uvx --from twine twine check dist/*;
built-wheel CLI smoke for pyro --help and pyro workspace --help; vhs validate plus rendered
workspace-first-run.gif outside the sandbox because vhs crashes when sandboxed.
This commit is contained in:
Thales Maciel 2026-03-12 18:59:09 -03:00
parent c82f4629b2
commit f2d20ef30a
15 changed files with 255 additions and 42 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View file

@ -0,0 +1,98 @@
Output docs/assets/workspace-first-run.gif
Require uv
Require python3
Set Shell "zsh"
Set FontSize 18
Set Width 1400
Set Height 860
Set Theme "Dracula"
Set TypingSpeed 35ms
Set Padding 24
Set WindowBar Colorful
Hide
Type "cd /home/thales/projects/personal/pyro"
Enter
Type "setopt interactivecomments"
Enter
Type "export UV_CACHE_DIR=.uv-cache"
Enter
Type "export PYRO_ENVIRONMENT_CACHE_DIR=$(mktemp -d)"
Enter
Type "alias pyro='uv run pyro'"
Enter
Type "SEED_DIR=$(mktemp -d)"
Enter
Type "SYNC_DIR=$(mktemp -d)"
Enter
Type "EXPORT_DIR=$(mktemp -d)"
Enter
Type 'printf "%s\n" "hello from seed" > "$SEED_DIR/note.txt"'
Enter
Type 'printf "%s\n" "hello from sync" > "$SYNC_DIR/note.txt"'
Enter
Type "pyro env pull debian:12 >/dev/null"
Enter
Show
Type "# Create a stable workspace from host content and capture its id"
Enter
Sleep 700ms
Type 'pyro workspace create debian:12 --seed-path "$SEED_DIR" --json | tee /tmp/pyro-workspace.json'
Enter
Sleep 2200ms
Hide
Type 'export WORKSPACE_ID=$(python3 -c "import json; print(json.load(open(\"/tmp/pyro-workspace.json\", encoding=\"utf-8\"))[\"workspace_id\"])")'
Enter
Show
Type "# Push a later host-side change into the same workspace"
Enter
Sleep 700ms
Type 'pyro workspace sync push "$WORKSPACE_ID" "$SYNC_DIR"'
Enter
Sleep 1800ms
Type "# Run inside the live workspace"
Enter
Sleep 700ms
Type 'pyro workspace exec "$WORKSPACE_ID" -- cat note.txt'
Enter
Sleep 2000ms
Type "# Capture a checkpoint, then start one long-running service"
Enter
Sleep 700ms
Type 'pyro workspace snapshot create "$WORKSPACE_ID" checkpoint'
Enter
Sleep 1800ms
Type 'pyro workspace service start "$WORKSPACE_ID" web --ready-file .web-ready -- sh -lc "touch .web-ready && while true; do sleep 60; done"'
Enter
Sleep 2200ms
Type "# Reset the full sandbox back to that checkpoint"
Enter
Sleep 700ms
Type 'pyro workspace reset "$WORKSPACE_ID" --snapshot checkpoint'
Enter
Sleep 2200ms
Type "# Export one file back to the host and inspect it locally"
Enter
Sleep 700ms
Type 'pyro workspace export "$WORKSPACE_ID" note.txt --output "$EXPORT_DIR/note.txt"'
Enter
Sleep 1800ms
Type 'cat "$EXPORT_DIR/note.txt"'
Enter
Sleep 1800ms
Type "# Remove the workspace when the loop is done"
Enter
Sleep 700ms
Type 'pyro workspace delete "$WORKSPACE_ID"'
Enter
Sleep 2000ms

View file

@ -22,7 +22,7 @@ Networking: tun=yes ip_forward=yes
```bash
$ uvx --from pyro-mcp pyro env list
Catalog version: 2.10.0
Catalog version: 3.0.0
debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows.
debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling.
debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled.
@ -66,7 +66,25 @@ The guest command output and the `[run] ...` summary are written to different st
may appear in either order in terminals or capture tools. Use `--json` if you need a
deterministic structured result.
## 5. Optional next steps
## 5. Continue into the stable workspace path
The commands below use the published-package form. The same stable workspace path works with an
installed `pyro` binary by dropping the `uvx --from pyro-mcp` prefix, or with `uv run pyro` from
a source checkout.
```bash
$ uvx --from pyro-mcp pyro workspace create debian:12 --seed-path ./repo --json | tee /tmp/pyro-workspace.json
$ export WORKSPACE_ID="$(python -c 'import json,sys; print(json.load(sys.stdin)["workspace_id"])' < /tmp/pyro-workspace.json)"
$ uvx --from pyro-mcp pyro workspace sync push "$WORKSPACE_ID" ./changes
$ uvx --from pyro-mcp pyro workspace exec "$WORKSPACE_ID" -- cat note.txt
$ uvx --from pyro-mcp pyro workspace snapshot create "$WORKSPACE_ID" checkpoint
$ uvx --from pyro-mcp pyro workspace service start "$WORKSPACE_ID" web --ready-file .web-ready -- sh -lc 'touch .web-ready && while true; do sleep 60; done'
$ uvx --from pyro-mcp pyro workspace reset "$WORKSPACE_ID" --snapshot checkpoint
$ uvx --from pyro-mcp pyro workspace export "$WORKSPACE_ID" note.txt --output ./note.txt
$ uvx --from pyro-mcp pyro workspace delete "$WORKSPACE_ID"
```
## 6. Optional one-shot demo and expanded workspace flow
```bash
$ uvx --from pyro-mcp pyro demo
@ -187,7 +205,7 @@ $ uvx --from pyro-mcp pyro workspace service stop WORKSPACE_ID worker
Use `--seed-path` when the workspace should start from a host directory or a local
`.tar` / `.tar.gz` / `.tgz` archive instead of an empty `/workspace`. Use
`pyro workspace sync push` when you need to import later host-side changes into a started
workspace. Sync is non-atomic in `2.10.0`; if it fails partway through, prefer `pyro workspace reset`
workspace. Sync is non-atomic in `3.0.0`; if it fails partway through, prefer `pyro workspace reset`
to recover from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the current
`/workspace` tree to its immutable create-time baseline, `pyro workspace snapshot *` to create
named checkpoints, and `pyro workspace export` to copy one changed file or directory back to the
@ -203,6 +221,10 @@ materialized at `/run/pyro-secrets/<name>`, and `--secret-env SECRET_NAME[=ENV_V
secret into one exec, shell, or service call without storing that environment mapping on the
workspace itself.
The stable workspace walkthrough GIF in the README is rendered from
[docs/assets/workspace-first-run.tape](assets/workspace-first-run.tape) with
[scripts/render_tape.sh](../scripts/render_tape.sh).
Example output:
```json

View file

@ -55,6 +55,8 @@ pyro run debian:12 -- git --version
If you are running from a repo checkout instead, replace `pyro` with `uv run pyro`.
After that one-shot proof works, continue into the stable workspace path with `pyro workspace ...`.
### 1. Check the host first
```bash
@ -83,7 +85,7 @@ uvx --from pyro-mcp pyro env list
Expected output:
```bash
Catalog version: 2.10.0
Catalog version: 3.0.0
debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows.
debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling.
debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled.
@ -131,7 +133,34 @@ deterministic structured result.
If guest execution is unavailable, the command fails unless you explicitly pass
`--allow-host-compat`.
## 5. Optional demo proof point
## 5. Continue into the stable workspace path
The commands below use plain `pyro ...`. Run the same flow with `uvx --from pyro-mcp pyro ...`
for the published package, or `uv run pyro ...` from a source checkout.
```bash
uv tool install pyro-mcp
WORKSPACE_ID="$(pyro workspace create debian:12 --seed-path ./repo --json | python -c 'import json,sys; print(json.load(sys.stdin)["workspace_id"])')"
pyro workspace sync push "$WORKSPACE_ID" ./changes
pyro workspace exec "$WORKSPACE_ID" -- cat note.txt
pyro workspace snapshot create "$WORKSPACE_ID" checkpoint
pyro workspace service start "$WORKSPACE_ID" web --ready-file .web-ready -- sh -lc 'touch .web-ready && while true; do sleep 60; done'
pyro workspace reset "$WORKSPACE_ID" --snapshot checkpoint
pyro workspace export "$WORKSPACE_ID" note.txt --output ./note.txt
pyro workspace delete "$WORKSPACE_ID"
```
This is the stable persistent-workspace contract:
- `workspace create` seeds `/workspace`
- `workspace sync push` imports later host-side changes
- `workspace exec` and `workspace shell *` keep work inside one sandbox
- `workspace service *` manages long-running processes with typed readiness
- `workspace snapshot *` and `workspace reset` make reset-over-repair explicit
- `workspace diff` compares against the immutable create-time baseline
- `workspace export` copies results back to the host
## 6. Optional demo proof point
```bash
uvx --from pyro-mcp pyro demo
@ -188,7 +217,7 @@ After the CLI path works, you can move on to:
- Python SDK: `from pyro_mcp import Pyro`
- Demos: `pyro demo` or `pyro demo --network`
## Persistent Workspace
## Stable Workspace
Use `pyro workspace ...` when you need repeated commands in one sandbox instead of one-shot `pyro run`.
@ -225,7 +254,7 @@ Workspace commands default to the persistent `/workspace` directory inside the g
the identifier programmatically, use `--json` and read the `workspace_id` field. Use `--seed-path`
when the workspace should start from a host directory or a local `.tar` / `.tar.gz` / `.tgz`
archive. Use `pyro workspace sync push` for later host-side changes to a started workspace. Sync
is non-atomic in `2.10.0`; if it fails partway through, prefer `pyro workspace reset` to recover
is non-atomic in `3.0.0`; if it fails partway through, prefer `pyro workspace reset` to recover
from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the current workspace
tree to its immutable create-time baseline, `pyro workspace snapshot *` to capture named
checkpoints, and `pyro workspace export` to copy one changed file or directory back to the host. Use

View file

@ -7,7 +7,8 @@ CLI path in [install.md](install.md) or [first-run.md](first-run.md).
## Recommended Default
Use `vm_run` first for one-shot commands.
Use `vm_run` first for one-shot commands, then move to the stable workspace surface when the
agent needs to inhabit one sandbox across multiple calls.
That keeps the model-facing contract small:
@ -16,8 +17,8 @@ That keeps the model-facing contract small:
- one ephemeral VM
- automatic cleanup
Move to `workspace_*` only when the agent truly needs repeated commands in one workspace across
multiple calls.
Move to `workspace_*` when the agent needs repeated commands, shells, services, snapshots, reset,
diff, or export in one stable workspace across multiple calls.
## OpenAI Responses API

View file

@ -1,6 +1,6 @@
# Public Contract
This document defines the supported public interface for `pyro-mcp` `2.x`.
This document defines the stable public interface for `pyro-mcp` `3.x`.
## Package Identity
@ -9,6 +9,11 @@ This document defines the supported public interface for `pyro-mcp` `2.x`.
- Public Python import: `from pyro_mcp import Pyro`
- Public package-level factory: `from pyro_mcp import create_server`
Stable product framing:
- `pyro run` is the stable one-shot entrypoint.
- `pyro workspace ...` is the stable persistent workspace contract.
## CLI Contract
Top-level commands:

View file

@ -2,7 +2,7 @@
This roadmap turns the agent-workspace vision into release-sized milestones.
Current baseline is `2.10.0`:
Current baseline is `3.0.0`:
- workspace persistence exists and the public surface is now workspace-first
- host crossing currently covers create-time seeding, later sync push, and explicit export
@ -37,16 +37,13 @@ also expected to update:
5. [`2.8.0` Named Snapshots And Reset](task-workspace-ga/2.8.0-named-snapshots-and-reset.md) - Done
6. [`2.9.0` Secrets](task-workspace-ga/2.9.0-secrets.md) - Done
7. [`2.10.0` Network Policy And Host Port Publication](task-workspace-ga/2.10.0-network-policy-and-host-port-publication.md) - Done
8. [`3.0.0` Stable Workspace Product](task-workspace-ga/3.0.0-stable-workspace-product.md)
8. [`3.0.0` Stable Workspace Product](task-workspace-ga/3.0.0-stable-workspace-product.md) - Done
9. [`3.1.0` Secondary Disk Tools](task-workspace-ga/3.1.0-secondary-disk-tools.md)
## Definition Of Done For The Roadmap
## Remaining Follow-Up
The workspace product is ready to leave beta when:
The core workspace product is now stable. The remaining planned follow-up is intentionally
secondary:
- the public contract is workspace-first rather than task-first
- an agent can inhabit a sandbox through shell, exec, service, diff, export,
snapshot, reset, and explicit host-crossing operations
- the main docs lead with the workspace product, not one-shot VM execution
- the remaining deliberate deferrals are secondary disk tools rather than core
workspace features
- `3.1.0` secondary disk tools for offline inspection and disk-level workflows
- no further roadmap milestone changes the stable workspace-first core contract

View file

@ -1,5 +1,7 @@
# `3.0.0` Stable Workspace Product
Status: Done
## Goal
Freeze the workspace-first public contract and promote the product from a