Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
Added
Changed
Fixed
Removed
0.3.1 - 2026-01-11
Added
-
CancellationToken: Cooperative cancellation mechanism for long-running custom commands. Commands check
cancelled?periodically and stop gracefully whencancel!is called. IncludesCancellationToken::NONEnull object for commands that ignore cancellation. -
Command::Custom Mixin: Include in your class to mark it as a custom command. Provides
tea_command?brand predicate andtea_cancellation_grace_period(default 2.0 seconds) for configuring cleanup time after cancellation. -
Command::Outlet: Messaging gateway for custom commands. Use
put(tag, *payload)to send results back to the update function. Validates Ractor-shareability in debug mode. -
Custom Command Dispatch: Runtime now dispatches custom commands (objects with
tea_command?returning true) in background threads. Commands receive anOutletfor messaging and aCancellationTokenfor cooperative shutdown. -
Command.custom Factory: Wraps lambdas/procs to give them unique identity for dispatch tracking. Each
Command.custom(callable)call produces a distinct wrapper, enabling targeted cancellation. Accepts optionalgrace_period:to override the default 2.0 second cleanup window. -
Command.cancel Factory: Request cancellation of a running command. Returns a
Command::Cancelsentinel that the runtime routes to the appropriate command’s CancellationToken. -
Runtime Cancellation Dispatch: The runtime now handles
Command::Cancelby signaling the target command’sCancellationToken, enabling cooperative cancellation of long-running commands. Respectstea_cancellation_grace_period: waits for the grace period, then force-kills unresponsive threads. UseFloat::INFINITYto never force-kill. -
Graceful Shutdown: On exit, runtime signals all active commands then respects each command’s grace period. Commands with
Float::INFINITYgrace are waited on indefinitely (user has SIGKILL). Final queue messages are processed before returning. -
Automatic Error Propagation: Custom commands that raise unhandled exceptions now produce a
Command::Errormessage instead of corrupting the TUI display. The runtime catches exceptions and pushesCommand::Error.new(command:, exception:)to the queue. Pattern match onCommand::Errorin your update function to handle failures uniformly. Factory methodCommand.error(command, exception)is available for testing. -
Command::System Cancellation: Streaming shell commands now respect cooperative cancellation. When cancelled, sends
SIGTERMfor graceful shutdown, thenSIGKILLif the child process doesn’t exit. Prevents orphaned child processes from lingering after app exit.
Changed
Fixed
-
Ractor Enforcement is Debug-Only: The Ractor-shareability check now only runs in debug mode (and automated tests). Production skips this check for performance, matching the original specification. Previously, the check ran unconditionally.
Removed
0.3.0 - 2026-01-08
Added
-
Router DSL: New
Tea::Routermodule provides declarative routing for Fractal Architecture: -
route :prefix, to: ChildBag— declares a child bag route -
keymap { key "q", -> { Command.exit } }— declares keyboard handlers -
keymap { key "x", handler, when: -> (m) { m.ready? } }— guards (also:if:,only:,guard:,unless:,except:,skip:) -
keymap { only when: guard do ... end }— nested guard blocks apply to all keys within (also:skip when: ...) -
mousemap { click -> (x, y) { ... } }— declares mouse handlers -
action :name, handler— declares reusable actions for key/mouse handlers -
from_router— generates an UPDATE lambda from routes and handlers -
Composition Helpers: New helper methods for Fractal Architecture reduce boilerplate:
-
Tea.route(command, :prefix)— wraps a command to route results to a child bag -
Tea.delegate(message, :prefix, child_update, child_model)— dispatches prefixed messages to child bags -
Command Mapping:
Command.map(inner_command, &mapper)wraps a child command and transforms its result message. Essential for parent bags routing child command results. -
Shortcuts Module:
require "ratatui_ruby/tea/shortcuts"andinclude Tea::Shortcutsfor short aliases: -
Cmd.exit— alias forCommand.exit -
Cmd.sh(command, tag)— alias forCommand.system -
Cmd.map(command, &block)— alias forCommand.map -
Sync Event Integration: Runtime now handles
Event::SyncfromRatatuiRuby::SyntheticEvents. When a Sync event is received, the runtime waits for all pending async threads and processes their results before continuing. Useinject_syncin tests for deterministic async verification. -
Streaming Command Output:
Command.systemnow accepts astream:keyword argument. Whenstream: true, the runtime sends incremental messages ([:tag, :stdout, line],[:tag, :stderr, line]) as output arrives, followed by[:tag, :complete, {status:}]when the command finishes. Invalid commands send[:tag, :error, {message:}]. Default behavior (stream: false) remains unchanged. -
Custom Shell Modal Example: Added
examples/app_fractal_dashboard/bags/custom_shell_modal.rbdemonstrating a 3-bag fractal architecture for a modal that runs arbitrary shell commands with streaming output. Features interleaved stdout/stderr, exit status indication, and Ractor-safe implementation usingtui.overlayfor opaque rendering.
Changed
-
Command Module Rename (Breaking): The
Cmdmodule is nowCommandwith Rubyish naming: -
Cmd::Quit→Command::Exit(useCommand.exitfactory) -
Cmd::Exec→Command::System(useCommand.system(cmd, tag)factory)
Fixed
Removed
0.2.0 - 2026-01-08
Added
-
The Elm Architecture (TEA): Implemented the core Model-View-Update (MVU) runtime. Use
RatatuiRuby::Tea.run(model, view: ..., update: ...)to start an interactive application with predictable state management. -
Async Command System: Side effects (database, HTTP, shell) are executed asynchronously in a thread pool. Results are dispatched back to the main loop as messages, ensuring the UI never freezes.
-
Ractor Safety Enforcement: The runtime strictly enforces that all
ModelandMessageobjects are Ractor-shareable (deeply frozen). This guarantees thread safety by design and prepares for future parallelism. -
Flexible Update Returns: The
updatefunction supports multiple return signatures for developer ergonomics: -
[Model, Cmd]— Standard tuple. -
Model— Implicitly[Model, Cmd::None]. -
Cmd— Implicitly[CurrentModel, Cmd]. -
Startup Commands:
RatatuiRuby::Tea.runaccepts aninit:parameter to dispatch an initial command immediately after startup, useful for loading initial data without blocking the first render. -
View Validation: The
viewfunction must return a valid widget. ReturningnilraisesRatatuiRuby::Error::Invariantto catch bugs early.
0.1.0 - 2026-01-07
Added
-
First Release: Empty release of
ratatui_ruby-tea, a Ruby implementation of The Elm Architecture (TEA) forratatui_ruby. Scaffolding generated byratatui_ruby-devtools.