Run and Inspect Finite Process Work
By the end of this chapter, you will have submitted copied document bytes to a
local process, edited and saved while it waited, inspected its escaped output,
reloaded its command and cancelled another run. Use the
terminal prerequisites.
The exercise uses trusted Ruby and /usr/bin/ruby on Linux.
Prepare an Isolated Check
From the repository root, build the terminal and create a temporary directory:
cargo build --locked -p rur-editor --bin rur-terminal-proof
process_editor="$PWD/target/debug/rur-terminal-proof"
process_demo=$(mktemp -d)
printf 'seed\n' > "$process_demo/note.txt"
Save this worker as $process_demo/finite-worker.rb. It records the copied
input, waits for an explicit file, and emits that input plus hostile stderr
bytes. The fail mode writes a separate file before exiting with code 7.
mode = ARGV.fetch(0)
STDOUT.binmode
STDERR.binmode
input = STDIN.read
File.binwrite('captured.bin', input)
File.binwrite('worker.pid', Process.pid.to_s)
if mode == 'fail'
File.binwrite('effect.txt', 'changed before failure')
exit 7
end
sleep 0.01 until File.exist?('continue')
STDOUT.write(input)
STDERR.write([27, 0, 255].pack('C*'))
Save this configuration as $process_demo/process.rb:
directory = Dir.pwd
worker = File.join(directory, 'finite-worker.rb')
Rur.configuration.command('finite-check', ->(context) {
mode = context.argument
context.process({
'label' => 'Finite check',
'executable' => mode == 'missing' ? '/no-such-rur-executable' : '/usr/bin/ruby',
'argv' => ['--disable-gems', worker, mode],
'cwd' => directory,
'stdin' => context.observe.fetch('text').b,
'env' => {'RUBYOPT' => '', 'RUBYLIB' => ''},
'timeout_ms' => 30000
})
}, {'kind' => 'compound', 'requires' => 'buffer', 'argument_bytes' => 32,
'effects' => ['process']})
The process effect permits one copied request in a compound command. It does
not change editor text. Arguments stay separate; no shell expands their bytes.
cwd is explicit, and the process inherits the environment with the listed
overrides. Configuration and children run with your permissions. A failed
callback starts no child. Execution begins after successful command publication;
a later spawn failure preserves any already committed editor changes.
Start inside the temporary directory so the worker's files stay there:
(cd "$process_demo" && env -u RUBYOPT -u RUBYLIB -u GEM_HOME -u GEM_PATH "$process_editor" --config process.rb --profile nonmodal note.txt)
Edit While the Check Waits
Alt-x opens command entry in both profiles. Invoke finite-check, type copy
at its argument prompt and press Enter. In another shell, inspect
$process_demo/captured.bin; it contains exactly seed and one newline.
Invoke show-progress to read the live operation. Ctrl-G closes this page
without stopping the process. Invoke inspect-job and confirm its empty
argument to inspect the most recent process in a separate ordinary buffer.
It reports pending execution and output completeness. Invoke kill-buffer to
close that details buffer and return to the note.
Type ! at the beginning of the note. Save with Ctrl-X Ctrl-S and wait for
saved durably. The saved file now contains exactly !seed and a newline;
the process still owns its original copied input.
While it runs, change the configuration label from Finite check to
Reloaded check in another editor and invoke reload-configuration. The
accepted operation continues with its historical label and input. Current
native inspection and cancellation remain available; old callback contexts
and old checked actions cannot acquire authority from the new configuration.
Release the waiting worker from the shell:
touch "$process_demo/continue"
Invoke inspect-job with an empty argument again. It reports exit code 0,
complete streams and External effects: unverified. Its stdout contains
seed followed by a displayed line break. Inspect stderr by entering the displayed process token followed
by stderr 0, for example OWNER:REQUEST:GENERATION stderr 0. Copy the actual
token from your result. The stderr page contains \x1b\x00\xff; those bytes
are displayed as text and cannot clear the terminal or execute a command.
When a page has more output, its Continue: line gives the next argument.
Close each details buffer with kill-buffer.
Cancel and Read the Actual Outcome
Remove the release file from the other shell:
rm "$process_demo/continue"
Invoke finite-check with hold, then open show-progress. Select its row and press Enter. The detail page lists
Action 1: cancel-progress. Close the page with Ctrl-G, then invoke feedback-action through Alt-x to
request that checked action. It addresses the current operation
revision and native identity. A stale action, a stopping job or an already
finished job refuses cancellation. You can also invoke cancel-progress with
a current native operation token supplied by inspection; the process-result
token and a PID are not cancellation authority.
After reconciliation, inspect-job reports cancellation after start, actual
exit/signal facts and cleanup. Cancellation cannot prove rollback of external
effects. Dismissing feedback, clearing its history or closing a details buffer
only changes presentation. The ordinary global Ctrl-G recovery command also
has its established pending-job cancellation behavior; close the progress
page before treating Ctrl-G as a global command.
Invoke finite-check with fail. Its exit code is 7 and effect.txt still
contains changed before failure. Invoke it with missing to see a spawn-stage
failure with Started: false and External effects: not-started. The editor
remains usable in both cases. Exit zero established only execution success;
none of these outcomes proves a domain result or undoes an external write.
Return to the note, type ? after !, save and exit with Ctrl-X Ctrl-C. Verify
the exact bytes, including the newline, after the terminal restores its modes:
printf '!?seed\n' | cmp - "$process_demo/note.txt"
Repeat with a fresh directory and --profile modal. Before typing !, press
i to enter Insert. Named commands and inspection work through Alt-x in both
profiles. After returning from a details buffer, enter Insert again if the
source pane is in Normal.
Recognize Finite Limits
Four outstanding jobs share admission across snapshot and process executors. One process worker supervises one process group at a time. A request admits at most one MiB of stdin, 32 arguments totalling eight KiB, 16 environment overrides totalling eight KiB, and a deadline of at most 30 seconds including queue time. The executable and working directory each admit at most 4096 bytes. Each stream retains at most 64 KiB; exceeding a limit stops execution and preserves its bounded prefix and honest completeness facts.
The result store keeps four memberships. Old copied details remain ordinary
text, while evicted result tokens stop resolving. A full buffer registry can
refuse a new details buffer without losing native execution or retained output.
Trusted Ruby can inspect copied Rur.job_results and bounded
Rur.job_output(token, 'stdout', offset, count) pages; a page is at most 16 KiB
and remains subject to aggregate admission.
See the runtime request and result reference and the native job ownership reference for exact fields, limits and lifecycle rules. Children are trusted local programs; the editor's accounting is not a child-memory limit or a sandbox.
Previous: Reload Your Personal Configuration | Part | User Guide | Next: Modal Interaction