Blog
Reflections on Eva-CLI Architecture and Harness Design
How Eva-CLI can turn its Rust-governed runtime architecture into executable evidence through a narrow, deterministic harness layer.
Eva-CLI has reached the V1.5 source-release checkpoint, so the most important engineering question is no longer how many modules can be named. The harder question is how architecture decisions keep producing executable evidence as the project moves from diagnostics toward real apply paths. The current implementation already proves that Rust owns authority, Lua-facing behavior stays behind controlled boundaries, Topic events connect work, AdapterRegistry controls external capabilities, and memory, knowledge, release snapshots, and recovery stay inside runtime-owned services. A harness architecture should be the bridge between those claims and future durable runtime loops.
This article treats harness as a proposed validation and execution fixture layer. It does not claim that Eva-CLI already ships this module. The point is to define how the project can keep testing its architecture before real providers, destructive apply paths, and durable process supervision make the surface too large.
What the current architecture is really saying
The architecture is not just a Rust plus Lua split. It is an authority model. Lua Agents can express business intent and workflow logic, but they do not directly read secrets, run shell commands, scan the filesystem, open arbitrary network connections, or mutate release state. Rust keeps those decisions behind schemas, policies, capability manifests, audit identity, and recovery boundaries.
That matters because the future implementation will include many tempting escape routes: local CLIs, MCP servers, workflow skills, browser automation, hardware adapters, memory writes, and process generation switches. Without a harness, each integration can appear to work while quietly weakening the same boundary the architecture is trying to protect.
Harness as an executable architecture reader
A good harness reads the architecture as contracts, not prose. It should feed typed events into Ingress, run a Scheduler and Lua Agent inside an isolated runtime sandbox, replace external capabilities with deterministic doubles, collect trace and audit output, then assert the invariant that should hold after each scenario.
| Architecture claim | Harness responsibility | Evidence to keep |
|---|---|---|
| Lua cannot own host authority. | Try forbidden filesystem, secret, network, and process actions through Lua-facing APIs. | Policy rejection before side effects, with origin and audit reason. |
| Topic routing is explicit. | Publish scenario events and verify the selected Agent, queue, priority, and dead-letter behavior. | Event log, scheduler trace, delivery decision, structured error. |
| Adapters are controlled capabilities. | Register mock adapters with schemas and policy limits, then test allowed and rejected calls. | Validated input, selected provider, output schema, timeout and cancellation record. |
| Memory has provenance. | Seed memory, request writes, and verify promotion, conflict, TTL, sensitivity, and source fields. | Memory delta, rejected write reason, context pack contents. |
| Upgrade and release evidence are runtime-owned. | Drive a candidate generation swap or release snapshot request without real deployment authority. | Snapshot manifest, health check result, rollback eligibility, audit identity. |
The first useful harness is narrow
The first harness should not try to simulate the whole future platform. It should prove the minimum runtime loop from the roadmap: user input becomes a typed event, the Scheduler routes it to one Agent queue, Lua handles it in an isolated state, Lua requests one controlled Rust tool, Rust validates schema and policy before execution, and the runtime emits trace, audit, and structured failure data.
That narrow loop gives the project a place to test the hardest architectural invariants early: no direct Lua host access, deterministic routing, policy rejection before side effects, observable errors, and replayable evidence. Once those are true, broader capability families can be added without making every later test invent its own runtime world.
Scenario packs instead of one-off tests
The harness should use scenario packs. A scenario pack contains input events, config fragments, manifests, policy files, memory seeds, adapter double definitions, expected trace checkpoints, and assertions. That shape keeps examples, integration tests, and architecture review close to each other. A scenario can explain a design decision while also proving it.
scenario
-> fixture input
-> runtime sandbox
-> EventBus and Scheduler
-> Lua Agent
-> controlled Tool or Adapter double
-> trace and audit capture
-> assertions
-> replay artifact
The scenario format also prevents an early mistake: treating tests as separate from product contracts. If the harness has to describe allowed capabilities, permissions, memory seeds, and expected evidence, the implementation is forced to make those boundaries explicit.
Doubles must obey the same contracts as real capabilities
Adapter doubles are not casual mocks. They should carry the same manifest shape, capability names, schemas, policy limits, timeout behavior, error classes, and audit identity as real Adapters. The only difference is transport. A double returns deterministic fixture output instead of touching a real CLI, network service, MCP server, model, browser, or device.
This lets Eva-CLI test capability routing without granting accidental host authority. It also lets tests cover negative cases: schema mismatch, missing permission, policy conflict, timeout, cancellation, retryable provider failure, non-retryable provider failure, and unsafe output.
Observation is part of the contract
A harness that only checks returned values will miss the architecture. Eva-CLI needs evidence that the right boundary made the right decision. The harness should capture event log records, scheduler decisions, tool invocation records, policy evaluation results, memory deltas, state snapshots, structured errors, and release evidence. Assertions should be able to target all of these, not just the final answer.
Replay is the other half of observation. A failed scenario should be replayable with the same fixtures and deterministic doubles. If a failure cannot be replayed, the harness has not yet made the runtime observable enough.
What harness should not become
The harness should not become a second runtime with its own rules. It should not bypass policy because tests are inconvenient. It should not use real secrets, real user directories, or uncontrolled network access by default. It should not make assertions by scraping loose log strings when structured events are available. Most importantly, it should not widen the production design before the minimum loop is proven.
Conclusion
The current Eva-CLI architecture is strongest when read as an authority boundary: Rust governs execution, Lua expresses workflow, Topic events keep work observable, AdapterRegistry controls external action, and memory plus release services preserve evidence. The harness architecture should make that boundary executable. It should drive the runtime with scenarios, replace dangerous edges with contract-faithful doubles, capture trace and audit evidence, and turn failures into smaller contracts.
That is the practical path from architecture documents to implementation. Do not first build every planned capability. First build the harness that can prove one small loop is honest.