Files
agentic-mobile-control/docs/CONSTITUTION.md
T
q792602257andClaude Opus 4.6 e00c50e703 feat(api): server-rendered Jinja2 Runtime console at /ui/
Replaces the separate Vue/Vite `console/` SPA with a same-origin,
server-rendered console built on a module-level Jinja2 Environment
with select_autoescape(["html","xml"]).

- Add api/console_web.py with /ui/ routes (dashboard, tasks, task
  detail/timeline, config) and a _status_fragment polled every 10s.
- Refactor api/console.py into a typed ConsoleService shared by the
  JSON and HTML routers so validation/persistence cannot drift.
- Remove RUNTIME_CONSOLE_STATIC_DIR, SpaStaticFiles, and the wildcard
  CORS middleware from api/rest.py; GET / now redirects to /ui/.
- Delete the top-level console/ project; add jinja2 and python-multipart
  as direct dependencies and ship templates/CSS/JS via package-data.
- Add 31 tests (XSS probes, PRG flows, fragment refresh, no-static-dir
  and no-CORS regressions, wheel-packaging smoke test).

/console/* JSON endpoints remain unchanged. The console keeps the
trusted-network-only boundary; auth/CSRF is intentionally deferred.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-15 08:03:13 +08:00

2.7 KiB

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.

Packaging Boundary

The repository is a uv workspace with device-agent-runtime as the root member and outer platform packages as separate members. The cloud platform is owned by packages/cloud-platform and may depend on the Runtime through an explicit workspace source; the Runtime distribution must never depend on or package cloud.

All Python members share the committed root uv.lock. The Runtime operator console is server-rendered by the api layer through Jinja2 templates and static assets packaged with device-agent-runtime; there is no separate frontend project or Node build step for the Runtime console. The unrelated cloud-console/ Vue/Vite application keeps its own independent npm lifecycle.

Change Discipline

Future changes must keep the dependency direction:

core -> driver/device -> tools -> perception -> storage -> runtime -> api -> optional outer workspace applications.

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.