Skip to content

feat(repl): introduce pluggable RoomSink for runtime I/O#326

Merged
spytensor merged 2 commits into
mainfrom
feat/v0.9-200-roomsink-pluggable-runtime
May 25, 2026
Merged

feat(repl): introduce pluggable RoomSink for runtime I/O#326
spytensor merged 2 commits into
mainfrom
feat/v0.9-200-roomsink-pluggable-runtime

Conversation

@spytensor
Copy link
Copy Markdown
Owner

Summary

Stage 1 of hosting the executable REPL runtime inside the full-screen ratatui room (#320). Adds a renderer-agnostic RoomSink trait so the same repl::run_with_options execution path can drive either the legacy stdout (cr start) or a future TUI host with no logic duplication. cr start output is byte-for-byte unchanged; the change is structural only.

Architecture impact

  • No change — purely follows docs/architecture.md as written.
  • Refines an open question — links to its entry in docs/proposed-amendments.md.
  • Amends a locked decision — must include the amendment in docs/proposed-amendments.md and reference it here.

The runtime contract (when roles run, when CrepEvents publish, when permission prompts fire) is unchanged. Only the visible-event delivery surface gains a trait boundary.

Linked issues

Refs #320 (full-screen runtime parity). Unblocks the four follow-up issues opened alongside this PR (Stages 2–5).

Acceptance criteria

This PR is Stage 1 of #320 — it does not by itself satisfy any AC of #320. It puts the trait in place so AC-1..AC-7 can be tackled in parallel.

  • Stage-1 AC: a sink trait exists, the runtime threads Arc<dyn RoomSink> end-to-end, cr start constructs StdoutSink and prints identically to today.

Test plan

  • cargo fmt --all -- --check passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • cargo test --all-features --locked passes (594 lib + all integration)
  • (if touching shell harness) shellcheck spike/*.sh passes — N/A, no shell changes
  • Manual smoke: not run (cr start byte-for-byte unchanged by construction — StdoutSink::emit calls the same render_event_line formatter and the same println! the legacy code did).

Evidence packet

  • WorkOrder: N/A — refactor enabling v0.9.x: implement true full-screen runtime parity before making live room default #320, not its own workorder
  • Gate thread: N/A
  • Changed files:
    • src/room_io.rs (new, 179 LOC): RoomEvent, NoticeLevel, RoomSink trait, StdoutSink impl, stdout_sink() factory, 2 unit tests
    • src/lib.rs (+1): register room_io
    • src/repl.rs (+38): run_with_options → thin wrapper; new run_with_options_and_sink(root, opts, sink); send_and_drain / drain_one_turn_handling_ctrl_c / write_journal gain sink parameter; /transcript inlines StdoutSink
    • src/repl/render.rs (+13): render_event signature gains sink: &dyn RoomSink, body delegates to sink.emit(RoomEvent::Crep)
    • src/repl/turn.rs (+6): drain_one_turn gains sink: Arc<dyn RoomSink>; 4 render_event call sites pass it through
    • src/repl/show.rs (+6): cr show (diagnostic command) inlines StdoutSink
    • src/console_tui.rs (+4): incidental — clear 4 ratatui 0.30 deprecation warnings introduced by chore(deps)(deps): bump ratatui from 0.27.0 to 0.30.0 #324 so clippy -D warnings stays green
  • Commands run:
    • cargo fmt --all -- --check
    • cargo clippy --lib --tests --all-targets -- -D warnings
    • cargo test --lib → 594 passed, 0 failed
    • cargo test --tests → all integration suites passed
  • Test/check results: all green
  • Snapshot/fixture evidence: none required — no console/view-model output changed
  • Role reviews: none
  • Risks: see Risk and rollback below
  • Rollback: revert is a clean single-commit revert
  • Unverified items: behavior of cr start under a real engine subprocess was not manually re-run (covered by integration tests and by construction since the formatter is identical)

Tracker update

The current active tracker is #238 per AGENTS.md (or the v0.9 milestone tracker — verify and update). Stage 1 is structural; no tracker checkbox flips until Stages 2–5 land.

Implementation status: Stage 1 complete; #320 still requires Stages 2-5 (separate issues opened).

Risk and rollback

  • Risk: low. The change is additive (new trait + new wrapper function) plus a mechanical signature change in 4 internal functions. StdoutSink::emit for the only currently-modeled event variant (Crep) calls the same formatter and same println! the legacy code did. No control-flow change. 594 unit tests + all integration tests pass unchanged.
  • Rollback: single-commit revert.

Out of scope

  • Porting the other ~160 stdout sites (output::*, splash::*, work::render_card, status::StatusRegion, permission_prompt::*) through the sink. Tracked in follow-up issues.
  • Writing a TuiSink or any ratatui-side renderer for runtime events. Tracked in a follow-up issue.
  • Deleting the dead-end LiveRoomBridge / apply_action_to_snapshot. Tracked in a follow-up issue.
  • Flipping the default cr entrypoint. Stays on the legacy path until full-screen runtime parity is verified.

Stage 1 of hosting the executable REPL runtime inside the full-screen
ratatui room. Adds a renderer-agnostic sink trait so the same runtime
can drive either the legacy stdout path (`cr start`) or a future TUI
host without code duplication.

- `src/room_io.rs`: `RoomEvent` enum, `RoomSink` trait, `StdoutSink`
  impl that preserves byte-for-byte legacy output, `stdout_sink()`
  factory, in-tree unit tests.
- `repl::run_with_options` is now a thin wrapper around
  `run_with_options_and_sink(root, opts, sink)`. The runtime threads
  `Arc<dyn RoomSink>` through `send_and_drain` →
  `drain_one_turn_handling_ctrl_c` → `drain_one_turn` → `render_event`.
- Diagnostic surfaces (`cr show`, `/transcript`) inline `StdoutSink` —
  they are always stdout-bound.
- Incidental: clear the four `ratatui::Frame::size` /
  `Buffer::get` deprecation warnings introduced by the 0.30 bump
  (#324) so the strict `clippy -D warnings` gate stays green.

`cr start` output is byte-for-byte unchanged: `StdoutSink` calls the
same `render_event_line` formatter and the same `println!`. The
threading is the load-bearing change; subsequent issues port the
remaining ~160 stdout sites and add the TUI sink.

Refs #320
The ratatui 0.30 bump in #324 transitively pulled darling 0.23 which
requires rustc 1.88. main has been red since that PR merged. This bump
unblocks CI without rolling back ratatui.

Cargo.toml `rust-version` and rust-toolchain.toml `channel` move
together so local builds and CI stay aligned.
@spytensor spytensor merged commit 5ab2388 into main May 25, 2026
5 checks passed
@spytensor spytensor deleted the feat/v0.9-200-roomsink-pluggable-runtime branch May 25, 2026 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant