August 11, 2026 · BariBariGood
v0.5.0: one call from clean simulator to evidence
Until now, driving a simulator through manzanas meant hand-sequencing the loop yourself: acquire a lease, boot the target, apply fixtures, install the app, launch it, dispatch a dozen actions, capture artifacts, and, on every failure path, remember to release the lease. Every agent I watched do this wrote the same boilerplate, and every one of them occasionally forgot the release and orphaned a simulator.
v0.5.0 makes the whole loop one call. A run is a declarative spec; the daemon owns the choreography:
acquire lease → boot → fixtures → install app → launch → steps →
artifact capture → release lease (applying its reset)The YAML run-spec
You describe what to lease, what to install, and what to do, the native step DSL is just the existing action surface, one action per step, dispatched and journaled exactly like POST /v0/actions:
# login-smoke.yaml
name: login-smoke
target:
labels: [ios26]
app:
path: /Users/ci/builds/MyApp.app # .app bundle on the daemon host
bundle_id: com.example.myapp
steps:
- action: tap_element
with: {id: username}
- action: type_into_element
with: {id: username, text: agent}
- action: type_into_element
with: {id: password, text: hunter2}
- action: tap_element
with: {label: "Sign In"}
- action: wait_for_element
with: {label: "Welcome, agent!", timeout_ms: 5000}
- name: quality gate
action: auditThen:
$ manzanas run login-smoke.yaml -o evidence.md
run run_1a2b3c4d5e6f7a8b: passed
journal run: lse_0123456789abcdef
step 0 tap_element: ok
step 1 type_into_element: ok
step 2 type_into_element: ok
step 3 tap_element: ok
step 4 wait_for_element: ok
step 5 audit: ok-o evidence.md writes the journal's markdown export, the same document as GET /v0/journal/{run}/export.md , with every step, tree hash, screenshot, and audit finding. Paste it into a PR comment and the run argues for itself.
Steps are actions, not a new language
I deliberately did not invent a test framework. Each step is one action kind from the protocol, with the payload passed through verbatim:
steps:
- name: optional human label
action: tap_element # any action kind: tap, swipe, type,
with: {id: username} # tap_element, wait_for_element,
timeout_seconds: 15 # scroll_to_element, observe,
continue_on_error: false # screenshot, audit, batch...Steps stop at the first failure (later steps report skipped); continue_on_error lets cleanup steps run anyway. Whatever fails, a step, a boot, an install, the run budget expiring, the lease is always released with its reset. The evidence trail of a red run is as complete as a green one.
Three frontends, one schema
The same spec drives POST /v0/runs (the wire API, sync by default, async with polling for long runs), manzanas run spec.yaml (the CLI), and the MCP run tool, so an agent that speaks MCP gets the one-call loop for free. All three also work pointed at a broker: the run is placed on a fleet host with the same warm-first ranking as lease scheduling, then proxied to the owning daemon.
Also in v0.5.0
Broker-transparent clients. The CLI and MCP server now follow a broker lease's host_addr annotation automatically, point them at the broker and every lease-scoped call routes to the owning daemon. Fleet dashboard. The broker serves an aggregated /dash across every daemon, next to each daemon's own. Version surfacing + optional auth. Binaries report the build version stamped at link time, and --auth-token puts a shared bearer token in front of the whole API. Mock actions backend. --mock now carries a full deterministic action backend, so the entire loop, including runs, works on a Linux box with no Mac at all. That one gets its own post.
v0.5.0 is on GitHub and the Homebrew tap. Full run-spec reference in docs/runs.md.