Repository navigation
host: speak NVXC v2, and stream execs in the CLI (SL4.4c) - #1541
Merged
Pedro Henrique Penna (ppenna) merged 2 commits intoNov 12, 2026
Merged
Pedro Henrique Penna (ppenna) merged 2 commits into
Pedro Henrique Penna (ppenna) merged 2 commits into
Conversation
Contributor
This pull request changes existing testsIt modifies or removes 131 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests. Test code
... and 77 more, which the job's summary lists. End-to-end tests
Test policy
Relocated unchanged: 0; added: 46. Compared the merge base |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Outstanding issues can append cleanup diagnostics to unterminated stderr and cause shutdown to fail spuriously when it encounters an unconsumed execution ERROR frame.
2 open issues
What changed in this PR
Moves NVX’s host control paths to NVXC v2 and enables streaming CLI executions, building on the codec and servers from SL4.4a–b. Version 1 remains for removal in SL4.4d.
Changes:
- Migrates host sessions, capture, and restore to v2, replacing feature queries with protocol-version checks.
- Streams CLI stdin, stdout, and stderr, with windowed input, uncapped output, and Ctrl-C cancellation.
- Updates tests, feature gates, and documentation for the new behavior.
| File | Description |
|---|---|
| scripts/test-layout-allowlist.json | Updates dead-code seam allowances. |
| scripts/test_microvm_tests.py | Updates streamed-output regression expectations. |
| scripts/nvx_tools/sandbox_lifecycle_tests.py | Checks complete 2 MiB output and successful status. |
| nvx-rs/tests/cli/sandbox_run.rs | Covers streaming runs and refusal diagnostics. |
| nvx-rs/tests/cli/lifecycle.rs | Tests streamed input, output, and diagnostics. |
| nvx-rs/tests/cli/harness.rs | Adds commands with piped input. |
| nvx-rs/tests/cli.rs | Tests feature-free startup and Ctrl-C cancellation. |
| nvx-rs/src/protocol/tests.rs | Adjusts v1 test feature gates. |
| nvx-rs/src/protocol/mod.rs | Gates protocol exports by their remaining users. |
| nvx-rs/src/protocol/features.rs | Marks legacy feature handling for later removal. |
| nvx-rs/src/protocol/exec.rs | Restricts the legacy output-limit constant’s gate. |
| nvx-rs/src/protocol/app.rs | Enables v2 for CLI and regates v1 items. |
| nvx-rs/src/host/session/tests/managed_lifecycle.rs | Migrates real-guest session tests to v2. |
| nvx-rs/src/host/session/tests.rs | Tests version checks, input windows, and active-exec stop. |
| nvx-rs/src/host/session.rs | Implements v2 host requests and execution streams. |
| nvx-rs/src/host/restore/tests.rs | Regates the retained v1 restore test. |
| nvx-rs/src/host/restore_driver/tests.rs | Migrates the scripted restore peer to v2. |
| nvx-rs/src/host/restore_driver.rs | Starts restored workloads with explicit stdin end. |
| nvx-rs/src/host/cli/snapshots/capture/tests.rs | Migrates capture fixtures to v2. |
| nvx-rs/src/host/cli/session/tests.rs | Covers streaming, cancellation, and input failures. |
| nvx-rs/src/host/cli/session.rs | Streams CLI executions through the host session. |
| nvx-rs/src/host/cli/sandbox/mod.rs | Removes buffered output writes and tracks stderr endings. |
| nvx-rs/src/host/cli/sandbox/lifecycle/start/tests/restore.rs | Checks v2 restore sequencing and stdin end. |
| nvx-rs/src/host/cli/sandbox/lifecycle/start.rs | Removes feature queries and handles v2 restore events. |
| nvx-rs/src/host/cli/sandbox/lifecycle/mod.rs | Removes the required-features constant. |
| nvx-rs/src/guest/managed_agent/tests/loopback/tests.rs | Exercises v2 streams while retaining v1 cap coverage. |
| nvx-rs/README.md | Documents v2 sessions and streaming CLI behavior. |
| doc/usage.md | Explains streams and cancellation. |
| doc/run.md | Updates run behavior and acceptance expectations. |
| doc/design/4.4-host-guest-control-interface.md | Describes v2 streaming, readiness, and shutdown. |
| doc/acceptance-case-matrix.md | Records the uncapped-output acceptance change. |
Review effort: Balanced
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl4-4c-nvxc-v2-host
branch
from
November 12, 2026 14:27
5999e4f to
d354235
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl4-4b-nvxc-v2-serve
branch
2 times, most recently
from
November 12, 2026 16:36
c935635 to
23bf183
Compare
Base automatically changed from
agents/slim-sl4-4b-nvxc-v2-serve
to
feature/nvx-refactor
November 12, 2026 16:55
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl4-4c-nvxc-v2-host
branch
from
November 12, 2026 17:39
d354235 to
0c20546
Compare
NVX's host spoke NVXC v1, which buffers an execution's input and caps its output, and asked the guest for FEATURES. SL4.4c (#1128) moves every host path onto v2, which SL4.4a's codec and SL4.4b's servers provide. The host's control session speaks v2 alone: every READY must carry the protocol version, and no host path sends FEATURES. PING, MAPS, capture and the restore driver's activate exchange use v2's frames, with their payloads and order unchanged. The driver ends the restored workload's standard input after its Start, and returns the live v2 session. The session streams an execution: send_stdin keeps at most the 64 KiB window unacknowledged, close_stdin ends the input, the output arrives without the old total cap, and a STOP ends an execution that runs, skipping its frames until STOPPED. `sandbox exec` and `sandbox run` stream through the session: the workload reads the command's standard input until its end, and its output reaches the command's as it arrives. Ctrl-C sends CANCEL, so that the workload does not outlive the session, and a guest's diagnostic of a refused request now precedes the CLI's error. The CLI delegates PING, MAPS and STOP to the host session, with Python's messages, and a refusal keeps the session open, so that a refused mapping still lets the start stop the guest. SL6.12's dead-code expectations on ControlSession::{ping, start_exec, cancel_exec, stop} go with their seams, since the CLI calls them. Version 1's frames, which only the servers use now, lose the cli gate. The host's FEATURES request and REQUIRED_FEATURES go with their only caller, while GuestFeatures and ExitCategory::parse stay, marked dead, for SL4.4d to delete with the rest of version 1. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The sandbox-lifecycle scenario checked that an exec which writes 2 MiB ends with status 125 and the output-limit category after at most the 1 MiB that version 1 of NVXC forwarded. NVX's host speaks version 2 now, which streams the output without a total cap (#1128), so the scenario expects all 2 MiB, status 0 and the exit category instead. Its harness test's regressions follow: a guest that still caps the output fails the exec's status, and one that loses a chunk fails the count. The case matrix's row of the scenario says what changed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl4-4c-nvxc-v2-host
branch
from
November 12, 2026 18:58
0c20546 to
d669945
Compare
Pedro Henrique Penna (ppenna)
marked this pull request as ready for review
November 12, 2026 19:00
Pedro Henrique Penna (ppenna)
merged commit Nov 12, 2026
5715bb6
into
feature/nvx-refactor
86 checks passed
Pedro Henrique Penna (ppenna)
deleted the
agents/slim-sl4-4c-nvxc-v2-host
branch
November 12, 2026 19:33
This was referenced Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Part of #1128 (SL4.4c, "NVX's host speaks v2, and the CLI streams execs"). Parent #1089, umbrella #1076.
Rebased on
feature/nvx-refactoratc0cf126efa2, into which SL4.4a (#1528) and SL4.4b (#1531) merged; it was stacked on #1531 before.What and why
SL4.4a's codec and SL4.4b's servers carry NVXC v2, but every host path still spoke v1, which buffers an execution's input and caps its output at 1 MiB, and asked the guest for
FEATURES. As SL4.4c's Scope says, this PR moves every host path onto v2, and hassandbox execandsandbox runstream through it.The host's control session (
host/session.rs) speaks v2 alone. EveryREADYmust carry the protocol version: one of another version fails withthe guest agent speaks NVXC version N, not version 2, and a frame of another protocol fails to decode. No host path sendsFEATURES.ping,capture,activateandmap_host_pathskeep their payloads, order and messages on v2's frames. An execution streams:start_execstarts it with an empty window;send_stdinsends what the 64 KiB window takes, at most one frame, andnext_exec_eventgives the window back onSTDIN_ACK(an acknowledgement of bytes never sent fails closed);close_stdinends the input;STDOUTandSTDERRarrive without a total cap; andstopworks during an execution, skipping that execution's frames, its refusal included, untilSTOPPED. SL6.12'sexpect(dead_code)markers onping,start_exec,cancel_execandstopgo, since the CLI calls all four, andfeaturesgoes with its marker, so their five seams leave the test-layout allowlist.The restore driver (
host/restore_driver.rs) keeps its order:ACTIVATEon each v2 session untilDone, thenMAPSand the Start, nowstart_execfollowed byclose_stdin, since the restored workload reads no input, as v1's null device gave it none. It returns the live v2 session, in which the CLI reads the workload's events.The CLI (
host/cli/session.rs) delegatesping,map_host_pathsandstopto the host session, with Python's messages (the guest agent …readsmanaged guest …).execstreams: a thread reads the command's standard input in frame-sized chunks, which the loop sends as the window allows, thenSTDIN_ENDonce the input ends; the workload's output reaches the command's standard output and error as it arrives; and Ctrl-C sendsCANCEL, so that the workload does not outlive the session, then ends the command with status 130 without waiting for theEXIT. A read of the standard input that fails cancels the workload and fails the command, rather than ending the input as if it were whole. While a workload streams, the transport leaves Ctrl-C to the loop, which needs the session to sendCANCEL.--timeoutstill bounds the whole exec.sandbox execandsandbox run(host/cli/sandbox/mod.rs) no longer print buffered output, and an error after the workload's output still starts a line of its own, as dosandbox run's own warnings after it (lifecycle/start.rs).start(lifecycle/start.rs) pings without asking for features, andREQUIRED_FEATURESgoes with that last caller.Version 1 stays for SL4.4d to delete, with its servers: its frames lose the
cligate, which no host code uses now, andprotocol::app'sv2gets it back.ExitCategory::parseandGuestFeatures's host side lose their last production callers, so they get dead-code markers that name SL4.4d: anexpectonparse, which takes a seam in the test-layout allowlist (protocol/app.rs: 1), and a module-levelallowinprotocol/features.rs, since which of its items the tests use differs between builds, so that no expectation holds in all of them.Docs.
nvx-rs/README.md(thenvx::protocoland control-session paragraphs,sandbox runandexec, "Guest protocol", which replaces "Guest features", the differences fromnvx.py, and the tests),doc/usage.mdanddoc/run.mddescribe the streams and Ctrl-C, anddoc/design/4.4-host-guest-control-interface.mdsays what version 2 changes: standard input, no output cap, no feature negotiation, andSTOPduring an execution.Not in this PR, as the Scope says: deleting v1,
FEATURESorGuestFeatures(SL4.4d), payload changes, a network-policy frame, concurrent executions, signal forwarding beyondCANCELandSTOP, negotiation or aFEATURESfallback, and a separate streaming subsystem.BOOT_CONTRACT_VERSIONandCONTROL_CONTRACT_REVISIONstay unchanged: neither #1076 nor #1128 asks v2 to bump them. Everything is crate-private, so the public-API snapshots don't change.Judgment calls
FEATURESrequest goes;GuestFeaturesstays. WithFEATURESsent on no host path,ControlSession::features, the CLI'sSession::featuresandREQUIRED_FEATUREShave no caller, so they go, with their tests; the type, its constants and codec, andExitCategory, stay, marked, for SL4.4d. The publicErrorCode::GuestFeaturesMissingis no longer reported; it stays, since removing it changes the public API, for SL4.4d or a later decision.STDIN_ENDfollows the Start, an endpoint that closes right after the Start can reset the stream before it read the end, so the start treats a reset or broken pipe of the restore's Start or events as a closed endpoint, and gives OpenVMM its grace to exit, as it already did for an end of the stream.a_failed_restore_ends_its_vm_and_its_launch_before_its_snapshot_goes_freecaught this on Linux.EXIT: the command ends with status 130 at once, and the guest ends the workload.startcan still stop the guest after a refused mapping, as before; transfer failures still close it.BUSYduring an execution is an invalid exec response: the exec lock keeps a second exec from reaching a guest.Size
Measured: 342 core lines by #1076's rule (366 counting regate-only lines), in 7 counted files (estimate 300 and 5; stop at 600):
host/cli/session.rs164,host/session.rs141,host/cli/sandbox/lifecycle/start.rs19,protocol/app.rs7 (theexpectonExitCategory::parse; its 9 other lines only regate),protocol/features.rs7 (theallow),host/restore_driver.rs3 andhost/cli/sandbox/mod.rs1.protocol/mod.rsandprotocol/exec.rsonly gate items by the features that use them (15 lines), andhost/cli/sandbox/lifecycle/mod.rsonly loses code, so they don't count; tests, docs, the scenario and the allowlist don't either. Seven files rather than five: two of them hold only the dead-code markers that removing the host's last v1 callers forces, which no other PR can take before this one.Validation
The gates that the orchestration checkout's
local_gates.py --filesselects for these files (the adapter gates don't exist onfeature/nvx-refactor), run from this branch's own action definitions, with Rust 1.95.0. Each row names the head that it ran at:6cd2f1944d0and5999e4facab, on SL4.4b'sbeb8611de91, the first before the CLI's read-failure and reset fixes (host/cli/session.rsandlifecycle/start.rsonly);d35423505fa, which adds only the fixes of Copilot's two threads (stopskips a refused execution'sERROR, andsandbox run's warnings start lines of their own) and their tests;0c20546b7e8, the same commits rebased on22163771b23; and this head,d66994591e9, their identical patches (bygit range-diff) onc0cf126efa2.5999e4facab:cargo fmt --all --check;cargo clippy --locked -- -D warningswith--all-targets --all-features,--lib,--lib --no-default-features,serde,--lib --binswithcliand withtesting, and forx86_64-unknown-linux-gnu--all-targets --all-features,--lib --binswithcli,testingandguest, and--lib --testswithcliand withguest5999e4facab:cargo test --locked:--all-features, the defaults,--lib --no-default-features; also--libwithclialone and withtestingalonetests/cli.rs113 and the rest of the targets; the defaults' lib 853; 246; 1144 and 2785999e4facab:RUSTDOCFLAGS="-D warnings" cargo doc --all-features;cargo +1.89 check --all-targets --all-features5999e4facab:check_test_layout.py;check_markdown_links.py;ruff checkandruff format --check;pyrightfor Linux and for Windows;python -m unittest scripts/test_microvm_tests.py; the case-matrix check (check_matrix.py … 99d2022085f)6cd2f1944d0: the same fmt, Clippy (also--all-targetswithguest,guest,testingandcli,guest), doc, MSRV,aarch64-apple-darwincheck, bundling test,public_api.py,check_test_layout.py,nvx.py check-guest-binaries --toolchain 1.95.0,build-guest-binariesandtest-guest-binaries, andcargo testwith--all-features, the defaults,--libwithout default features, withguest, withtestingand withclihangupcase gotECONNRESET, which this head treats as a closed endpoint (second judgment call)5999e4facab: the Clippy matrix above, fmt,cargo test --all-features,cargo test --lib --features cli, the layout and public-API checks; the restore tests five timestests/cli.rs123 (with the Ctrl-C test), the rest; 1129; 13 × 56cd2f1944d0: the same gates; at5999e4facab: Clippy (--all-targets --all-features,cli),cargo test --all-features, the restore tests five timescargo test --all-featuresfails the same 33guest::tests as the base,beb8611de91, which I ran in a worktree of its own there and compared by name (kernel 6.6 refuses to end a process group by pidfd); every other target passes,tests/cli.rs123 with the Ctrl-C test.guestalone and the muslcheck-guest-binariesfail 7 of those 335999e4facab:nvx.py test-microvm --backend kvm, and--backend mshv: the default suite, every scenario butsmp-lapic, with 1, 2, 4 and 8 processors. Its Alpine initramfs came fromnvx.py build-initramfs --guest alpineat5999e4facab(df66f452…on both hosts; this PR changes no guest code), with CI run 43185976865's kernel, Ubuntu distro layer, scratch template and musl OpenVMM (14dc4116ec7, this base's pin), checked by SHA-256 against their provenancesandbox-lifecycle, whoseexecstreamed all 2 MiB with anexitoutcome,managed-exec-config, proxy-only, RAM-upper, GPT-layer),managed-lifecycle(the host session on v2 against the real managed agent),vm-lifecycle, structured outcomes, workload identity, and every snapshot and restore scenario, the publicsnapshot-coreandsnapshot-tiersamong them5999e4facab:nvx.py test-microvm --backend whp: the default suite, with that initramfs (copied from MSHV), the same kernel, distro layer and scratch template, and CI run 43185976865's Windows OpenVMM, checked by SHA-256managed-lifecycleandvm-lifecyclescenarios;sandbox-lifecycle'sexecstreamed all 2 MiBd35423505fa: fmt; Clippy--all-targets --all-featuresand--lib --bins --features cli(on Windows also forx86_64-unknown-linux-gnu);cargo test --all-features --test cliand--lib host::; the new tests fail without their fixestests/cli.rs114 on Windows and 124 on Linux (with the Ctrl-C test),host::898 and 8840c20546b7e8:cargo fmt --all --check;cargo clippy --locked -- -D warningswith--all-targets --all-features,--lib,--lib --no-default-features,serde, and--lib --binswithcliand withtesting,--lib --testswithcli; forx86_64-unknown-linux-gnu, those and--all-targetswithguest,guest,testingandcli,guest; forx86_64-unknown-linux-musl, the guest binaries'--all-targetswithguest;cargo test --all-featuresandcargo test --lib --features cli;check_test_layout.py,check_markdown_links.py, the case-matrix check,ruff, andpython -m unittest scripts/test_microvm_tests.pytests/cli.rs114, the rest; 1033; the unit tests 362, after one error that three reruns didn't reproduce0c20546b7e8: fmt; the same Clippy matrix, natively;nvx.py check-guest-binaries --toolchain 1.95.0;cargo test --all-features --lib -- host:: protocol:: guest::managed_agent::tests::loopbackand--test clitests/cli.rs124, with the Ctrl-C test0c20546b7e8:cargo test --all-features --lib -- host:: protocol::and--test clitests/cli.rs124, with the Ctrl-C test0c20546b7e8:nvx.py test-microvmwith--backend kvm,mshvandwhp, the default suite, with an Alpine initramfs built at that head (caa26244…on both Linux hosts, copied to WHP),nvx-rsbuilt from that head (its provenance names that head's sources), and CI run 43263930955's kernel, Ubuntu distro layer and scratch template, at22163771b23, and OpenVMM (14dc4116ec7, unchanged), checked by SHA-256sandbox-lifecycle'sexecstreamed all 2 MiB on each. Two earlier runs don't count: the scenarios run an existingnvx-rs/target/release/nvx-rswithout rebuilding it, so a run atd35423505fa(the public sandbox scenarios,managed-lifecycleandsnapshot-coreon MSHV) and a first run at0c20546b7e8ran thenvx-rsthat the5999e4facabsuite had built; the second faileduntiered-network-policyon each host, for the--netofsnapshot capturethat SL3.7c added to the basecargo fmt --all --check;cargo clippy --locked -- -D warningswith--all-targets --all-features,--lib,--lib --no-default-features,serde,--lib --binswithcliand withtesting, and--lib --testswithcli; forx86_64-unknown-linux-gnu, those and--all-targetswithguest,guest,testingandcli,guest; forx86_64-unknown-linux-musl,--all-targetswithguest;cargo test --all-features;python -m unittest scripts/test_nvx_tools.py, the README's module-table test among them;check_test_layout.py,check_markdown_links.pyand the case-matrix checktests/cli.rs114, the rest; 536 tests, 44 skippedLeft to CI: its full matrix on this head, with the Ubuntu guest, the debug kernel and benchmarks.
Changes to existing tests
check_test_changes.py --base beb8611de91lists 131 changes: 127 to test code, 3 to an end-to-end test and 1 to test policy. Each kept test checks what it checked, through v2, unless this list says otherwise.host::session::tests(Responder,attached_recording,acknowledgement;exec_streams_events_in_order,exec_sends_the_working_directory_and_reports_its_refusal,records_that_the_protocol_does_not_allow_fail_closed,timed_out_polls_keep_partial_records,frames_travel_in_one_record_each,pings_and_stops_need_an_empty_acknowledgement, the capture, activate, mapping and mismatch tests),host::session::tests::managed_lifecycle(the exec helper ends the input after the Start),host::cli::session::tests(theGuesthelper,Recording,exec_payload; the exec, refusal, deadline, closed-endpoint and transfer tests),host::cli::snapshots::capture::tests::respond,host::restore_driver::tests(its Python peer) and the CLI's restore tests (serve).STDIN_ENDafter the Start, so their request kinds gain it and their request counts grow by one per restore (2 → 3, 4 → 6). Their guest (serve) keeps the behaviors thata_restore_that_fails_before_its_guest_is_ready_reports_its_attributionadded on the new base,unusable-rootandunreadable-report, on v2's frames.FEATUREStestsfeatures_report_what_the_guest_provides,guests_that_predate_the_features_request_provide_none,malformed_features_responses_fail_closed(host::session::tests) andfeatures_of_a_guest_that_predates_them_are_none(host::cli::session::tests), with the methods that they tested; and SL6.12's five test hooks onControlSession.output_beyond_the_guest_limit_breaks_the_protocolisexec_streams_output_past_the_old_cap, since v2 has no cap;start_requires_the_guest_features_of_layered_sandboxes(tests/cli.rs) isstarts_ask_the_guest_for_no_features, since no host path sendsFEATURES.tests/cli/lifecycle.rs(managed_execs_exit_with_the_workload_statusand itsexecutionshelper) andtests/cli/sandbox_run.rs(a_run_whose_workload_the_guest_refuses_stops_its_vm) expect the streamed diagnostic of a refused working directory or workload before the error (fourth judgment call).guest::managed_agent::tests::loopback) drives the real agent through the v2 session:control_session_broker_and_real_agent_loop_backasks for no features, streams output past 1 MiB and standard input past the window, and stops during an execution;output_limit_forwards_nothing_after_the_capkeeps checking v1's cap, on raw v1 frames, until SL4.4d.protocol::tests'frames_match_their_vectors,decoders_reject_malformed_input,record_definitions_keep_their_wire_values,frame_kind, theGuestFeatureshelpers, andhost::restore::tests::live_init) lose thecligate with the items that they test, andprotocol::app::v2::testsgains it withmod v2;protocol_violations_keep_the_messages_of_pythonloses its gate, since it needs no v1 code.sandbox-lifecycle'scheck_bounded_resultsexpects an exec that writes 2 MiB to stream all of it with status 0 and theexitcategory, where it expected v1'soutput-limitcut at 1 MiB (OUTPUT_LIMIT_BYTESandOUTPUT_CHUNK_BYTESgive way toSTREAMED_OUTPUT_BYTES); its harness test's fake and regressions follow (capped-output,short-output), and the case matrix's row says what changed.protocol/app.rs, theexpectonExitCategory::parseabove;host/session.rs's five seams go.New tests:
ready_must_carry_the_protocol_version,standard_input_keeps_at_most_the_window_unacknowledgedanda_stop_ends_the_execution_that_runs_and_skips_its_frames(host::session::tests);exec_streams_its_standard_input_under_the_window_until_its_end,ctrl_c_cancels_the_running_workloadanda_failed_read_of_the_standard_input_cancels_the_workload(host::cli::session::tests);managed_execs_stream_their_standard_input_and_output(tests/cli/lifecycle.rs),a_run_streams_its_standard_input_and_output(tests/cli/sandbox_run.rs)a_runs_warnings_start_lines_of_their_own_after_its_workloads_output(tests/cli/sandbox_run.rs) and, on Unix,interrupts::interrupting_an_exec_cancels_the_workload_that_streams(tests/cli.rs), against the fake OpenVMM.