Blog

Module Partitioning Boundaries in Eva-CLI

How Eva-CLI turns architecture decisions into Rust crate boundaries, dependency direction, runtime handoffs, and controlled side-effect ownership.

Published: Category: Runtime

Eva-CLI's module partitioning is not a crate-naming exercise. It is the architecture boundary that decides where authority lives, where side effects are allowed, and how hot-reloadable Agent behavior can evolve without turning the runtime into an unstructured script host.

The short version is deliberate: Rust owns trusted runtime boundaries, Lua owns replaceable business behavior, EventBus and Scheduler own coordination, Adapter and service crates own side effects, and eva-runtime is the only place where concrete implementations are composed.

Eva-CLI module partition overview showing CLI, runtime, core contracts, event routing, Agents, Lua host, adapters, memory, storage, discovery, lifecycle, and observability boundaries.
The module map separates stable ownership boundaries from temporary implementation phases.

Start with ownership, not folders

The planned workspace uses crates for stable bounded contexts and modules inside each crate for implementation detail. That distinction matters. A folder layout can be reshuffled cheaply; an ownership boundary is harder to repair after behavior starts depending on the wrong direction.

The first rule is that lower-level crates do not import the application composition root. eva-core, eva-eventbus, eva-scheduler, eva-agent, eva-lua-host, eva-adapter, eva-storage, and service crates should remain independently testable. eva-runtime wires them together, but it should not leak back into them.

The core dependency direction

The dependency direction should keep contracts at the center and concrete transports at the edge. Core types, Topic rules, structured errors, permission shapes, and observability fields can be shared inward. Provider protocols, shell execution, MCP transport, HTTP, hardware I/O, and release mutation must stay behind adapter or service boundaries.

Eva-CLI module dependency rules showing core contracts at the center, runtime composition above, and adapters, services, Lua host, storage, policy, discovery, lifecycle, and observability depending in controlled directions.
Dependency direction is the enforcement mechanism behind the module plan.
Boundary Owns Must not own
eva-core Events, Topics, IDs, schema-shaped contracts, common error shape. Runtime orchestration, filesystem access, provider protocols, policy decisions.
eva-eventbus and eva-scheduler Publish/subscribe, delivery, routing rules, queues, dead letters. Business decisions, Lua execution, external capability calls.
eva-agent and eva-lua-host Agent lifecycle, private inboxes, sandboxed Lua state, controlled host APIs. Raw shell, raw network, secrets, device handles, release pointer mutation.
eva-adapter and service crates Capabilities, provider routing, side-effect boundaries, storage, memory, discovery, lifecycle. Unvalidated Lua authority or hidden global state shared across modules.

Runtime handoff should be explicit

A good module boundary becomes visible in runtime handoff. User input enters through an ingress surface and becomes a typed Event. EventBus persists and publishes it. Scheduler decides delivery. AgentRuntime isolates each Agent inbox. Lua handles business logic through a narrow host context. AdapterRouter and service crates execute side effects only after schema and policy checks.

Eva-CLI runtime module flow showing ingress to EventBus, Scheduler, AgentRuntime, Lua Host, Tool Layer, AdapterRouter, external providers, service modules, storage, lifecycle, and observability.
The runtime flow keeps side effects outside Lua and makes each handoff observable.

Cross-cutting rules

Some rules are not owned by one crate, but every crate must preserve them. Cross-module errors need stable fields such as kind, message, retryable, provider_code, and correlation identifiers. Permissions only narrow as requests move from system policy to manifest permissions, user or session policy, request constraints, and effective permissions. State ownership must remain explicit: Agent local state belongs to Agent and Lua generations, durable business state belongs to storage and memory, event recovery state belongs to EventBus, Adapter runtime state belongs to Adapter, and generation state belongs to lifecycle.

foundation contracts
  -> event and routing kernel
  -> isolated Agent and Lua execution boundary
  -> controlled capability and adapter boundary
  -> discovery and runtime services
  -> application, supervisor, and operational surfaces

Why this matters for implementation

Eva-CLI will eventually need Skills, MCP, external Agents, memory, hardware, backup, release snapshots, and process generation switching. Each of those features wants direct access to something powerful. The module partition is what keeps those powers reviewable: discovery can find candidates, policy can authorize them, adapters can execute them, observability can record them, and runtime can compose them without letting Lua or Scheduler become hidden system APIs.

The complete technical plan is available in Module Partitioning Plan.