Map: core / IO, process & stream
The byte plumbing under the evaluator’s pipelines and external commands: where a stage’s bytes come from and go, the signals and process groups that govern a foreground child, the daemon that fires every scheduled action, and the labels the lazy Stream protocol shares with the type system. Authority over the controlling terminal is carried as a value, not re-derived from process state — the foreground handoff is gated on a held TerminalLease.
IO — core/src/io/
io.rs holds Io, the per-Shell bundle (stdin / stdout / stderr /
interactive / terminal / launch_role / capture_outer), and
LaunchRole — the process-group role distinguishing the top-level
orchestrator (TopLevel) from a pipeline-local child (PipelineStage). It
decides pgid placement (a top-level standalone external may lead its own
group so a watchdog cancel can kill(-pgid, …) the whole subtree; a stage
joins the pipeline’s pgid) and forgives SIGPIPE on pipeline children — never
who may foreground. Io::inherit_from / return_to move the read-once stdin
between parent and child shells.
source.rs—Source, a stage’s byte input:Pipe(upstream stage),File(a<fileredirect parked here),Terminal(fall through to fd 0), andEmpty(no input — immediate EOF, child stdin to/dev/null, no fall-through to fd 0).Emptyis what an exarch tool turn installs so a tool command can never steal the TUI’s terminal; it is kept distinct fromTerminalprecisely so denial of byte input and denial of foreground stay separate effects.sink.rs—Sink, byte output and child stdio routing (ChildStdioPlan): terminal, stderr, kernel pipe, redirect file, in-memoryByteBuffercapture, tee, frontend printer, line-framing adapter.child_stdout/child_stderrcentralise the (stdio, pump) decision so no caller computes inherit-vs-pipe by hand.terminal.rs—TerminalState: cached startup isatty / ANSI / NO_COLOR / mode bits.startup_foregroundrecords whether ral’s group owned the controlling terminal’s foreground at entry; it is no longer a per-handoff oracle but the lease’s mint condition (terminal-foreground-ownership). On Windows it also ownsconsole_mode_snapshot/restore_console_mode, the termios-snapshot analogue a panic hook restores a raw-mode console through.
Redirect reads and writes — < file, > file and friends — open through the
File source/sink here, and the runtime emits a byte-level I/O door at each:
the read fires eagerly when stdin is redirected, the write at frame settle with
its committed / aborted / failed outcome. The event shapes and their card
rendering belong to io-surface.
Process — core/src/process/
outcome.rs—Signal,WaitOutcome, and the user-facingSpawnFailure/CommandFailurethe evaluator surfaces.lease.rs—TerminalLease, the unforgeable authority to hand the controlling terminal to a child viatcsetpgrp. No public constructor, neitherClonenorCopy: a host cannot forge or duplicate it. Minted at most once at session construction iff ral owned the foreground at startup (Noneon a backgrounded or tty-less launch, and always on platforms with notcsetpgrp), then lent per turn as&TerminalLeaseto the one chokepoint that foregrounds —ForegroundGuard::try_acquire, which is uninvocable without the borrow. The type lives at shell-state; the rationale at terminal-lease.reaper.rs— one lazily started, process-global daemon (ral-reaper) owning a min-ordered heap of(when, action)entries, firing each at itsInstant. Deadlines are data, not a thread per worker:arm_lifetime/arm_callbackpush an entry and return a#[must_use]Deadlineguard — dropped, the entry disarms;keep-consumed, it fires regardless (the fire-and-forget mode a detached worker’s lease needs, since the worker outlives thespawnthat armed it). The fired action isCancel(scope) | Run(closure):Cancelcancels aCancelScopewithCancelCause::Deadline(the foreground wall);Runinvokes an opaque host closure once, the shape a scheduled wakeup rides — exarch arms aRunthat posts a prompt and wakes its idle loop, a detached agent worker arms aRunthat cancels its own token at its ceiling, and a detachedspawnworker’s idle-observation lease chain (builtins) is akeep-edRunthat re-arms itself until it reaps or the worker settles. The reaper stays ignorant of prompts, cron, and sessions; recurrence is not a reaper concept — a recurring producer re-arms from inside its ownRun, fired outside the heap lock so it cannot deadlock (scheduled-wakeups, concurrency-primitives).cancel.rs— the cause-bearingCancelScopetree (DurableRoot/ForegroundScope,CancelCause) for structured-concurrency cancellation, polled cooperatively in hot loops (hot-path-cancellation), with the process-globalCancelSlotpublications that let a signal handler or TUI thread cancel a scope it cannot hold.signal.rs— signals are causes: the platform handlers translate each delivered signal into aCancelCauseon the published slots — SIGINT → foregroundInterrupt, SIGTERM/SIGHUP → rootTerminate— so one cancel-aware wait loop serves user interrupts, timeouts, and termination alike (signals-are-causes).checkis scope-only;clearis the boundary acknowledgment; theESCALATIONcounter backs only the third-delivery_exitladder (escalation_pendingis the probe). A raw-mode frontend’s Esc drives the same non-escalating foreground cancel (esc-non-escalating-interrupt). AlsoPgid/PgidPolicy/ChildHandleand the platformspawn_with_pgidfamily for process-group placement. UnixForegroundGuardtakes the&TerminalLease, performs thetcsetpgrphandoff, snapshots and restores tty foreground / termios, and blocks SIGTTOU for the parent-only restore window; unixinterrupt_foreground_childre-sends raw-mode Esc/Ctrl-C to a foreground external group,relay_handlerfans SIGINT to active external pgids, andquit_handleris the Ctrl-\root abort. Platform handlers live insignal/unix.rsandsignal/windows.rs. Unix child and process-group waits pass through typed blocking / polling funnels for pids and pgids: rustix owns pid and total status types, while the funnel shape owns optionality and makesEINTRinvisible without conflatingNOHANGwithECHILD(total-wait-status). The Windows side carries the console-control escalation ladder (CTRL_BREAK_EVENTfan-out, thenTerminateJobObject, then exit),relay_interrupt—relay_handler’s non-escalating twin, whose fan-out skips a detached worker’s group — andbreak_pipeline_group, the SIGTERM-grade cooperative break a job teardown sends before escalating tokill_pipeline_group.launch.rs— the owned launch value and its platform interpreters. Unix lowers tostd::process::Commandand keeps thepre_execpgid/fd discipline; Windows owns the rawCreateProcessWboundary, including command-line/env rendering, explicit helper-handle allow lists, theSECURITY_CAPABILITIESattribute a confined spawn attaches (its projection’s AppContainer SID and the capability SIDs — capabilities), the launch mutex, suspended create → Job Object assignment → resume, and the widenedChildHandleraw process wrapper (windows-spawn-boundary). The whole stop-work flow — theInterrupt < Explicit < Deadline < Terminate < RootAbortorder — is narrated in cancellation.
Spawning an external command is capability-gated; that gate lives in capabilities, and the command/pipeline dispatch that drives this plumbing in runtime.
Stream — core/src/stream.rs
Shared label vocabulary for the lazy Stream protocol: runtime variant labels
more / done and the head / tail payload fields, with the type-row
spellings (`more / `done) kept beside them so runtime and
typechecker recognition cannot drift. docs/SPEC.md §13
covers Stream semantics.