Repository navigation
Releases: arcships/rutis
Release list
rutis v0.10.0
rutis 0.10.0
0.10.0 is a quality release. Following the second quality step, it adds tests across processes and platforms and fixes the defects those tests found. It adds three features: a format version in rutis.json, link states and listening addresses in rutis-host run, and runtime output passed on a whole line at a time. Everything else is fixes. A few behaviours now fail explicitly; see "Compatibility".
Packages
All of these are at 0.10.0:
| Registry | Packages |
|---|---|
| crates.io | rutis (the core), rutis-bridge, rutis-loader, rutis-host; the dylib toolchain rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher |
| npm | @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-bun, @arcships/rutis-host, and the five platform host packages |
| PyPI | rutis, rutis-host |
| Go | github.com/arcships/rutis/go/rutis (tag go/rutis/v0.10.0) |
| GitHub | rutis-host binaries for Linux / macOS (x64 / arm64) and Windows (x64), with SHA-256 files |
rutis-cli is still released on its own.
New
- A format version in
rutis.json(#207): top-level"format": 1. It can be left out, and a file without it reads as format 1, so existing files need no change. When a file's format is newer than the one rutis-host supports, rutis-host refuses it before reading any other field and says to upgrade rutis-host.rutis-host newwrites the field. Every releasedrutis.jsonsince 0.8.0 is kept as a sample, and tests check that each still reads as it did. dsh'scordis.patch.ymlis Cordis's configuration format and gets no version. rutis-host runprints link states and listening addresses (#321): at start, each listener prints the address it actually bound:rutis-host: listening on <name> <address>. When the link of a node row changes state, rutis-host prints one line:link connected,link down (<reason>); retrying in …,link refused: auth-rejected (<reason>), orlink stopped: incompatible (<reason>). You can now tell from the output whether a token was refused, a certificate was not trusted, or the far end is not up. Tokens never appear in the output.- Runtime output is passed on a whole line at a time (#332): each line that a Node, Bun, Python or Go runtime writes to stdout or stderr appears whole and unchanged on the same stream of rutis-host. It no longer runs into rutis-host's own lines, even when a plugin writes a line in several pieces. Runtimes now see pipes, not a terminal, on stdout and stderr, so libraries that choose colours by whether they write to a terminal print without colours. On the Rust side,
Stdio::Linesis new; the library default is stillInherit. - A protocol version mismatch says which end to upgrade (#293): in all five implementations (Rust, Node, Bun, Python, Go), handshake refusals and WebSocket subprotocol refusals name the end to upgrade and its package. The error category is still
incompatible.
Fixes
Values across processes
- A value may nest at most 64 levels deep (#279). Before, a value deeper than serde_json's recursion limit on the receiving side ended the whole session, so every other call on it failed. Now the side that sends the value checks it before sending, and a value nested too deep fails only that call; the session goes on.
- Floating-point numbers reach the Rust side bit for bit (#290). Before, they could change by one or two ULPs.
- On Node 24 and later,
JSON.parsereads some object keys that contain escapes as other keys (#302). The Node runtime now works around it, so plugins no longer receive silently changed values. - The Go runtime ends the session on a frame with invalid UTF-8 (#294), as the other runtimes do. Before, it replaced the invalid bytes with U+FFFD and went on.
- When Python sends an integer outside ±(2^53−1), that call fails explicitly (#356). Before, nothing checked it: integers over 2^64 silently became floats when relayed through Rust, and integers over 2^53 were not exact on the JS and Go sides either. The limit is the same as in JS and Go.
Sessions and links
- When a call chain crosses processes over links, a process no longer takes another process's calls for its own (#325). Session tags are now unique across processes; the wire format is unchanged.
- When a client certificate is invalid, the listener sends its TLS alert before it closes the connection (#300). The dialer now gets
AuthRejectedon Windows too, instead of a connection reset. - On macOS, the system sometimes killed a runtime process (SIGKILL) as it started (#287). This happened when another thread was initialising libnotify during a fork. rutis now finishes that initialisation before its first fork. The problem appeared on macOS 26 and 27.
Boundary rules of Cordis plugins (#281, #282)
- A synchronous
bailon the Cordis side for an event forwarded to rutis now fails explicitly and suggestsserial. Before, it silently got a Promise. - When a
waterfallpasses through the rutis side, rutis's listeners run as one asynchronous step, and the chain goes on to the listeners after it on the Cordis side. - A mount that lists an
internal/*event ineventsoremitsfails, with the error reported before the process starts.
Core and loader
- A failed plugin is retried only when its dependencies actually change (#327). Before, repeated notices about the same dependencies could load it again, and it could stay in Loading.
- The inject and listener lists under one key shrink back once they hold fewer entries (#291).
- Go runtimes: a restart whose caller stopped waiting still finishes, so two processes of the same name no longer run at once (#307). The manifest of a binary that was just replaced is read again when the first read failed, and ETXTBSY on Linux is retried (#306).
rutis-hostreports that it has started only after its runtimes have actually let their rows through (#314).- When the host is killed (
kill -9), its runtimes exit too (#353). Before, on Unix, a Node runtime kept running whenever a plugin left a timer, and a cleanup that never returned made the Node, Bun and Python runtimes hang. Now, once the session ends, all four runtimes unload their rows within a deadline and exit. The deadline isrutis-host's--shutdown-timeout, passed to the runtimes in the environment variableRUTIS_SHUTDOWN_TIMEOUT, 10 seconds by default. Past it, the remaining cleanups are given up and the exit code is 1.
Python
- On CPython 3.13.6,
listen("wss://…")refuses to start (#304). That patch release has an SSL regression (python/cpython#137583) that hangs every TLS connection. Use 3.13.7 or later.ws://is not affected.
Tests and quality
Most of the work in this release went into tests, which bring no direct change for users. This section only lists what they cover:
- End-to-end scenarios: real
rutis-hostprocesses with probe plugins in every language. They cover the plugin development loop, combinations of languages and runtime crashes, moving an implementation, nodes in two separate processes, and running right after installing. They run on Linux, macOS and Windows. - The conformance suites have Windows and loopback columns. Fault injection is wired into sessions and links. There are negative TLS tests, and property tests for values crossing languages and for reference release counts.
- The testing tools (
@arcships/rutis/testing,rutis.testing) and the real runtimes are checked against the same expectations file (#206). - Core guarantees are covered: event order, lifecycle and reclamation. Assertions no longer depend on the real clock, and randomised tests take a seed.
- The guarantee registry records rutis's core promises and contract behaviours, and the tests that verify them. 0.10 publishes it as a baseline; from 0.11 on, it is checked before every release.
Compatibility
- Protocol versions are unchanged: local sessions are still protocol 2, sessions with endpoint identities protocol 3, and
PLUGIN_APIis still 1. 0.9 and 0.10 hosts and runtimes work together. Only between two 0.9 processes is #325 still possible. rutis.json: files from 0.10'srutis-host newhave"format": 1. A 0.9 rutis-host does not know the field and reports it as an unknown field. To read such a file with 0.9, delete that line.- Behaviours that now fail explicitly:
rutis v0.9.1
rutis 0.9.1
0.9.1 fixes the launcher in the npm package @arcships/rutis-host: one Ctrl-C in a terminal made rutis-host exit at once without running cleanups (#267). The other packages have no changes and move to 0.9.1 only to stay on the train.
Fixes
- The npm launcher no longer forwards Ctrl-C:
npx rutis-host …and a project'snode_modules/.bin/rutis-hostare a Node launcher, which forwarded every signal it got torutis-host. A terminal already sends Ctrl-C to the whole process group, sorutis-hostgot it twice and took the second as "exit at once": plugin cleanups did not run, runtime processes were killed, and the exit code was 2. The launcher now leaves SIGINT and SIGHUP torutis-host(it gets them itself) and forwards only SIGTERM (which service managers anddocker stopsend to the main process alone). On Windows, forwarding Ctrl-C used to terminaterutis-hostoutright; the launcher now forwards nothing, andrutis-hosthandles the console events itself. - A SIGINT or SIGHUP sent to the launcher's pid alone (
kill -INT <pid>) no longer reachesrutis-host; send SIGTERM instead.
uvx rutis-host, rutis-host installed from PyPI, and the binaries on the release page are not affected.
Packages
All of these are at 0.9.1: on crates.io rutis, rutis-bridge, rutis-loader, rutis-host, rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher; on npm @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-bun, @arcships/rutis-host and the five platform packages; on PyPI rutis, rutis-host; the Go module github.com/arcships/rutis/go/rutis (tag go/rutis/v0.9.1); the rutis-host binaries on the release page.
Compatibility
- Fully compatible with 0.9.0: no API, protocol or configuration changes; 0.9.0 and 0.9.1 hosts and runtimes work together.
- Projects that install
rutis-hostfrom npm should upgrade; other setups can stay on 0.9.0. - Dylib: the SDK identity includes the package versions in its dependency tree. After rebuilding the SDK and the host with 0.9.1, dylib plugins built for 0.9.0 must be rebuilt with the new SDK; keeping the existing SDK bundle is unaffected.
rutis v0.9.0
rutis 0.9.0
0.9.0 adds Bun and Go as plugin runtimes. The host refuses a synchronous call that would close a wait cycle across runtimes, rutis-host check finds services nothing provides, and stopping and local channels are more reliable. The minimum Python goes down to 3.10 and the minimum Node to 22.
Packages
All of these are at 0.9.0:
| Registry | Packages |
|---|---|
| crates.io | rutis (the core), rutis-bridge, rutis-loader, rutis-host; the dylib toolchain rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher |
| npm | @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-bun (first release), @arcships/rutis-host, and the five platform host packages |
| PyPI | rutis, rutis-host |
| Go | github.com/arcships/rutis/go/rutis (first release, tag go/rutis/v0.9.0) |
| GitHub | rutis-host binaries for Linux / macOS (x64 / arm64) and Windows (x64), with SHA-256 checksums |
rutis-cli keeps its own version.
What's new
- Bun runtime (
@arcships/rutis-bun, Bun 1.4+): JavaScript and TypeScript plugins can run in Bun; plugin code still uses@arcships/rutis. The host takesruntimes.bun,rutis-host new --lang buncreates a project, andrutis-host devrecognizes Bun projects and reloads them. In Rust:Launcher::bun/LocalRuntime::bun(featurebun) and the loader'sbun:<module>rows. Synchronous calls are re-entrant. A plugin with a syntax error is reported withfile:line:column. Remote listening and Windows come in a later release. - Go runtime (
go/rutis, Go 1.24+): a Go plugin is compiled into a binary, and each binary is one runtime with only the standard library as a dependency. Write plugins withDefine/Plugin[C]/Serve; the config struct gives the JSON Schema,--rutis-manifestprints the manifest, andrutistesttests plugins. The host takesruntimes.go(dir/binaries/start/idle) and starts a runtime when a row needs it and stops it when idle;rutis-host new --lang go,rutis-host go add <module>@<version>;devbuilds Go projects and restarts only the Go runtime. In Rust:Launcher::go/LocalRuntime::goand the loader'sGoResolver/GoRuntimes(featurego). - Wait cycles across runtimes: before forwarding a synchronous call, the host checks who waits for whom; a call that would close a cycle (for example Python → Node → Python, each waiting synchronously) fails with
SyncWaitCycleinstead of deadlocking. The Node, Python and Bun runtimes declaresync-wait. A nested call's origin carries a session label, so nested calls such as Python → Node → Python now complete. rutis-host check: without running plugins, it checks that every service a row injects is provided by some row, and exits with 1 when one is not (when the provider is on another node, it only notes it). Disabled rows are no longer resolved. In Rust:Loader::check. It also prints each runtime's implementation and engine, and the Go binaries.- Stopping and signals:
run/devhandle SIGINT / SIGTERM / SIGHUP (Ctrl-C / Ctrl-Break / closing the console on Windows), unload the rows and exit.--shutdown-timeout <seconds>(orRUTIS_SHUTDOWN_TIMEOUT, 10 by default) bounds the cleanup, and the exit code is 2 when it did not finish. Runtime processes run in their own process group, so Ctrl-C in the terminal reaches only the host. - A runtime process's standard streams:
stdin/stdout/stderronLauncher/LocalRuntimecan each beStdio::NullorStdio::Inherit, for example to give stdin to a plugin that reads the terminal. - A plugin that disposes itself: when a plugin in a Node row unloads itself, the host gets
SelfDisposedand the row becomes disabled (a copy in an instance becomesStopped) instead of staying shown as running. New: therows.endedmessage andProcess::on_row_ended. - Local channels: one message is at most 16 MiB (the same in Rust and every language runtime); a larger one closes the channel, and a stream that ends in the middle of a message is a failure everywhere.
- Configuration: with
rutis.jsongiven as a relative path, rows such as./plugin.mjsnow resolve against the configuration file; unknown fields inrowsare warned about; a listener with onlycertor onlykeyis an error instead of silently running without TLS; runtime names must be unique. - Python (3.10 minimum): on 3.10 / 3.11 rutis starts plugin methods eagerly itself, the same way as the native implementation on 3.12+. A cancel that arrives during a plugin method's first step is no longer ignored; a WebSocket listener whose
accept()fails ends as a failure;python -m rutisprints an error and exits with 1;Listener.close()works with websockets older than 17. The optionalnetworkdependency needs websockets 15+. - Other fixes:
- Child processes inherit only fds 0–3, which fixes occasional Broken pipe errors and hangs when runtimes start concurrently on macOS.
- A process that ends has its exit status reported, including one that closed its channel but has not exited after 10 s, and how it ended when a send fails.
- A protocol version mismatch reliably gives
Handshake::Incompatibleon both sides. - Calling the root's
dispose()andCtx::shutdown()at the same time no longer makesdispose()returnClosednow and then. - A crashed Go runtime is
Downinstead of staying "Starting".
Compatibility
- Upgrade the host and the language runtimes to 0.9 together: protocol versions are unchanged (local sessions use protocol 2, sessions with endpoint identity protocol 3) and PLUGIN_API is still 1, but a 0.9 host forwards call origins with a session label that 0.8 runtimes do not accept; they end the session.
- Rust API:
LauncherandSpawninrutis-bridgeare#[non_exhaustive], andRowSchemahas a new fieldversion;rutisandrutis-loaderhave no incompatible changes. Dylib plugins must be rebuilt with the 0.9.0 SDK. rutis-host:checkfails on a service nothing provides; exit code 2 is new.- Minimum versions: Rust 1.88 (was 1.85), Node 22 (was 24), Python 3.10 (was 3.12), Bun 1.4, Go 1.24.
See the migration guide.
Getting started
npx @arcships/rutis-host@0.9.0 new greeter --lang node
npx @arcships/rutis-host@0.9.0 new greeter-bun --lang bun
npx @arcships/rutis-host@0.9.0 new greeter-go --lang go
uvx --from rutis-host==0.9.0 rutis-host new greeter-py --lang pythonThen read TypeScript plugins, Bun plugins, Python plugins, Go plugins, embedding in Rust or connecting nodes.
rutis v0.8.0
rutis 0.8.0
0.8.0 adds native Windows support and per-instance plugin management, and brings the core and the dylib toolchain into the release train: from this release on, every rutis package shares one version number.
Packages
All of these are at 0.8.0:
| Registry | Packages |
|---|---|
| crates.io | rutis (the core), rutis-bridge, rutis-loader, rutis-host; the dylib toolchain rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher (first release on crates.io) |
| npm | @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-host, and the five platform host packages |
| PyPI | rutis, rutis-host |
| GitHub | rutis-host binaries for Linux / macOS (x64 / arm64) and Windows (x64), with SHA-256 checksums |
The core has no code changes; it moves from 0.6.1 straight to 0.8.0 to line up with the train. rutis-cli keeps its own version.
What's new
- Native Windows (x64, MSVC): embedded in Rust, Node / Python language runtimes, remote runtimes and cross-language shared services run on Windows. A local runtime gets its channel over a loopback address with a one-time token. Runtime processes join a Job Object that closes with the host, so none outlives the host however it exits. Exit reasons are reported as
RuntimeState::Downas usual. TheProcess::launch/Process::mountcompatibility API and the Cordis mount bindings generated with it start their runtimes the same way. Therutis-hostcommand runs on Windows too: a release binary,npx @arcships/rutis-host(@arcships/rutis-host-win32-x64) anduvx rutis-host(a Windows wheel); it finds a project's virtual environment at.venv\Scripts\python.exeand usespythonotherwise. - Instanced groups: the loader manages plugins inside instances the application creates at runtime, for example one set per session. Set
instanced: trueon a group and manage instances withcreate_instance/remove_instance/restart_instance. Configuration edits,reloadandrestartreach every copy; if any copy fails, the change is rolled back. - Service names inside instances: a service name can belong to a kind of instance and resolve to each instance's own key. Configuration and plugin code (Rust, TypeScript, Python) write only the name. Language runtimes and node links are isolated per instance.
- Fixes:
- A local process that exits right after starting reports its exit status on send too, not just
Broken pipe. - Another local process that connects to the loopback listener and sends nothing no longer delays the runtime's start.
- The Python runtime now applies a row's
isolate.
- A local process that exits right after starting reports its exit status on send too, not just
- Release: the two PyPI projects are published from separate environments.
Compatibility
A few public Rust APIs changed incompatibly: Resolved is now built with Resolved::new; EntryStatus gains Stopped and Handover gains Loopback; EntryStatus, EntryInfo, InstanceInfo, Handover and Resolved are #[non_exhaustive], so later fields and variants are no longer breaking changes. Dylib plugins must be rebuilt with the 0.8.0 SDK. See the migration guide.
Protocol versions are unchanged: local sessions use protocol 2, sessions with endpoint identity protocol 3. Use the same train version for the host and the language runtimes; instance services need 0.8 runtimes. Node 24+ and Python 3.12+ are required.
Getting started
npx @arcships/rutis-host@0.8.0 new greeter --lang node
uvx --from rutis-host==0.8.0 rutis-host new greeter-py --lang pythonThen read TypeScript plugins, Python plugins, embedding in Rust or connecting nodes.
rutis v0.7.0
rutis 0.7.0
0.7.0 is the first release of the release train: the plugin control plane, language runtimes and networked nodes in one developer workflow. With rutis-host, TypeScript, JavaScript and Python authors can scaffold, check, run and reload plugins without writing a Rust host.
Packages
These packages are versioned 0.7.0 and build on the rutis core 0.6.1:
| Registry | Packages |
|---|---|
| crates.io | rutis-bridge, rutis-loader, rutis-host |
| npm | @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-host, and four platform host packages |
| PyPI | rutis, rutis-host |
| GitHub | rutis-host binaries and SHA-256 checksums for Linux/macOS, x64/arm64 |
The rutis core is not part of this release and stays at 0.6.1. rutis-cli, the agent examples, aimux-llm and dylib tools keep their own versions.
What's in it
- Plugin control plane: layered configuration, dynamic edits, persistence, service catalogs, expressions, multiple plugin sources, volatile configuration and self-disposal through
rutis-loader. - Language plugins: JS/TS and Python leaf plugins, named runtimes, service sharing, lifecycle cleanup, cross-session references and module refresh.
- Remote runtimes: loader rows on other machines, controller leases, release and takeover.
- Nodes: shared connections, service imports/exports, hosted plugins, events, multi-hop calls and reconnection.
- Transports: local and inherited Unix sockets, in-memory channels, WebSocket with TLS, authentication and shared listeners.
- Standalone host:
rutis-host new,check,runanddev, with matching Node/Python project templates. - Guides and validation: Chinese/English role-based guides, channel/session/runtime/node conformance suites, and reconnect/process-lifecycle soak tests.
Compatibility
rutis-interop is folded into rutis-bridge, and the old packages are no longer updated. The npm SDK and runtime are now @arcships/rutis and @arcships/rutis-runtime. Users of the old packages must migrate dependencies, imports, features and generated bindings using the migration guide. Hosts and language runtimes should come from the same train version.
Package versions are separate from protocol versions: local sessions use protocol 2; endpoint sessions use protocol 3.
rutis-host and local language runtimes support Linux/macOS; use WSL on Windows. Node 24+ and Python 3.12+ are required.
Getting started
npx @arcships/rutis-host@0.7.0 new greeter --lang node
uvx --from rutis-host==0.7.0 rutis-host new greeter-py --lang pythonRead the developer guides for plugins, embedding and networking.
rutis 0.6.0
rutis 0.6.0
This release is for the rutis core crate. rutis-cli binary releases are unaffected by this tag.
Highlights
- Public types that keep growing are
#[non_exhaustive]: errors (CordisError,ServiceReadFailure,ServiceWriteFailure,DisposeWaitError,ServiceReadError,ServiceWriteError), diagnostics and observation records (RuntimeDiagnostics,PluginDiagnostics,DependencyDiagnostics,DependencyStatus,ResolvedDependency,ServiceAccess,BindingDiagnostics,EffectMeta,DispatchAttempt,DispatchMode,FiberStatusChanged) andEventOptions. Adding fields or variants to them is no longer a breaking change. (#84) EventOptions::default().prepend(true).once(true)builds registration options outside the crate.- Same-key
emitbacklogs are visible:RuntimeDiagnostics::event_backlogslists, per event key, the accepted emits not yet finished and how long the oldest has waited (EventBacklog). Backpressure is deliberately not added; see the performance notes. (#90) - Fix: root shutdown cancels descendants before draining instance events, so a listener waiting for its owner's cancellation no longer keeps shutdown waiting. (#79)
- The development handbook's examples compile as doctests. (#78)
- Releases check semver against the previous crates.io version before publishing.
See the 0.5 → 0.6 migration guide.
Compatibility notes
- Build
EventOptionswithEventOptions::default()and its setters instead of a struct literal. matchon the errors and onDependencyStatus/DispatchModeneeds a wildcard arm.- Destructuring the diagnostics and observation records needs
..; field access is unchanged.Snapshot,FiberState,EffectPhaseandEffectare unchanged. - The dylib SDK moves to
rutis-sdk0.4.0; hosts and plugins must be rebuilt together.
Install with cargo add rutis@0.6.0.
rutis-interop 0.1.0
rutis-interop 0.1.0
First release of rutis-interop: mount published Cordis (Node) plugins in rutis applications across processes, with Rust bindings generated from the plugins' type declarations at build time.
- crate
rutis-interop0.1.0 on crates.io (depends onrutis0.6) - npm runtime
@arcships/rutis-interop0.1.0, published with provenance
Both are released together from the same tag and must speak the same protocol version (checked at build time). Unix only; Node 26 or later.
Highlights
- Declare mounts in
Cargo.toml([package.metadata.rutis-interop]) and callrutis_interop::build::from_manifest()inbuild.rs; each mount becomes a module with aPlugin, typed service proxies, events and host-service traits. - Services in both directions: Cordis services become ordinary rutis services; the rutis application can provide services the mounted plugins inject.
- Live objects, callbacks, cancellation by dropping futures, events in both directions, group mounts, crash handling (services are withdrawn when the Node process ends).
- Relocatable deployments:
RUTIS_INTEROP_ROOTnames a deployed copy of the npm project.
Getting started: the rutis-interop guide (Chinese). crates/rutis-dsh runs the full dsh web UI in a rutis host with it.
rutis 0.5.0
rutis 0.5.0
This release is for the rutis core crate. 0.4.0 was never published; its content ships here as 0.5.0. rutis-cli binary releases are unaffected by this tag.
Highlights
- Typed
EventKey<E>unifies default, named and instance channels behind one set of methods:on,once,emit,parallel,serial,waterfallall take a key;EventKey::namedbuilds const static keys without allocation. EventPattern<E>::prefix("room/")subscribes to groups of dynamic names;PatternListenerreceives the actually matched key, and patterns share registration order with exact listeners (prepend,once).- Synchronous decision points: events implementing
SyncEventuseon_sync+bail_syncandon_waterfall_sync+waterfall_sync; terminals are localFnOnceand may borrow stack variables orMutexGuard. Same-thread reentry on the same full key returnsReentrantEvent. EventOptionsgainsonce;emitnow reports whether the call was admitted, and instance out-of-range/closed become errors.- Service strict declared reads and mutable-write/strict-read interception; labeled effect ownership tree; dispatch observation before listener selection (nested dispatch from observer reentry supported).
- Fixes: replaced and candidate
StoredValuedropped outside framework locks, nested failure causes inDisplay, early cleanup error consumption, instance subtree follow-ups, notification error routing to ErrorSink. - Workspace additions: Linux dylib SDK (
rutis-sdk0.3.0,rutis-dylib,rutis-dylib-launcher) with pre-execution and pre-dlopen verification.
See the 0.3 → 0.5 migration guide for the full API mapping and semantics.
Compatibility notes
on(ctx, listener)becomeson(ctx, &EventKey::of(), listener); the old*_keyed/*_instancemethods remain as deprecated wrappers (since 0.5.0).- Direct
EventOptionsconstruction needsonce: falseor..Default::default(). DispatchModegainsBailSync/WaterfallSync;CordisErrorgainsSyncEventPanicked. Exhaustive matches must add the new arms.- dylib SDK identity follows version and locked dependencies; hosts and plugins must be rebuilt together against
rutis-sdk0.3.0.
Install with cargo add rutis@0.5.0.
rutis 0.3.0
rutis 0.3.0
This release is for the rutis core crate. rutis-cli remains at 0.2.0; this tag does not trigger the CLI binary release workflow.
Highlights
- Fiber-owned
InstanceIdand instance-awareTypeKey, with subtree checks for service registration, reads, dependency gating, and diagnostics. EventBus::{on,emit,serial,parallel}_instancewith isolated listener tables and independent orderedemitchains per instance.FiberView::shutdown()for permanent subtree closure, shared completion, dependency-aware disposal, and reclamation of parent/index/bus records.- Final root
Ctx::shutdown()and bounded disposal waits; the rootdispose/restartbehavior remains available. - Review fixes for queued
settle, listener removal versus dispatch snapshots, dependency declaration consistency, and synchronous listener panic reporting.
See PR #25 for the implementation and issue #30 for selected follow-up work.
Compatibility notes
TypeKeyisClone, as in 0.2.x; dynamic qualifiers preventCopy.- Instance keys enforce subtree visibility at runtime.
TypeKey::of::<T>()still compiles for every service type; compile-time service-scope markers belong in the consuming runtime. - Listener registration after root or subtree closure now returns
Closed, including the existing unscoped and named registration methods.
Install with cargo add rutis@0.3.0.
rutis-cli 0.2.0
Binary release of rutis-cli (minimal coding agent: bash + replace_text).
Install: download the tar.gz for your platform, verify the .sha256, extract, and put rutis-cli on your PATH. (cargo install rutis-cli installs the older crates.io build without the rutui TUI.)
Requires an aimux provider key at runtime (e.g. DEEPSEEK_API_KEY); try rutis-cli --scripted for an offline demo.