# Constitution These invariants are durable project rules. Every future milestone change must state in its `design.md` how it preserves them. ## Device Boundary `Driver` is the only device-capability contract. Concrete drivers translate external SDKs into that contract and do not own task, workflow, or planner state. Drivers are stateless with respect to agent tasks. A driver may hold a live connection handle, but task memory, retries, plans, and workflow state belong above the driver layer. ## Tool Boundary `tools/` exposes device capabilities to the runtime. Tools call into device/driver capabilities through abstractions and never import a concrete driver such as `WDADriver`. ## Perception Boundary `Scene` is the only perception artifact the LLM sees, with one narrow, explicit exception: the runtime-layer AI `Planner` (and only that Planner) may additionally receive the raw screenshot bytes for the current step, alongside `Scene`, to support vision-grounded decision-making. No other layer — `api`, `tools`, `perception`, `storage`, or any other LLM consumer — may receive raw screenshot bytes; every other perception consumer still receives `Scene` only. `Scene` itself is still produced exclusively through `PerceptionProvider`, not by direct calls to OCR, UI tree parsing, or `scene_builder` from runtime and API layers. ## Runtime Boundary The Planner produces a plan. The Executor is the only component that calls tools and handles retries for tool execution. LLM dependencies enter at `runtime` through Planner behavior. HTTP and MCP dependencies enter at `api`. No LLM, HTTP, or MCP dependency may appear in `core`, `driver`, `device`, or `tools`. ## Change Discipline Future changes must keep the dependency direction: `core` -> `driver`/`device` -> `tools` -> `perception` -> `storage` -> `runtime` -> `api`. When a change needs a new external integration, add it at the adapter layer that owns that concern, not at the domain or device boundary.