Architecture
The shape of the runtime: coordinator, sessions, turns, effects, and the boundaries that hold them together.
A thin central router.
The coordinator owns four inbound channels (control_rx, command_rx, message_rx, submit_rx) and a single select! over them dispatches to the right session worker. The split matters: command_rx must keep working during streaming so a turn can be cancelled mid-flight, while submit_rx is gated to coordinator-idle so a new turn cannot start while another is streaming.
The coordinator never runs turns itself. That single constraint enforces the invariant that turns are never reentrant: new turns can only originate from the routing loop, never from inside streaming code.
SessionsSelf-contained execution contexts.
Each session has its own lifecycle state machine (idle, active, cancelling, shutting-down), its own scripting environment, its own configuration, its own conversation history, and its own agent. The scripting environment is not safe to move between executors, so each session is pinned to its own worker.
The session manager owns the per-session worker handles: creation, supervision, teardown. But engine shutdown is not a drain through the manager. It is a shared cancellation token that the coordinator and every session worker listen for. Shutdown is a signal, not a method call.
TurnsAn explicit phase machine.
When a turn runs, it walks named phases. Phases are explicit so progress is observable, failures happen at known boundaries, and recovery is deterministic.
- accept input
- prepare
- preflight
- stream from model
- handle completion
- execute script blocks
- recover from overflow
- persist
- finalize
Overflow triggers compact-and-retry. Cancellation interrupts at the next phase boundary, not in the middle of an unknown state.
ConfigurationThe effects bridge.
Configuration is code. The system's behavior is shaped by scripts the user writes (hooks, prompt builders, tool definitions, workflow logic) running inside the session's scripting environment with access to a host bridge for effects.
The bridge separates intent from execution. Scripts declare effects ("read this file", "call this tool"); the host carries them out. It has a reject mode: scripts can still register intents and define handlers under it, but no real effects fire. Reject mode is the machinery that makes configuration phases safely re-runnable.
// boot is staged
1. bootstrap
2. prompt JS
3. stdlib
4. repo root global
5. config files
6. extract typed config
7. prompt pre-activation
8. install effects ← effects-live boundary
9. startup hooks
10. prompt post-activation Phases 1 through 7 run with the bridge in reject mode. A broken configuration cannot fire half its side effects into the world, because no real effects fire before phase 8. The atomicity guarantee is on effects, not on runtime continuity.
TrustReviewer and executor.
Two roles, two boundaries. The trusted host is the reviewer and Git owner. It pulls, commits, merges, pushes, and reads executor reports as evidence, not authority. The untrusted executor edits files and runs checks inside a sandbox; it never receives credentials, never pushes, never modifies remotes or hooks.
Changes flow trust-ward through review, not the other way. The reviewer imports selectively, runs verification, then commits. An agent can do an enormous amount of useful work without ever holding the keys to the kingdom, which is exactly the point.
Shutdown is a cancellation-token signal, not a method drain.