500 lines
33 KiB
Markdown
500 lines
33 KiB
Markdown
# Runa — Project Specification and Architecture
|
|
|
|
**Status:** Architecture specification, revision 4 (Runa naming)
|
|
**Primary host language:** Rust
|
|
**Initial embedded language:** Rune
|
|
**Inspirations:** Smalltalk/Squeak/Pharo, Morphic, Erlang/OTP
|
|
**Primary interfaces:** Self-contained graphical world and VS Code extension
|
|
connected to the same live image through an authenticated network API
|
|
|
|
## 1. Vision
|
|
|
|
Build a self-contained, persistent, live programming world. Its fundamental computational entities are actors, not shared mutable objects. The environment itself is programmable and inspectable, with live actor spawning, message sending, state inspection, behavior editing, debugging, and hot code upgrades. A VS Code extension provides an equally capable external interface to the _same_ running image via a programmatic API.
|
|
|
|
Rust supplies a minimal, reliable substrate; increasingly much of the actor framework, graphical world, and development tools should be implemented in Rune. The end state is a Smalltalk-like image with Erlang-inspired actor isolation and modern tooling.
|
|
|
|
### Core goals
|
|
|
|
- Inspect, spawn, stop, restart, and supervise actors from both graphical world and VS Code.
|
|
- Inspect state, mailboxes, behavior versions, failures, and execution status.
|
|
- Send messages and evaluate development operations interactively.
|
|
- Edit, compile, publish, install, and roll back behaviors without restarting the image.
|
|
- Support interruptible execution, pause/resume, and eventually source-level stepping.
|
|
- Preserve stable actor identity and optionally mailbox contents across actor incarnation failures.
|
|
- Store canonical Rune source and immutable implementations by content identity; cache compilation.
|
|
- Build self-inspecting, self-modifiable graphical tools, gradually moving implementation from Rust to Rune.
|
|
- Persist and restore meaningful parts of the image without assuming arbitrary stack serialization.
|
|
|
|
## 2. Architectural Principles
|
|
|
|
1. **One authoritative live image.** In-world tools and VS Code are clients of the same semantic development services.
|
|
2. **Actor isolation.** No direct mutable cross-actor state sharing. All normal interaction occurs through messages.
|
|
3. **Separate identity, mailbox, state, handler, and incarnation.** A failed handler execution need not destroy an actor's identity or mailbox.
|
|
4. **Stateless handlers.** Actor-specific mutable state is explicit input/output, not hidden global state.
|
|
5. **Immutable code versions.** A behavior name points to an exact implementation; active executions retain their own version.
|
|
6. **Rust mechanisms, Rune policies.** Native kernel for scheduling, execution control, memory/resource ownership, platform I/O; Rune for behaviors, UI, supervision policy, and tools where practical.
|
|
7. **Safe-point upgrades and inspection.** Never unsafely mutate a currently executing handler.
|
|
8. **Honest guarantees.** Distinguish cooperative yielding from true preemption, in-memory retention from disk durability, and at-least-once delivery from exactly-once effects.
|
|
9. **Replaceable language integration.** Keep a narrow runtime adapter, but do not over-generalize before Rune feasibility is tested.
|
|
|
|
## 3. Layered Architecture
|
|
|
|
```text
|
|
+-----------------------------------------------------------+
|
|
| Live graphical world (Morphic-inspired) |
|
|
| Windows, widgets, actor browser, inspector, debugger |
|
|
+-------------------------------+---------------------------+
|
|
| Rune development services | VS Code extension |
|
|
| Behavior registry, workspace | Virtual docs, trees, DAP |
|
|
+-------------------------------+---------------------------+
|
|
| Unified image API / development protocol |
|
|
| Actors, mailboxes, state, code, debugging, events |
|
|
+-----------------------------------------------------------+
|
|
| Rune actor framework |
|
|
| Stateless handlers, supervision policies, UI behaviors |
|
|
+-----------------------------------------------------------+
|
|
| Rune runtime adapter / compilation and execution |
|
|
+-----------------------------------------------------------+
|
|
| Rust actor kernel |
|
|
| Identity, mailboxes, scheduler, transactions, monitoring |
|
|
+-----------------------------------------------------------+
|
|
| Rust platform substrate |
|
|
| Graphics, input, timers, filesystem, networking, storage |
|
|
+-----------------------------------------------------------+
|
|
```
|
|
|
|
The graphical world should use internal service calls to the image API. The VS Code extension connects to the same live image through a versioned network transport. CLI tools, tests, and local automation can use in-process calls or a child-process protocol over stdio. The network boundary must authenticate and authorize clients; it does not create a separate actor runtime or image.
|
|
|
|
## 4. Fundamental Actor Model
|
|
|
|
An actor comprises distinct components:
|
|
|
|
```text
|
|
Actor {
|
|
id: ActorId, // stable logical identity
|
|
mailbox: MailboxId, // independent queue; may survive restart
|
|
state: StateRecord, // committed private state
|
|
behavior: ImplementationId, // immutable handler implementation
|
|
incarnation: Generation, // changes on restart
|
|
status: ActorStatus,
|
|
supervisor: Option<ActorId>,
|
|
}
|
|
```
|
|
|
|
### 4.1 Identity
|
|
|
|
Actor IDs are opaque, never raw pointers. Use generation or other safeguards against stale references. A logical actor may be restarted with the same ID and mailbox but a new incarnation. Distinguish runtime-instance identity from actor identity if remote or persisted references are introduced.
|
|
|
|
### 4.2 Mailbox
|
|
|
|
The mailbox is managed independently of handler execution. Messages have at least `queued`, `reserved`, `acknowledged`, and `dead-lettered` lifecycle states where durable processing is enabled. Define ordering explicitly; FIFO within a queue does not imply deterministic ordering between concurrent senders.
|
|
|
|
Start with bounded queues and observable backpressure. For durable mailboxes, initially target **at-least-once processing**, retry limits, and dead-letter handling. Retention across actor restarts does not imply survival across host process crashes; disk durability requires explicit storage and recovery.
|
|
|
|
### 4.3 State
|
|
|
|
State is owned by the actor runtime, logically private, and supplied to each scheduled handler invocation. The handler works with a controlled draft or value and returns new state; it cannot mutate committed state directly. State has a schema/version where useful and can be inspected via snapshots at safe points.
|
|
|
|
### 4.4 Stateless handler
|
|
|
|
The handler is a stateless Rune function associated with an immutable implementation ID. Conceptually:
|
|
|
|
```text
|
|
handle(state, message, context) -> Transition(new_state, effects)
|
|
```
|
|
|
|
`context` provides restricted runtime capabilities, such as actor identity and correlation IDs. Actor-specific state must not be stored in global variables or implicit mutable closures. The handler may await approved asynchronous operations. This API is conceptual, not verified Rune syntax.
|
|
|
|
### 4.5 Effects
|
|
|
|
Prefer explicit effect descriptions for sends, timers, external requests, and lifecycle operations rather than arbitrary irreversible side effects during a state transition.
|
|
|
|
```text
|
|
Transition {
|
|
new_state,
|
|
effects: [Send(...), ScheduleTimer(...), ...],
|
|
}
|
|
```
|
|
|
|
On durable paths, commit the state transition, input-message acknowledgment, and transactional outbox records atomically. Delivery of outbox effects occurs afterward and may be retried. Exactly-once external side effects are **not** guaranteed; use idempotency keys and deduplication where needed.
|
|
|
|
## 5. Scheduling, Awaiting, and Interruption
|
|
|
|
Each actor processes at most one active handler invocation at a time, including suspended invocations, unless a future explicitly designed concurrency policy says otherwise. Other messages remain queued.
|
|
|
|
A scheduled invocation receives its committed state, a reserved message, the selected implementation, and execution context. It runs until it:
|
|
|
|
1. Completes, producing a transition to commit.
|
|
2. Awaits an asynchronous operation, suspending without blocking a native worker thread.
|
|
3. Is paused/interrupted at a supported safe point.
|
|
4. Fails or is cancelled.
|
|
5. Reaches a configured execution budget.
|
|
|
|
**Await is not commit.** State and effects from an incomplete invocation remain uncommitted. On crash, the current invocation is discarded or recovered according to documented policy, and its reserved message can be retried. Long awaits can consume resources and complicate recovery; establish limits and cancellation rules.
|
|
|
|
### 5.1 Interruptibility requirement
|
|
|
|
Interruptible Rune execution is a foundational requirement, not a future nice-to-have. The runtime should eventually support pause, resume, cancel, execution budgets, runaway-code detection, breakpoint locations, and source-level stepping.
|
|
|
|
Phase 0 must verify actual Rune APIs and limitations: cooperative yield, VM instruction hooks/budgets, native callback blocking, async suspension, frame inspection, and safe interruption of CPU-bound loops. If Rune lacks the necessary mechanisms, evaluate bytecode instrumentation, interpreter modifications, or a controlled fork. **Do not claim preemptive scheduling until it is actually implemented and tested.** Native Rust callbacks must also define their cancellation behavior.
|
|
|
|
### 5.2 Failure and supervision
|
|
|
|
Separate handler exceptions, invocation cancellation, actor incarnation failure, supervisor restarts, host process failure, and machine failure. Supervisors can restart an actor with retained mailbox, last committed state, and the same or a compatible upgraded handler. Supervision strategies (one-for-one, one-for-all, rest-for-one) can initially live in Rune, atop native monitoring and lifecycle events. Add restart-intensity limits and poison-message handling.
|
|
|
|
## 6. Content-Addressed Rune Code
|
|
|
|
Keep four distinct things:
|
|
|
|
1. **Original source** for editing, diagnostics, and exact text preservation.
|
|
2. **Canonical source** normalized deterministically and semantics-preservingly.
|
|
3. **Source identity** derived from canonical bytes with a versioned hash scheme.
|
|
4. **Compiled artifact** cached using all compilation inputs.
|
|
|
|
Use a domain-separated hash such as BLAKE3 and a canonicalization version. Never strip arbitrary whitespace/comments without parser-aware analysis; preserve original source and source maps for debugging.
|
|
|
|
Example identifiers:
|
|
|
|
```text
|
|
rune-source:v1:blake3:<digest>
|
|
compiled:<digest-of-source-plus-toolchain-configuration>
|
|
```
|
|
|
|
A compiled artifact cache key must include source identity, Rune compiler version, compiler settings, enabled native modules, runtime ABI, relevant features, and target constraints. Do not assume artifacts are portable between Rune versions or host configurations.
|
|
|
|
A mutable behavior registry maps names to immutable implementations:
|
|
|
|
```text
|
|
behaviors/Counter -> implementation:abc123
|
|
history: [implementation:def456, implementation:abc123]
|
|
```
|
|
|
|
Active frames retain references to their exact version. Garbage collection must respect references from active invocations, actor state, persisted snapshots, and retained history. Revisions prevent conflicting editor updates.
|
|
|
|
### 6.1 Hot upgrade procedure
|
|
|
|
1. Accept source and expected behavior revision.
|
|
2. Canonicalize, hash, and compile (or reuse cached artifact).
|
|
3. Report diagnostics without changing the running behavior on failure.
|
|
4. Publish an immutable implementation.
|
|
5. Validate state compatibility or execute explicit migration.
|
|
6. Install at a safe boundary (initially between message handlers).
|
|
7. Emit change events and retain rollback history.
|
|
|
|
Do not rewrite suspended execution frames in place.
|
|
|
|
## 7. Graphical World
|
|
|
|
Build a self-contained Morphic-inspired desktop where windows, widgets, and development tools are themselves inspectable and eventually written primarily in Rune.
|
|
|
|
**Required in-world operations:** browse actors and behaviors; spawn, stop, restart, pause, and resume actors; inspect state, mailboxes, failures, supervisor relationships, and versions; send messages; edit and compile behavior source; install/rollback versions; inspect execution; view events and diagnostics.
|
|
|
|
Not every graphical node must be an actor. Use actors for independently scheduled components and ordinary Rune data for geometry, style, and lightweight scene nodes. UI actors update a retained scene representation; a scene manager produces immutable render snapshots consumed by native graphics code. Avoid synchronous arbitrary actor callbacks on the render thread. Native code initially owns windowing, drawing, and input capture; Rune progressively owns composition, layout, event routing, widgets, and tools.
|
|
|
|
The graphical inspector should support selecting a component, locating its owning actor, inspecting its state and behavior, editing its implementation, and observing live changes. The development environment must be able to inspect itself.
|
|
|
|
## 8. Unified Programmatic Image API
|
|
|
|
The running image exposes a versioned semantic API, used by graphical tools, CLI tools, tests, automation, coding agents, and the VS Code extension. The extension uses a network transport to reach the same running image; local stdio remains available for child-process integrations. Neither transport changes actor placement or message-passing semantics.
|
|
|
|
Suggested operation families (provisional names):
|
|
|
|
```text
|
|
image.info image.snapshot image.restore
|
|
image.subscribe
|
|
|
|
actor.list actor.spawn actor.inspect
|
|
actor.send actor.call actor.pause
|
|
actor.resume actor.stop actor.restart
|
|
actor.subscribe
|
|
|
|
mailbox.inspect mailbox.peek mailbox.statistics
|
|
mailbox.retry mailbox.deadLetters
|
|
|
|
state.inspect state.snapshot state.history
|
|
|
|
behavior.list behavior.get behavior.compile
|
|
behavior.publish behavior.install behavior.rollback
|
|
behavior.history
|
|
|
|
code.getSource code.getArtifact code.getMetadata
|
|
code.listReferences
|
|
|
|
debug.attach debug.detach debug.pause
|
|
debug.resume debug.step debug.breakpoints
|
|
debug.stack debug.inspectFrame
|
|
```
|
|
|
|
These are desired capabilities, not a requirement to implement every endpoint immediately. Define explicit request/response schemas, error codes, authorization, optimistic revision checks, and event subscription semantics. Mutations should return structured outcomes and emit events.
|
|
|
|
### 8.1 Security
|
|
|
|
Normal actors should not automatically receive development privileges. Arbitrary evaluation, state mutation, code replacement, and process control require explicit capabilities. The current stdio bridge is limited to a trusted parent process. Any future network bridge must bind locally by default and use a defensible authentication mechanism; never expose unauthenticated remote code execution endpoints.
|
|
|
|
## 9. VS Code Extension
|
|
|
|
VS Code is an external client of the same live image, not a separate runtime. It connects through an authenticated versioned network transport, initially planned as JSON-RPC over WebSocket. The extension does not host actors or create a separate image. The local stdio protocol remains useful for CLI tools, tests, and other child-process clients. Network security, connection lifecycle, and event subscription semantics must be designed before exposing the listener.
|
|
|
|
Required extension UX:
|
|
|
|
- Connection management and runtime status.
|
|
- Actor tree with spawn, stop, restart, pause, and resume actions.
|
|
- Actor state and mailbox inspector, including message sending.
|
|
- Behavior tree and source navigation.
|
|
- Editable virtual documents for mutable behavior references.
|
|
- Read-only virtual documents for exact content-addressed implementations.
|
|
- Compilation diagnostics, update conflicts, and runtime event stream.
|
|
- Later: Debug Adapter Protocol integration for breakpoints, frames, and stepping.
|
|
|
|
Suggested virtual URIs:
|
|
|
|
```text
|
|
liveworld:/behaviors/Counter/current.rn
|
|
liveworld:/implementations/<hash>/source.rn
|
|
```
|
|
|
|
Saving the first compiles/publishes a new implementation and conditionally updates the behavior reference. The second is immutable and read-only. Avoid silently overwriting edits from another client.
|
|
|
|
## 10. Persistence
|
|
|
|
Implement persistence incrementally:
|
|
|
|
1. **Source:** canonical/original source, immutable implementations, registry revisions.
|
|
2. **Actor state:** selected actor identities, committed state, handler references, supervision metadata.
|
|
3. **Environment:** windows, layouts, workspaces, and development session state.
|
|
4. **Advanced:** coordinated actor/message snapshots and, only if technically feasible, suspended execution state.
|
|
|
|
Start with SQLite or another simple durable store plus Git-friendly source export. Define snapshot consistency explicitly. Never assume arbitrary Rune stacks, closures, and native resources can be serialized and restored. Preserve mailbox and state transaction invariants across recovery.
|
|
|
|
## 11. Workspace Boundaries and Dependency Direction
|
|
|
|
The Rust workspace uses **acyclic, inward-pointing dependencies**. The executable (`runa`) is the composition root. Higher-level services depend on lower-level contracts; low-level crates never import graphical, transport, or application code.
|
|
|
|
### 11.1 Dependency diagram
|
|
|
|
Arrows mean **"depends on"**, not runtime data flow:
|
|
|
|
```text
|
|
runa
|
|
/ | \
|
|
v v v
|
|
runa-world runa-server
|
|
| / \
|
|
v v v
|
|
runa-image-api runa-protocol
|
|
| |
|
|
v |
|
|
runa-runtime |
|
|
/ \ |
|
|
v v |
|
|
runa-actor runa-rune |
|
|
\ / |
|
|
v v v
|
|
runa-core <-----------+
|
|
|
|
runa-world also depends on runa-graphics (platform drawing/input
|
|
contracts); runa-graphics depends only on runa-core when needed.
|
|
runa-server depends on runa-image-api and runa-protocol.
|
|
runa wires together world, server, runtime, storage and platform.
|
|
```
|
|
|
|
The diagram is conceptual; Cargo dependencies should be kept minimal. A dependency is permitted only when the importing crate actually uses that crate's public contracts. The VS Code extension is a separate TypeScript project and depends on the **wire protocol**, not Rust crates.
|
|
|
|
### 11.2 Crate ownership
|
|
|
|
| Crate | Owns | May depend on |
|
|
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
|
| `runa-core` | Small, stable value types shared across independent layers: actor IDs, source and implementation IDs, canonical message value types, common error identifiers | Minimal external libraries only |
|
|
| `runa-code` | Original source retention, versioned source/implementation hashing, compile-input fingerprints, in-memory compiled artifact cache | `runa-core`, `runa-rune`, BLAKE3 |
|
|
| `runa-actor` | Mailbox and state-transition semantics, message reservation, acknowledgment, effects, actor lifecycle definitions | `runa-core` |
|
|
| `runa-rune` | Rune compilation, VM execution, suspension, interruption hooks, language-specific diagnostics | `runa-core`, Rune libraries |
|
|
| `runa-runtime` | Scheduling, actor execution coordination, state commits, crash recovery, binding actor semantics to Rune execution | `runa-core`, `runa-actor`, `runa-code`, `runa-rune` |
|
|
| `runa-image-api` | Trusted in-process application services for spawning, inspecting, sending, editing, and upgrading | `runa-core`, `runa-actor`, `runa-code`, `runa-runtime` |
|
|
| `runa-protocol` | Versioned transport-neutral request/response/event DTOs and validation | `serde` |
|
|
| `runa-server` | Protocol dispatch and local JSON-lines stdio transport; authenticated network transport for VS Code clients | `runa-protocol`, `runa-image-api` |
|
|
| `runa-client` | Local child-process client for the JSON-lines stdio protocol | `runa-protocol` |
|
|
| `runa-graphics` | Native window, rendering and input mechanisms; no actor policy | `runa-core` if necessary |
|
|
| `runa-world` | Morphic-style graphical composition and in-world development UI | `runa-image-api`, `runa-graphics` |
|
|
| `runa` | Startup, configuration, resource wiring, shutdown | Top-level crates it instantiates |
|
|
|
|
The current prototype has added `runa-code` for exact-source identity and
|
|
in-memory compilation caching, and `runa-image-api` as the trusted,
|
|
in-process application-service boundary used by the local CLI. It deliberately
|
|
does not canonicalize source yet; canonicalization needs a semantics-preserving,
|
|
source-map-aware policy. The image API is not yet a network API and performs no
|
|
authentication or authorization; callers must be trusted by the host.
|
|
|
|
The initial `runa-image-api` provides process-local behavior source retrieval,
|
|
publication, history and rollback, actor lifecycle and messaging, snapshots,
|
|
ticks, and event retrieval. The CLI uses these application services rather
|
|
than reaching into the code store and runtime directly. `runa-protocol` now
|
|
defines versioned, serializable request, response, and event DTOs without
|
|
depending on a transport or the runtime implementation. `runa-server` now
|
|
dispatches those commands through the image API and maps service results into
|
|
protocol replies and typed errors. It remains an in-process dispatcher; there
|
|
is no network listener, session model, authentication, or authorization. The
|
|
dispatcher is exposed through local child-process JSON-lines stdio with a 1
|
|
MiB request-line limit. In-process consumers call `runa-image-api`, and
|
|
external local tools can use `runa-client` to launch the stdio server. Actors
|
|
do not depend on network transport to coexist in one live image; the network
|
|
boundary exists for external clients such as VS Code. Authenticated network
|
|
transport is a planned integration requirement, not a runtime prerequisite.
|
|
|
|
**Important:** `runa-core` must not contain schedulers, mailbox implementations, persistence engines, Rune VM types, service traits used by only one crate, generic helper collections, or GUI abstractions. Prefer a type defined in its owning crate until two independent consumers demonstrably need a stable shared representation.
|
|
|
|
### 11.3 Runtime interfaces and avoiding cycles
|
|
|
|
- `runa-actor` defines actor rules and data contracts; it does **not** spawn threads or call Rune.
|
|
- `runa-rune` executes Rune code but does **not** own actor scheduling, mailboxes, or image APIs.
|
|
- `runa-runtime` coordinates both. Initially it can depend directly on `runa-rune`; introduce an execution-adapter trait only when a second implementation or test double justifies it. Place the trait at the lowest layer that actually consumes it, rather than automatically in `runa-core`.
|
|
- `runa-image-api` is the single application-service entry point for in-world tools and external clients. It centralizes lifecycle invariants and revision checks; host-level permissions and authentication remain required at any external boundary.
|
|
- `runa-protocol` holds wire DTOs, **not** runtime service implementations. Translate DTOs at the server boundary; never serialize internal actor locks or VM references.
|
|
- `runa-world` uses the same `runa-image-api` operations as the external bridge. It does not reach into runtime internals for convenience.
|
|
- Native platform handles stay behind `runa-graphics` (or a later platform crate), not in `runa-core`.
|
|
|
|
For content-addressed code, `runa-core` owns stable source/implementation ID value types, and `runa-code` owns source hashing, compile fingerprints, storage, and compilation caching. The current prototype hashes exact source bytes without canonicalization and keeps the cache in memory.
|
|
|
|
For persistence, begin with a concrete adapter wired by `runa`. Extract `runa-storage` only when its durable mailbox, state, outbox and artifact contracts are clear. Keep database-specific details out of actor semantics and out of `runa-core`.
|
|
|
|
### 11.4 Repository layout
|
|
|
|
```text
|
|
runa/
|
|
├── Cargo.toml
|
|
├── README.md
|
|
├── docs/
|
|
│ ├── architecture.md
|
|
│ ├── actor-model.md
|
|
│ ├── runtime.md
|
|
│ ├── protocol.md
|
|
│ └── decisions/
|
|
├── crates/
|
|
│ ├── runa-core/
|
|
│ ├── runa-actor/
|
|
│ ├── runa-code/
|
|
│ ├── runa-rune/
|
|
│ ├── runa-runtime/
|
|
│ ├── runa-image-api/
|
|
│ ├── runa-protocol/
|
|
│ ├── runa-server/
|
|
│ ├── runa-client/
|
|
│ ├── runa-graphics/
|
|
│ ├── runa-world/
|
|
│ └── runa/
|
|
├── runa-std/
|
|
│ ├── core/
|
|
│ ├── actors/
|
|
│ ├── ui/
|
|
│ └── tools/
|
|
├── scripts/
|
|
├── vscode/
|
|
├── examples/
|
|
└── tests/
|
|
```
|
|
|
|
This is a **target layout**, not a request to generate empty crates. For Phase 0, begin with `runa-rune` and a small executable test harness. Introduce `runa-core`, `runa-actor`, and `runa-runtime` only as the corresponding functionality is implemented. Enforce the dependency direction through Cargo manifests and periodic dependency-graph checks; reject circular dependencies and upward imports in code review.
|
|
|
|
## 12. Implementation Roadmap
|
|
|
|
### Phase 0 — Rune feasibility (first priority)
|
|
|
|
- Embed Rune in a Rust workspace and compile/run a minimal script.
|
|
- Register a native Rust function and call it from Rune.
|
|
- Demonstrate async suspension and resumption using verified APIs.
|
|
- Investigate interruption of CPU-bound code, execution budgets, frame inspection, and debugging hooks.
|
|
- Measure VM/context memory overhead and compiled-code sharing.
|
|
- Test cross-thread safety and runtime isolation assumptions.
|
|
- Document actual Rune limitations and potential mitigation strategies.
|
|
|
|
**Exit criterion:** Evidence-based choice of execution model and a running example. Do not start GUI implementation until this is assessed.
|
|
|
|
### Phase 1 — Minimal actor kernel
|
|
|
|
- Stable IDs, incarnation generations, bounded mailboxes, state records, stateless handlers.
|
|
- Spawn/send/receive/terminate, sequential scheduling, basic lifecycle and error events.
|
|
- Demonstrate two Rune actors exchanging structured messages without shared mutable state.
|
|
|
|
### Phase 2 — Transactional processing
|
|
|
|
- Reserve/ack/retry messages; commit state transitions.
|
|
- Explicit effects, error handling, and eventually an outbox for durable sends.
|
|
- Test crash/restart retaining mailbox and last committed state.
|
|
|
|
### Phase 3 — Content-addressed code
|
|
|
|
- Original/canonical source storage, hashing, cache keys, behavior registry, revision history.
|
|
- Compile or retrieve cached artifacts; retain exact implementation IDs.
|
|
|
|
### Phase 4 — Live code and debugging foundation
|
|
|
|
- Safe-point behavior upgrades, invalid-source rollback, state migration policy.
|
|
- Pause/resume/cancel and initial execution inspection, subject to Rune feasibility.
|
|
|
|
The current runtime prototype supports implementation installation only at an
|
|
idle handler boundary, cooperative pause/resume between scheduler ticks, and an
|
|
explicit host-provided migration closure for its temporary `i64` actor state.
|
|
Actor snapshots expose active VM instruction progress, instruction pointer,
|
|
and call-frame depth. Structured state schemas, version compatibility checks,
|
|
Rune-authored migration functions, source mapping, and local-variable
|
|
inspection remain future work.
|
|
|
|
### Phase 5 — Image API
|
|
|
|
- Headless server, versioned protocol, actor and mailbox operations, source editing, events.
|
|
- CLI client that can spawn, inspect, send messages, and replace behaviors.
|
|
|
|
The first Phase 5 increments are a trusted in-process application API used by
|
|
the CLI, a transport-neutral versioned protocol contract, and a dispatcher
|
|
exposed through bounded local JSON-lines stdio. The interactive CLI uses the
|
|
same protocol commands and dispatcher in-process. `runa-client` launches the
|
|
stdio server for external local tools. The next server increment for the VS
|
|
Code integration is an authenticated network transport over the same API and
|
|
live image; it is not needed for actors to share that image.
|
|
|
|
### Phase 6 — Graphical world
|
|
|
|
- Native window/rendering, input, scene manager, Rune-driven button and window.
|
|
- In-world actor browser, state inspector, behavior editor, and message sender.
|
|
|
|
### Phase 7 — VS Code extension
|
|
|
|
- Connection, actor explorer, state/mailbox inspection, spawn/send controls.
|
|
- Virtual behavior documents, compilation diagnostics, hot upgrades, runtime events.
|
|
|
|
### Phase 8 — Persistence and advanced debugger
|
|
|
|
- Durable mailboxes and state, snapshot/restore, supervised recovery.
|
|
- Source-level debugging and richer interruption/stepping as supported by runtime.
|
|
|
|
## 13. Critical Risks and Open Decisions
|
|
|
|
| Topic | Risk / decision |
|
|
| -------------------- | ------------------------------------------------------------------------------- |
|
|
| Rune interruption | Verify whether CPU-bound execution can be paused or budgeted safely. |
|
|
| Async invocation | Define how awaits preserve private state and what is retried after crash. |
|
|
| VM isolation | Determine per-actor VM vs shared compiled code and isolated execution contexts. |
|
|
| Scheduler fairness | Cooperative yield alone does not prevent a runaway CPU-bound handler. |
|
|
| Effects | Commit/retry semantics and idempotency for external side effects. |
|
|
| Mailbox durability | In-memory restart retention vs process-crash durable storage. |
|
|
| Source normalization | Canonicalization must preserve semantics and debugging locations. |
|
|
| Code upgrade | Active frames must retain exact old implementation versions. |
|
|
| UI performance | Avoid an actor per tiny graphical node and render-thread actor calls. |
|
|
| Persistence | Full execution-stack image restoration may require interpreter changes. |
|
|
| API security | Debugging and code installation are privileged operations. |
|
|
|
|
## 14. Initial Non-Goals
|
|
|
|
No full BEAM clone, distributed actors, millions-of-actors guarantee, full Morphic compatibility, custom Rune compiler, complete IDE, full stack serialization, production-grade hostile-code sandbox, or complete source-level debugger in the first prototype. Do not build a large abstraction framework before the Rune experiment validates it.
|
|
|
|
## 15. Instructions for a Local Coding LLM
|
|
|
|
Act as the principal systems architect and implementation partner. Work incrementally. Begin **only with Phase 0**. Verify exact Rune APIs and syntax against the pinned version; never invent working APIs. Distinguish confirmed capabilities from hypotheses. Produce a minimal Cargo workspace, runnable examples, tests where practical, build/run instructions, measurements, and a concise feasibility report. Record architectural decisions and unresolved risks. Do not silently change the mailbox/state/handler decomposition, collapse development tools into separate runtimes, or bypass actor isolation for inspection.
|
|
|
|
**First task:** Implement a minimal Rust + Rune experiment that executes a Rune function, invokes a registered native Rust function, demonstrates supported asynchronous suspension, and investigates interruption and compiled-code reuse. Stop after reporting the results and proposed Phase 1 architecture.
|
|
|
|
## 16. Long-Term Acceptance Scenario
|
|
|
|
A developer launches the graphical world, spawns a counter actor, sends it a message, inspects its mailbox and committed state, opens its exact content-addressed Rune handler, edits and publishes a new version, installs it at a safe point, and sees subsequent messages use the new behavior. The same operations are possible through VS Code using the image API. A failed actor incarnation can be restarted with the same logical identity and retained mailbox, and the world can eventually save and restore a meaningful development session.
|
|
|
|
**North star:** The world is the program; actors are its living components; development is continuous interaction with that world rather than a separate edit-build-run cycle.
|