Skip to content

protocol: add NVXC v2's frame codec beside v1 (SL4.4a) - #1528

Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
feature/nvx-refactorfrom
agents/slim-sl4-4a-nvxc-v2-codec
Nov 12, 2026
Merged

Pedro Henrique Penna (ppenna) merged 1 commit into
feature/nvx-refactorfrom
agents/slim-sl4-4a-nvxc-v2-codec

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Part of #1128 (SL4.4a, "NVXC v2's frames have a codec"). Parent #1089, umbrella #1076.

Was stacked on #1525 (SL6.12), which made NVXC crate-private, gated by the features of its users, and has merged. For its merge, this PR's commit was rebased from eda49e156dc onto feature/nvx-refactor at 1610f771002, as 927dce98446: git range-diff shows the same patch, with only a context line of the allowlist's hunk changed by the base. SL4.4b (#1531) was stacked on eda49e156dc.

What and why

NVXC v1 buffers an execution's input and caps its collected output at 1 MiB, so it cannot carry interactive or unbounded exec streams. As SL4.4a's Scope says, this PR defines version 2's complete frame codec, and its round-trip tests, in NVXC's private modules, beside v1, while every peer stays on v1. Serving v2 (SL4.4b), switching the host and the CLI (SL4.4c) and deleting v1 and FEATURES (SL4.4d) come later; no payload, wire value of v1, or restore ordering changes.

protocol::app::v2 (nvx-rs/src/protocol/app/v2.rs, new): a Frame enum, Frame::encode(request_id) and Frame::decode(bytes) -> (request_id, Frame), the Outcome of an EXIT, and the constants VERSION (2), MAX_PAYLOAD (65,512) and STDIN_WINDOW (64 KiB). A frame keeps v1's 24-byte header with version 2 (magic NVXC, version, kind, zero flags, request ID, status, payload length, little-endian), and fits one outer data record.

Kind Code From Payload
PING 0x01 Host none
EXEC 0x02 Host the EXEC payload, unchanged: arguments, working directory, environment, timeout
STOP 0x03 Host none
CANCEL 0x04 Host none, with the execution's ID
MAPS 0x06 Host the MAPS payload, unchanged
CAPTURE 0x07 Host the capture request's flag, unchanged
ACTIVATE 0x08 Host the activate request's workload identity and activation record, unchanged
STDIN 0x09 Host 1 or more bytes of the execution's standard input
STDIN_END 0x0a Host none: the explicit end of its standard input
READY 0x81 Guest the protocol version, one byte, then, in answer to ACTIVATE, ReadyActivation's canonical bytes
STDOUT / STDERR 0x82 / 0x83 Guest 1 or more bytes; no total cap
EXIT 0x84 Guest the outcome as text (exit, signal, timeout, cancelled, failed); the status is the exit status
STOPPED 0x85 Guest none
STDIN_ACK 0x86 Guest the number of bytes written into the execution's standard input, a u32 from 1 to 64 KiB
BUSY 0x87 Guest none
ERROR 0xff Guest a non-empty category; the status is the error number
  • Ready with the protocol version. READY acknowledges PING, MAPS, CAPTURE and ACTIVATE, as in v1, and always starts with the protocol version. In answer to ACTIVATE it carries what Ready reports about the activation after it, unchanged. The decoder reads any version byte, so that SL4.4c's host can check it and refuse another.
  • The payloads of v1, unchanged and in their order. EXEC, MAPS, CAPTURE and ACTIVATE carry the bytes that the existing codecs produce and read (encode_exec_payload and the guest's and fake's decoders, encode_maps_payloads and decode_*maps_payload with MAX_PAYLOAD as the limit, encode_capture_payload/decode_capture_payload, encode_activate_payload/decode_activate_payload, and ReadyActivation); the frame codec doesn't reinterpret them.
  • The stdin window is in the frames' semantics, not an engine. STDIN_ACK returns 1 to STDIN_WINDOW written bytes to the execution's window, STDIN_END ends its input explicitly, and the host never has more than STDIN_WINDOW bytes unacknowledged. The codec checks each frame's bounds; the peers keep the count (SL4.4b, SL4.4c).
  • No total output cap. STDOUT and STDERR are bounded only by the data record, and Outcome has no output limit, unlike v1's ExitCategory, which leaves with v1.
  • Strict both ways. Encoding and decoding refuse a zero request ID, an empty chunk, an acknowledgement outside 1 to 64 KiB, an empty error category and a frame larger than a data record; decoding also refuses another magic or version (with a message that names it, as for a v1 frame), unknown kinds (FEATURES, 0x05, has none in v2), a status outside EXIT and ERROR, and a payload that a kind does not allow. Every frame that decodes encodes back to its bytes.
  • Independent of v1's code. v2 uses only protocol's ProtocolError, array, violation and OUTER_MAX_PAYLOAD, and has its own magic and kind constants, so SL4.4d can delete v1 without editing it.
  • Docs. protocol::app's module docs name v2, whose module docs give the frames, their exchanges and the window; nvx-rs/README.md's nvx::protocol section says that the codec of v2's frames sits beside v1's. Its module table row is unchanged.

Not in this PR, as the Scope says: serving v2, switching any host path or the CLI, deleting v1, FEATURES or GuestFeatures, changing a payload or the restore ordering, negotiation, generations, build identifiers, conformance suites (no nvxc-v2.txt; the tests pin the bytes instead) and timing counters. BOOT_CONTRACT_VERSION and CONTROL_CONTRACT_REVISION stay unchanged: neither #1076 nor #1128 asks v2 to bump them. The codec is crate-private, so the public-API snapshots don't change.

Judgment calls, approved by the orchestrator for Pedro Henrique Penna (@ppenna)

  • Every READY carries the protocol version: it stays the success answer of PING, MAPS, CAPTURE and ACTIVATE, as in v1, so the host can check the version on every session, a restore's included, where the activate exchange takes the place of PING.
  • The decoder accepts a READY of any version, so that the host can refuse another version by name rather than as a malformed frame.
  • The kinds that v1 shares keep v1's codes; the new ones take 0x09, 0x0a, 0x86 and 0x87.
  • STDIN_ACK counts the bytes written since the previous acknowledgement, not a running total.
  • No vector file (nvxc-v2.txt), since nvx-rs slimming 5.1.1: NVXC v2 carries every control path, and streams execs #1128 excludes conformance suites; the tests pin each frame's bytes instead.

BUSY is a frame of its own, empty, rather than an ERROR with the busy category, as the Scope names it among v2's frames.

Seams

Nothing calls the codec yet, so mod v2 in protocol/app.rs is gated by the features of its eventual users, cli, testing, and guest on Linux x86-64, as SL6.12 gated NVXC, and carries #[cfg_attr(not(test), expect(dead_code, reason = "SL4.4b's guest loop and fake OpenVMM serve NVXC v2, and SL4.4c's host speaks it"))]. scripts/test-layout-allowlist.json gives nvx-rs/src/protocol/app.rs one seam for that hook.

Size

Measured: 213 core lines and 2 counted files (estimate 200 and 3; stop at 400): nvx-rs/src/protocol/app/v2.rs 200 (with its 2-line #[cfg(test)] mod tests;), nvx-rs/src/protocol/app.rs 13 (the module's declaration, gate and hook), counting the added lines that are neither blank nor comments. Tests, docs and the allowlist don't count.

Validation

The gates that local_gates.py --files selects, run from this branch's own action definitions (the adapter gates don't exist on feature/nvx-refactor), with Rust 1.95.0 and NVX_BUNDLE=skip, at f1ba8757 unless a row says otherwise. f1ba8757 sat on #1525's earlier head, 38d4409f163. Its patch, unchanged (git range-diff shows =), was rebased onto #1525's last head, 0e927f7865a, whose changes touch no protocol, README or allowlist file, as e6eeca19, on which nvx.py verify, cargo fmt --check, Clippy with all features for Windows, x86_64-unknown-linux-gnu and, with guest alone, x86_64-unknown-linux-musl, the protocol:: tests (108 passed), check_test_layout.py, check_test_changes.py and check_matrix.py passed again; and then onto feature/nvx-refactor at f03c21c3f0c, which has the same tree as 0e927f7865a, as eda49e15, whose tree is e6eeca19's. At this head, 927dce98446, on 1610f771002, these passed again: on Windows, nvx.py verify, cargo fmt --check, the Windows, x86_64-unknown-linux-gnu and x86_64-unknown-linux-musl Clippy rows below, the protocol:: tests with all features, cli and testing (108, 97 and 97 passed), check_test_layout.py, check_test_changes.py, check_markdown_links.py and check_matrix.py; on nvx-mshv-test, cargo fmt --check, the Linux Clippy row below, the v2 tests with all features, cli, testing and guest (10, 7, 7 and 7 passed), the protocol:: tests with all features (126 passed), cargo +1.89 check, public_api.py (no change) and nvx.py check-guest-binaries (musl Clippy and 1116 tests).

Where Check Result
Windows cargo fmt --all --check passed
Windows cargo clippy --locked -- -D warnings: --all-targets --all-features, --lib, --lib --no-default-features, serde alone, --lib --bins --features cli, --lib --bins --no-default-features --features testing, --lib --no-default-features --features guest, and --all-targets with cli, testing and guest alone passed, no warnings
Windows the same Clippy for x86_64-unknown-linux-gnu (all features, cli, testing and guest alone) and for x86_64-unknown-linux-musl with --no-default-features --features guest (--all-targets and --lib --bins) passed, no warnings
Windows cargo test --locked --all-features / cargo test --locked / cargo build --locked --lib --no-default-features / cargo test --locked --lib --no-default-features / --lib --features cli / --lib --no-default-features --features testing 1360 / 921 / built / 246 / 1146 / 278 passed, 0 failed
Windows RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps --all-features; cargo +1.89 check --locked --all-targets --all-features; cargo check --all-targets --all-features --target aarch64-apple-darwin passed
Windows check_test_layout.py, check_markdown_links.py, validate-nvx's python -m compileall -q scripts, python -m unittest scripts/test_*.py ..., test_adversarial.py, test_hosts.py, nvx.py test-microvm --help (at d6c766fe, whose scripts are this head's) passed: 1824 tests (73 skipped), 84 (11 skipped) and 4
Windows SL5.2's check_matrix.py against 99d2022085f passed
Linux/MSHV (nvx-mshv-test, kernel 6.18) cargo fmt --all --check; cargo clippy --locked -- -D warnings with all features, the defaults, no features, serde, cli, testing and guest alone (--lib --bins and --all-targets), cli,guest, testing,guest and cli,testing passed
Linux/MSHV cargo test --locked: --all-features, the defaults, --lib --no-default-features, --lib --features cli, --lib --no-default-features --features testing, --lib --no-default-features --features guest passed, 0 failed: with all features, the library's 2045 tests (55 ignored) and every other target; then 909 / 246 / 1132 / 281 / 1131. The first all-features run, at d6c766fe, failed tests/supervisor.rs's vmms_inherit_only_their_streams_and_allowed_descriptors_while_others_spawn once: a known race of that test, which reads the sleep child's descriptors as soon as posix_spawn returns, before its exec closes the close-on-exec pipes, and which #1507 also met at its base. It passed in 5 reruns of --test supervisor and in both later all-features runs.
Linux/MSHV the v2 tests alone with all features, cli, testing and guest: 10, 7, 7 and 7 passed (the capture and activate exchange tests need cli and guest, the workload test cli and testing) passed
Linux/MSHV cargo doc with -D warnings; cargo +1.89 check --all-targets --all-features; the bundled-artifacts test (at d6c766fe) passed (21 bundling tests)
Linux/MSHV python3 scripts/public_api.py (both snapshots) passed: no change
Linux/MSHV nvx.py check-guest-binaries --toolchain 1.95.0 (musl Clippy and 1218 tests), build-guest-binaries, test-guest-binaries passed

A code-review subagent reviewed the whole diff and found no significant issues. Left to CI: the microVM scenarios, since nothing calls the codec and no runtime path changes, and the rest of the matrix.

Changes to existing tests

python scripts/check_test_changes.py --base origin/feature/nvx-refactor reports one change to existing tests, 20 added test items, and none relocated unchanged, so this PR carries the tests-modified label:

  • Test policy: scripts/test-layout-allowlist.json loosens nvx-rs/src/protocol/app.rs from no entry to 1 seam, for the expect(dead_code) hook of mod v2 (Seams, above). SL4.4c, which gives the codec its last caller, removes the hook and the seam.
  • Added: protocol::app::v2::tests: every_frame_round_trips_in_its_wire_form, ready_round_trips_the_protocol_version, stream_frames_keep_their_bounds, malformed_frames_are_refused, the property test decoded_frames_encode_back_to_their_bytes, exec_requests_carry_their_workload_unchanged (cli and testing), exec_payloads_cross_unchanged, maps_tables_cross_unchanged_in_order, capture_requests_carry_their_flag_unchanged and the_activate_exchange_carries_its_payloads_unchanged (cli and guest), with their helpers and the table of frames.

Every old test of the area is kept unchanged: protocol::tests, v1's codec, payload and vector tests. No test is rewritten, moved or retired. The new tests are unit tests, which the case matrix doesn't inventory, and no row names a test that this PR touches.

@ppenna Pedro Henrique Penna (ppenna) added tests-modified Changes existing tests, test data, or test wiring feat-nvx-refactor labels Nov 12, 2026
@github-actions

github-actions Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 1 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 policy

Change What Before After
loosened allowlist entry nvx-rs/src/protocol/app.rs (the seams allow 1 test hooks) scripts/test-layout-allowlist.json

Relocated unchanged: 0; added: 20. Compared the merge base 1610f7710020 with 927dce984464.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The comparison includes host/store API removals and sandbox format-10 changes beyond the codec-only scope, requiring maintainer confirmation of the intended stacked base and lifecycle/cross-platform validation coverage.

No open issues 🎉

What changed in this PR

This PR’s stated goal is to introduce a private NVXC v2 frame codec alongside v1 for the streaming-control migration in #1128. The supplied changes also reflect the broader slimming workstream: making NVXC private, removing legacy stores and launch paths, and moving callers toward caller-owned VMs and CLI-owned state.

Changes:

  • Restrict NVXC and control-session access, adapting tests and examples to those boundaries.
  • Remove legacy store/template code and route retained functionality through VM and platform helpers.
  • Update CLI configuration expectations, test wiring, and documentation.
File Description
scripts/​test-layout-allowlist.json Adjusts protocol and session seam allowances.
scripts/​test_microvm_tests.py Updates format expectations and lifecycle test invocation.
scripts/​nvx_tools/​sandbox_ram_upper_tests.py Expects configuration format 10.
scripts/​nvx_tools/​sandbox_lifecycle_tests.py Updates the lifecycle test’s documented location.
scripts/​nvx_tools/​microvm_tests.py Runs managed lifecycle as a CLI-enabled unit test.
nvx-rs/​tests/​vm_lifecycle.rs Encodes minimal v1 frames without private protocol APIs.
nvx-rs/​tests/​vectors/​README.md Updates vector ownership and legacy-store documentation.
nvx-rs/​tests/​openvmm_vectors.rs Corrects documentation of excerpt consumers.
nvx-rs/​tests/​host_modules.rs Updates dependency assertions after store removal.
nvx-rs/​tests/​fixtures/​store/​runtime.json Removes a legacy runtime-record fixture.
nvx-rs/​tests/​fixtures/​store/​launch-spawned.json Removes a legacy spawned-launch fixture.
nvx-rs/​tests/​fixtures/​store/​launch-prepared.json Removes a legacy prepared-launch fixture.
nvx-rs/​tests/​fixtures/​store/​invalid/​runtime-unknown-field.json Removes an obsolete invalid-record fixture.
nvx-rs/​tests/​fixtures/​store/​invalid/​runtime-truncated.json Removes an obsolete truncated-record fixture.
nvx-rs/​tests/​fixtures/​store/​invalid/​runtime-instance-format-3.json Removes a legacy instance-format fixture.
nvx-rs/​tests/​fixtures/​store/​invalid/​runtime-format-5.json Removes an obsolete unsupported-format fixture.
nvx-rs/​tests/​fixtures/​store/​invalid/​runtime-cli-format-1.json Removes a legacy CLI-format fixture.
nvx-rs/​tests/​fixtures/​store/​invalid/​launch-without-log.json Removes an obsolete incomplete-launch fixture.
nvx-rs/​tests/​fixtures/​store/​invalid/​launch-instance-format-3.json Removes a legacy launch-format fixture.
nvx-rs/​tests/​cli/​formats.rs Tests format 10 and rejection of older configurations.
nvx-rs/​src/​testing/​fake_openvmm/​tests.rs Gates feature assertions on their dependencies.
nvx-rs/​src/​testing/​fake_openvmm.rs Removes a documentation link to private NVXC internals.
nvx-rs/​src/​protocol/​mod.rs Makes NVXC exports crate-private and feature-gated.
nvx-rs/​src/​protocol/​maps.rs Describes MAPS without linking private constants.
nvx-rs/​src/​host/​vm/​tests.rs Gates a Windows claim test on CLI support.
nvx-rs/​src/​host/​vm.rs Houses nonzero launch-capability generation.
nvx-rs/​src/​host/​vm_directory/​tests.rs Adapts permission assertions to retained helpers.
nvx-rs/​src/​host/​transport/​tests.rs Gates legacy tests and replaces store-based naming.
nvx-rs/​src/​host/​tests.rs Adds Windows test naming and gates shared helpers.
nvx-rs/​src/​host/​template/​mod.rs Removes the legacy template module.
nvx-rs/​src/​host/​template/​clone/​record.rs Removes legacy clone activation-record construction.
nvx-rs/​src/​host/​template/​clone/​launch/​tests.rs Removes a legacy clone-launch test hook.
nvx-rs/​src/​host/​sys/​mod.rs Limits rename support to CLI builds.
nvx-rs/​src/​host/​supervisor/​reattach.rs Removes store-coupled VM reattachment.
nvx-rs/​src/​host/​store/​vmm.rs Removes legacy store process-recovery helpers.
nvx-rs/​src/​host/​store/​regular.rs Removes legacy file-helper wrappers.
nvx-rs/​src/​host/​store/​names.rs Removes legacy store file-name constants.
nvx-rs/​src/​host/​store/​launch.rs Removes store-owned launch transactions.
nvx-rs/​src/​host/​spawn.rs Documents spawning without legacy store APIs.
nvx-rs/​src/​host/​snapshot/​tests.rs Uses platform file helpers and VM directory creation.
nvx-rs/​src/​host/​snapshot/​manifest.rs Removes the legacy manifest alias.
nvx-rs/​src/​host/​snapshot/​key/​tests.rs Removes legacy alias and store-identity assertions.
nvx-rs/​src/​host/​snapshot/​key.rs Removes legacy conversions, alias, and gateway accessor.
nvx-rs/​src/​host/​snapshot/​capture.rs Imports retained file helpers from platform.
nvx-rs/​src/​host/​snapshot.rs Drops the unused capture-exit re-export.
nvx-rs/​src/​host/​session/​tests/​managed_lifecycle.rs Adapts managed lifecycle to private unit-test access.
nvx-rs/​src/​host/​session/​tests.rs Registers managed lifecycle and gates dependent tests.
nvx-rs/​src/​host/​seal/​windows/​tests.rs Removes the deleted volume-path helper’s test.
nvx-rs/​src/​host/​seal/​windows.rs Removes GUID-volume path lookup.
nvx-rs/​src/​host/​seal.rs Removes the volume-path wrapper.
nvx-rs/​src/​host/​sandbox/​scratch.rs Removes an unused binding accessor and legacy link.
nvx-rs/​src/​host/​sandbox/​prepared.rs Documents process ownership through retained spawn APIs.
nvx-rs/​src/​host/​sandbox/​plan.rs Removes the legacy network DNS wrapper.
nvx-rs/​src/​host/​sandbox/​geometry.rs Removes documentation of a deleted re-export.
nvx-rs/​src/​host/​sandbox/​distro.rs Removes an unused binding accessor and legacy link.
nvx-rs/​src/​host/​runtime/​mod.rs Documents runtime identity through SavedVm verification.
nvx-rs/​src/​host/​restore/​tests/​live_init.rs Uses snapshot types and local capability generation.
nvx-rs/​src/​host/​restore/​tests.rs Gates the live-init harness on CLI support.
nvx-rs/​src/​host/​platform/​windows/​private/​tests.rs Gates CLI-only directory and rename checks.
nvx-rs/​src/​host/​platform/​windows/​mod.rs Trims exports and gates CLI-only helpers.
nvx-rs/​src/​host/​platform/​windows/​log_claim.rs Separates shared job creation from CLI claim checks.
nvx-rs/​src/​host/​platform/​windows/​endpoint/​tests.rs Uses standalone names and explicit probe deadlines.
nvx-rs/​src/​host/​platform/​windows/​endpoint.rs Removes legacy endpoint factories and probe wrapper.
nvx-rs/​src/​host/​platform/​tests.rs Tests retained private-file and directory-sync helpers.
nvx-rs/​src/​host/​platform/​other.rs Removes obsolete stubs and gates CLI helpers.
nvx-rs/​src/​host/​platform/​mod.rs Houses private-file creation, replacement, and directory syncing.
nvx-rs/​src/​host/​platform/​linux/​tests.rs Uses deadline probes and verified restore-ready reads.
nvx-rs/​src/​host/​platform/​linux/​private.rs Removes unused permission helpers and gates CLI operations.
nvx-rs/​src/​host/​platform/​linux/​mod.rs Trims exports and gates CLI-only modules.
nvx-rs/​src/​host/​platform/​linux/​endpoint.rs Removes legacy wrappers while retaining verified reads.
nvx-rs/​src/​host/​platform/​inherit.rs Makes the spawn lock crate-private.
nvx-rs/​src/​host/​mod.rs Removes legacy modules and privatizes the control session.
nvx-rs/​src/​host/​instance/​files.rs Removes legacy instance file utilities.
nvx-rs/​src/​host/​cli/​store/​tests.rs Removes compatibility tests against the deleted library store.
nvx-rs/​src/​host/​cli/​store/​mod.rs Documents the CLI store independently.
nvx-rs/​src/​host/​cli/​store/​files.rs Uses platform file operations directly.
nvx-rs/​src/​host/​cli/​snapshots/​tests.rs Uses the platform private-write helper.
nvx-rs/​src/​host/​cli/​snapshots/​capture/​tests.rs Replaces legacy store file-helper calls.
nvx-rs/​src/​host/​cli/​snapshots/​capture.rs Creates geometry files through platform.
nvx-rs/​src/​host/​cli/​snapshots.rs Uses platform syncing during snapshot publication.
nvx-rs/​src/​host/​cli/​session/​tests.rs Adapts imports and gates private-protocol dependencies.
nvx-rs/​src/​host/​cli/​sandbox/​state/​tests.rs Tests records using explicit provisioning inputs.
nvx-rs/​src/​host/​cli/​sandbox/​options.rs Builds NetworkConfig directly from validated options.
nvx-rs/​src/​host/​cli/​sandbox/​lifecycle/​tests.rs Uses the CLI-owned stop outcome.
nvx-rs/​src/​host/​cli/​sandbox/​lifecycle/​stop.rs Defines stop outcomes within the CLI.
nvx-rs/​src/​host/​cli/​sandbox/​lifecycle/​start/​tests/​restore.rs Adapts restore fixtures to direct configuration inputs.
nvx-rs/​src/​host/​cli/​sandbox/​lifecycle/​start/​tests.rs Tests share checks without legacy launch objects.
nvx-rs/​src/​host/​cli/​sandbox/​lifecycle/​mod.rs Provisions from explicit image, export, and network inputs.
nvx-rs/​src/​host/​cli/​sandbox/​lifecycle/​directory.rs Creates state directories through the CLI store.
nvx-rs/​src/​host/​cli/​run.rs Uses NetworkConfig without an intermediate conversion.
nvx-rs/​src/​guest/​sys/​tests.rs Gates capability-test exports on CLI support.
nvx-rs/​src/​guest/​sys/​spawn/​tests.rs Gates CLI-dependent test constants.
nvx-rs/​src/​guest/​managed_agent/​tests.rs Gates the host integration harness on CLI support.
nvx-rs/​src/​guest/​managed_agent/​seam/​tests.rs Gates CLI-dependent test helpers.
nvx-rs/​src/​guest/​managed_agent/​dispatch.rs Gates dispatch tests on CLI support.
nvx-rs/​src/​contract.rs Updates documentation to name SnapshotKey.
nvx-rs/​src/​activation/​tests.rs Removes tests of deleted store identity types.
nvx-rs/​src/​activation/​mod.rs Removes store identities, generations, and template references.
nvx-rs/​examples/​external-launch.rs Connects through the public verified transport.
nvx-rs/​Cargo.toml Updates the host feature’s descriptive comment.
doc/​usage.md Documents the relocated managed-lifecycle test.
doc/​run.md Documents format 10 and CLI-owned state.
doc/​project-structure.md Updates the host and test layout descriptions.
doc/​design/​5.3-snapshot-protocol.md Removes the legacy template-store deadline example.
doc/​design/​1.5-compatibility-and-versioning-model.md Describes unsupported keys without legacy store guidance.
doc/​contribute.md Updates managed-lifecycle test guidance.
doc/​ci.md Documents the CLI-enabled lifecycle unit test.
doc/​adversarial-testing.md Updates lifecycle test naming and build command.
doc/​acceptance-case-matrix.md Records relocated tests, retired doctests, and format changes.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are reported for the private v2 frame codec addition.

No open issues 🎉

Review effort: Balanced

Base automatically changed from agents/slim-sl6-12-nvxc-private to feature/nvx-refactor November 12, 2026 08:48
NVXC v1 buffers an execution's input and caps its collected output, so
it cannot carry interactive or unbounded exec streams. SL4.4a (#1128)
defines version 2's frames and their codec in NVXC's private modules,
beside v1, while every peer stays on v1: SL4.4b serves v2 in the guest
loop and the fake OpenVMM, and SL4.4c moves the host to it.

protocol::app::v2 holds a frame enum with its encoder and decoder. A
frame keeps v1's 24-byte header, with version 2, and fits one outer
data record. The host sends PING, EXEC, STOP, CANCEL, MAPS, CAPTURE,
ACTIVATE, STDIN and STDIN_END, and the guest READY, STDOUT, STDERR,
EXIT, STOPPED, STDIN_ACK, BUSY and ERROR. READY carries the protocol
version, then, in answer to ACTIVATE, what Ready reports about the
activation. EXEC, MAPS, CAPTURE and ACTIVATE carry v1's payloads, which
v1's codecs encode and decode, unchanged. STDIN_END ends an execution's
input explicitly, and STDIN_ACK returns 1 to 64 KiB of written bytes to
its 64 KiB window of unacknowledged input. STDOUT and STDERR have no
total cap, so EXIT's outcomes drop v1's output limit. FEATURES has no
kind in v2. Both directions refuse a zero request ID, an empty chunk,
an acknowledgement outside the window and an empty error category, and
the decoder also refuses another magic or version, unknown kinds, a
status outside EXIT and ERROR, and a payload that a kind does not
allow.

Nothing calls the codec yet, so its module is gated by the features of
its users, cli, testing, and guest on Linux x86-64, and carries
cfg_attr(not(test), expect(dead_code)) naming SL4.4b and SL4.4c, a test
hook for which protocol/app.rs takes one seam in the test-layout
allowlist. The codec is crate-private, so the public API doesn't
change, and BOOT_CONTRACT_VERSION and CONTROL_CONTRACT_REVISION stay as
they are.

Its tests pin each frame's bytes and round trip, the protocol version
that READY carries, the stdin window and the record's bounds, and the
refusals, v1's PING vector among them, check that every frame that
decodes encodes back to its bytes, and carry v1's EXEC, MAPS, capture
and activate payloads across v2 unchanged and in order.

Part of #1128 (SL4.4a).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat-nvx-refactor tests-modified Changes existing tests, test data, or test wiring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants