Repository navigation
doc: describe only the final nvx library in a guide and the READMEs (SL6.10a) - #1555
Pedro Henrique Penna (ppenna) wants to merge 13 commits into
Conversation
SL6.7b (#1124) makes host::sandbox private to the CLI. Twelve of its items have no caller in any NVX program, only in the public API and in the module's own tests, so they would be dead once private. This change deletes them first, as SL6.6c (#1122) records: - MountAccess::from_name, MountOwner::from_name and MountKind::from_name, with their helper setting_from_name, which read a share's settings by name, as a recorded share gave them. The CLI maps the choices of --mount-owner itself and records a sandbox's export plan, not its shares' settings. - SandboxMount's accessors guest_target, access, policy, owner and kind, and absolute and absolute_policy_paths, which called absolute_with and absolute_policy_paths_with with the current directory. plan_mounts and the checks of host paths call those variants, whose docs now say what the wrappers' said, and read the fields; host_path stays for sandbox_mounts. plan_mounts' docs no longer name absolute, and say how making a host path absolute fails. - SandboxOptions::new, the options of an operation with the defaults of nvx-rs sandbox, which the CLI builds field by field instead. The tests keep what they check of the code that stays: - The share tests compare whole shares with the shares that SandboxMount::new makes, or read the fields that the mount module shows them, and make shares absolute with absolute_with and absolute_policy_paths_with and the current directory, as the deleted wrappers did. - The option tests build their options with a helper of their own, defaults, which holds what SandboxOptions::new did, and compare the shares of sandbox_mounts with whole shares, policies included. - The checks of from_name's refusals go with it: they were the only callers of what they checked. The public API snapshots lose 21 lines on each platform, the eleven public methods at both of their paths and SandboxOptions::new, and gain none. Part of #1122 (SL6.6c). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SL6.7b (#1124) makes host::network::policy and host::sandbox private to the CLI. Two of the CLI's scenario tests reached them through their public paths, which they cannot once those are private, so they drive the nvx-rs binary alone, with the same expectations: - egress_compile_prints_the_library_lowering compared what `nvx-rs egress compile` printed with the rules of compile_policy_file, and its refusals with the reader's error. It keeps every case's native rules, error code and message fragments, which the binary must print, and the grammar, model and property tests of host::network::policy check the reader's own rules and refusals. - two_share_command_line_room spells the tag of OpenVMM's virtio-fs device, `microvm`, as the lifecycle tests do, in place of MOUNT_TAG, and cold_run_expected splits a fixture's --mount and --mount-child values as OpenVMM reads them, with a helper of its own, in place of parse_mount_value: independently of the CLI's parser, as its documentation says. Part of #1124 (SL6.7b). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… CLI host::network::policy and host::sandbox were public API of nvx, although only NVX's CLI reads egress policy files and the options of nvx-rs sandbox and nvx-rs run: the policy-file reader and its limits, the rules that it compiles, the --mount syntax, the shares that it requests and their plan, the checks of the options, and the sandbox's defaults. They become crate-private where they are, gated by the features of their users, with no change of behavior: - host::network::policy becomes a pub(crate) module that only the cli feature builds, with its JSON reader, compile_policy_file, compile_policy_bytes, compile_policy and CompiledEgressPolicy, and its limits, MAX_RULES_PER_ACTION, MAX_POLICY_FILE_SIZE and MAX_JSON_DEPTH. The lowering already takes MAX_RULES directly, and the shared normalization stays public: EgressRule, Destination, PortSelector and NetworkPolicy::native_egress_rules. - host::sandbox becomes pub(crate). Its options module, with SandboxOptions, PolicyPathOption, SandboxOperation and the checks of the options, takes cli, and so do, in its mount module, the --mount syntax, SandboxMount, the mount types and limits, plan_mounts and plan_mounts_with, the checks of host paths and path_text, and, at its root, the defaults, parse_workload_identity, parse_decimal, has_kernel_separator and require_file. What the crate uses outside the CLI stays ungated: block_geometry and BlockGeometry, which host::vm and host::snapshot read, MOUNT_TAG, which a snapshot's key names, refused and os_error. - host::sandbox no longer re-exports the mount types, nor its mount module the reserved targets of protocol::share or validate_mount_target, which nothing reads at those paths once they are private. The sandbox's tests import the mount types from the mount module, and validate_mount_target through the mount module's tests, as they do validate_mount_host_paths_with. - What these users leave to the CLI takes cli too: host::artifacts::require_existing, which only require_file and the CLI's require_artifact call, and host::paths::resolve, with without_verbatim_prefix and its two tests, which only the CLI and the checks of shares call. The unit tests of host::network::policy and host::sandbox, and the two host::paths tests of resolve, take cli with their modules, so the all-features tests run them as before. The public API snapshots lose 132 lines on each platform, every path under nvx::host::sandbox and nvx::host::network::policy, and gain none. The docs of host, host::network and host::sandbox, and the doc links of openvmm_arguments, Destination and the lowering, name the reader and the profile as the CLI's; the README drops the two modules' rows and sections and holds their details in Egress policy files and Sandbox input contract. Part of #1124 (SL6.7b). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SL6.5a2 (#1125) makes the export planner crate-private and gates it with cli. Five of its items have no caller in any NVX program, only in the public API and in tests, so the warning-denied build of the cli feature would find them dead once they are private. This deletes them first, so that SL6.5a2 stays visibility-only: - resolve_guest_path, with its re-exports at nvx:: and nvx::host::filesystem::, which gave the guest path of a host path once resolved, or as spelled when it did not resolve. No NVX program translates a host path that way. guest_path, the convention itself, stays public at both paths. - Target::Convention, with its branch of resolve_mapping, which derived a mapping's target from its resolved host path, and Mapping::convention, which mapped a list's paths there. NVX's callers, nvx-rs run and the sandbox's shares, give every target. resolve_mapping takes the target that the mapping gives, and checks it as before. - ExportRequest::new, and PathList::EMPTY, which only it used. The CLI builds its requests field by field. The docs of host::filesystem and of plan say that the caller gives each target, which guest_path may derive, and the README's filesystem section follows. The tests keep what they checked of the code that stays: - host::filesystem's tests place each path of their plan helper at the guest path that guest_path derives from the resolved host path, as the convention did, with a convention helper, and build their requests directly: plain_request holds what ExportRequest::new did. - resolved_guest_paths_canonicalize_temp_directory_case_aliases retires with resolve_guest_path. On Windows, spellings_of_one_object_share_its_guest_path now takes its case, the object's whole path in capitals, that of the temporary directory included, whose guest path as spelled is not the resolved path's: it plans to the object's one child, at the resolved path's guest path. - planned_boot_shares_keep_table_sources_targets_access_and_file_kind and the security checklist build their requests directly, the checklist through a helper that takes the owner, which the_caller_owner_is_refused_on_windows sets. The public API snapshots lose 6 lines on each platform, the five items with resolve_guest_path at both of its paths, and gain none. Part of #1122 (SL6.6d). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SL6.5a2 (#1125) makes the export planner and its host rechecks private to the CLI. Two integration tests reached them through their public paths, which they cannot once those are private, so each case moves beside its owner or drives the nvx-rs binary alone, with the same assertions: - The security checklist's four checks of an export, which only the CLI plans and checks again before a start, an_export_refuses_guest_targets_that_are_not_canonical_or_that_a_root_reserves, an_export_refuses_a_read_only_path_inside_a_writable_directory, the_caller_owner_is_refused_on_windows and an_exported_object_that_a_workload_could_move_is_checked_again_before_a_start, move unchanged to the unit tests of host::filesystem, where plan_blockless plans their mappings into the blockless root, as the checklist's plan did. - cold_run_expected planned the shares of a cold-run fixture through filesystem::plan before it lowered them through the public VM contract. fixture_export now builds the fixture's ExportPlan as host::filesystem documents an export, independently of the CLI's planner, as of its parser and token renderer, so the dry-run and one-shot tests compare the CLI's command line with an export that they derive on their own. The case matrix names the moved checklist tests where they now are. Part of #1125 (SL6.5a2). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The export planner was public API of nvx, although path resolution, the protected and reserved targets, the allow, deny and write rules, aliases and the host rechecks before a start are the CLI's policy: only nvx-rs run and the sandbox's shares plan exports, and only the CLI checks a recorded export again before it starts a VM. They become crate-private where they are, gated by cli, with no change of behavior: - host::filesystem's plan, ExportRequest, Mapping, Target and PathList become pub(crate) and take cli, with the helpers that only they use: resolve_mapping, check_targets, shows, Mapped and unsupported_inspection in the module, identity and canonicalize_lenient in host_path, check_root and check_policy_paths in limits, and the resolution and checks of policy paths in policy. - ExportPlan::verify, the host recheck before each start, becomes pub(crate) and takes cli, with bound, changed_object, uninspected, loops, check_caller_roots and CALLER_OWNER_ON_WINDOWS, which only it and the planner use. The CLI keeps the identity pins, and calls verify before each launch as before. - What stays public doesn't change: ExportPlan with its children, binds, owner and identities, check, openvmm_arguments, kernel_token and guest_table, ReservedTargets, Owner, FileIdentity, the constants, and guest_path, at nvx::host::filesystem:: and nvx::. host::paths is already crate-private; resolve, which only the CLI calls, took cli in SL6.7b, and the rest serves host::vm, host::snapshot and the VM directory too, so it stays ungated. The 27 unit tests of the planner and of verify in host::filesystem take cli with their 11 helpers, so the all-features tests run them as before; the six tests of guest_path, within, outermost, the whole-volume refusal, the reserved targets and check run without it. The public API snapshots lose 20 lines on each platform, the planner's items with their fields and ExportPlan::verify, and gain none. The docs of host and host::filesystem, and those of ExportPlan and check, name the planner and the recheck as the CLI's, and the README's filesystem section and module row follow. Part of #1125 (SL6.5a2). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ExportPlan, the public description of a VM's export, combined the host
paths with the file identities that only the CLI's store needs: each
child's denied_identities, each bind's identity, and FileIdentity, with
check's rules that a recorded plan pins each object that a workload
could move. The paths are what nvx lowers; the identities are the CLI's
recheck of its own records before each start.
The CLI now owns PlannedExport { description: ExportPlan, pins: Pins },
crate-private and cli-gated beside the planner and the verifier that
SL6.5a2 made private:
- The planner returns a PlannedExport: the description, and the pins
of each child's denied paths and of each bind, in their orders,
which it computes as before. The binds keep their pins as they are
sorted.
- PlannedExport::check runs ExportPlan::check, then the pin rules that
moved out of it: a slot for each child and each of its denied paths,
one for each bind, and the identity of each denied or mapped object
strictly inside a part that the guest may write, with the same
messages. PlannedExport::verify is the old ExportPlan::verify, which
reads the identities from the pins.
- The sandbox's config.json keeps the description under export, paths
only, where CI's share checks read it, and records the pins beside it
under export_pins, as it records each image beside its binding.
Config::new requires the field and refuses an export without pins or
pins without an export as malformed; Config::check checks and
verifies the pair before vm_config passes the description to the VM.
plan_mounts, provision's ProvisionConfig and check_images carry the
PlannedExport; nvx-rs run, which launches its plan at once and never
again, keeps the description and checks no pins, as before.
nvx's public API loses FileIdentity, ExportChild::denied_identities,
Bind::identity, and ExportPlan::openvmm_arguments and kernel_token,
which only VmConfig's lowering calls and which become pub(crate);
lowering is unchanged. ExportPlan::check stays structural and needs no
identity data. host::filesystem documents what the caller keeps stable:
the launch race, the writable-part recheck and durable denials.
A configuration that an earlier build wrote has no export_pins, so a
start refuses it as "sandbox configuration has no export pins;
deprovision the sandbox and provision it again", as for every field
that the record gained before; nothing is migrated, and the format
stays 10.
Tests: the planner's and verifier's unit tests read the pins from the
PlannedExport, and narrowed_writes_pin_only_what_lies_in_writable_paths
also checks the new slot rules; ExportPlan's own tests and fixtures,
in host::config, host::vm, the restore tests and tests/cli/openvmm.rs,
build plans without identities. A new state test records an export
with its pins, reads both back, and refuses a moved, a gone and an
uninspectable pinned object at Config::check. The CLI's lifecycle
tests expect export_pins in each record, and malformed_configuration
refuses a record without it, an export without pins, and pins without
an export.
Part of #1125 (SL6.5b).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SL6.8c (#1126) makes ErrorCode and Error's constructors crate-private. Once they are, the warning-denied build of the cli feature, which builds every code of the crate that makes errors, finds three codes and one constructor that nothing makes or calls any more: only the public API and the tests named them. This deletes them first, so that the change of visibility leaves every feature set's build clean: - template-ineligible and template-tombstoned, which the template store reported until it left (SL6.2a, #1121), and sandbox-leased, which the sandbox store reported until it left (SL6.1, #1121). No NVX program reports them, so the CLI prints the same code for every error that it reports. - Error::not_found, which nothing calls. The README's and doc/usage.md's tables of the codes lose the three rows, as the test that compares the README with ErrorCode::ALL, and the test that compares the two tables, require. The public API snapshots lose 4 lines on each platform, the four items, and gain none. Part of #1126 (SL6.8c). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SL6.8c (#1126) makes Error's constructors and ErrorCode crate-private, and ErrorCode::ALL, which only tests read, goes once the warning-denied builds find it unused. Two tests reached them, which they cannot once those are private, so each keeps its assertions without them: - cold_run_expected, which projects a cold-run fixture onto the public VM contract, built nvx's Unsupported errors for the two fixtures that it cannot project. It now refuses them with errors of its own, as a caller that built nvx's errors must, and still passes on the public contract's own errors. The dry-run and one-shot tests show either only when they report an unexpected refusal. - The error module's tests list the codes themselves, in the order of the README's table, in place of ErrorCode::ALL, for codes_are_unique_lowercase_words_joined_by_hyphens and the_readme_documents_every_code_with_its_kind. They make their errors with Error::new and Error::unavailable, which every feature set builds, in place of Error::io and Error::unsupported, which only the host and guest builds will: errors_keep_their_kind_message_and_cause and codes_determine_kinds check the same kinds, codes, messages and causes. Part of #1126 (SL6.8c). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Callers act on nvx's failures by an error's kind, message and source, but ErrorCode, Error::code and Error's constructors were public: the codes, which serve the CLI's output, were part of the library's API, and any caller could fabricate nvx's errors. They become crate-private where they are, so that nvx alone makes its errors, and its public error is Error, ErrorKind and Result: - ErrorCode, with as_str and kind, and Error::code become pub(crate), and the crate root re-exports ErrorCode to the crate only, for the host and the CLI, which name it there. ErrorCode loses #[non_exhaustive], which only bound other crates, and ErrorCode::ALL, which only tests read. - Error::new, its constructor of each kind, and with_source become pub(crate), gated by the features of their callers: unsupported and io build with the host or the guest, exited, protocol, timed_out and other with the host, and new, unavailable and with_source with every feature set. - The CLI keeps its codes, and prints each error's code with the same messages and exit statuses. Most finer codes come from the CLI alone, and the CLI reads Error::code, as nvx-init and tests do, so the builds without the cli feature allow both to be unused. - Error keeps kind, message, into_parts, its display and its source, and ErrorKind its variants, as_str and its display. Their docs, and those of SnapshotKey::from_bytes and SnapshotManifest::parse, name kinds and no codes, and the docs of the CLI's hidden module no longer link the private ErrorCode. The README's Errors section describes the error by its kind, which only nvx makes, and its Error codes section the codes that the CLI prints, which the library keeps private. doc/usage.md, and a comment of the test that compares the two tables, follow. The public API snapshots lose 42 lines on each platform, ErrorCode with its variants and methods, and Error's constructors and code, and gain none. Part of #1126 (SL6.8c). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
The documented restore sequence omits skipping MAPS when no exports are configured, so following it unconditionally would fail an otherwise valid restore because encoding an empty mapping table returns an error.
1 open issue
What changed in this PR
Updates the documentation for the final public nvx library, separating its microVM mechanisms from caller-owned state and policy and NVX’s private programs.
Changes:
- Adds one library guide covering cold boot, snapshot restore, and reattachment, linked to compiled examples.
- Slims the crate README to the final public API and clarifies caller responsibilities.
- Adds library-guide and guest-agent-guideline links to the repository landing page.
| File | Description |
|---|---|
README.md |
Updates the crate description and links the library and guest-agent guides. |
nvx-rs/README.md |
Documents the final public modules and separates private implementation details. |
doc/library.md |
Introduces the three host workflows and caller-owned responsibilities. |
Review effort: Balanced
The library keeps no stores, drives no restore and applies no path or image rules any more, and nothing told a program that uses it what it owns in their place, or how its workflows go: the crate README's one example, a cold boot, was an uncompiled copy of lib.rs's, and the other workflows lived only in the compile-only host-workflows example. doc/library.md follows a host program through a cold boot, a restore from a strict snapshot, with the capture that makes one, and a reattach after the program restarts, and links each to code that CI compiles through the public API alone: the example of the crate documentation in lib.rs, cold_boot, stop, capture, restore and reattach in host-workflows, capture and activate in guest-workflows, the example of host::transport, and external-launch. It then states, in bounded lists, what the program owns in place of the removed stores, driver and policies: paths and image checks, durable state, locks, I/O, timing, recovery, outputs and process lifecycle, each checked against the rustdoc and code of host::vm, host::snapshot, host::restore, host::filesystem, host::transport and host::process. Docs only: 0 core lines, no counted files. Part of #1130 (SL6.10a). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The README still introduced the crate as the NVX mechanics and their
supervision, laid out the split platform, store and supervisor modules,
listed exec among the modules without default features, kept an
uncompiled copy of lib.rs's example, and gave modules that leave the
public API, or leave the crate, rows and long sections of their own.
It now opens with the library's mechanisms and what it leaves to its
users, links the library guide and the guest-agent guidelines, and
names NVX's programs, with NVXC and the code that only they use, as
private users of the library, whose binaries call hidden mains. Its
features come first, and its layout and module table describe the
final public modules: guest::{exec, spawn, process, cgroup, entry} are
gone; guest::{root, view, gpt}, the mapper and the application of an
activation are nvx-init's space, private to the crate, which a short
section under the guest binaries describes and the guidelines detail;
host::platform is private and host::report a module of its own; and
nvx::protocol::maps and nvx::Error gain rows. The table keeps one line
of at most 200 characters for each of its 36 modules, above the floor
of 30 that #1542 set. The module sections keep each module's contracts
and leave the rest to its rustdoc. NVXC is private and speaks version 2
alone, as SL4.4c and SL4.4d make it; library callers tell errors apart
by their kinds alone; and the Example gives way to the guide, whose
links reach compiled code.
The CLI's sections, the table of error codes, the binaries' table and
the tests stay as they were but for one stale sentence on an API
change: other documents link them, SL6.10d owns the CLI reference, and
the slices that change them keep them current. The table of error codes
keeps guest-features-missing, which a unit test of the base reads, until
SL4.4d removes it.
Docs only: 0 core lines, no counted files.
Part of #1130 (SL6.10a).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The landing page described the nvx crate as the NVX mechanics with the supervision of NVX's microVMs, and had no link for a program that runs microVMs through the library, nor for the authors of guest inits. Its note on integration and its list of usage documents now link the library guide, its crate entry describes the library and NVX's programs in it, and the guest-agent guidelines join the list. Docs only: 0 core lines, no counted files. Part of #1130 (SL6.10a). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
761fc1a to
e223dd7
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
The documentation targets several pending stacked branches rather than this snapshot, requiring maintainer verification of API and protocol claims against the integrated tree after the planned rebase.
No open issues 🎉
1 resolved since last review
Review effort: Balanced
5d18353 to
b92df2b
Compare
This pull request changes existing testsIt modifies or removes 467 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 417 more, which the job's summary lists. Relocated unchanged: 0; added: 11. Compared the merge base |

Part of #1130 (SL6.10a, "The library's guide describes only the final public library"). Parent #1090, umbrella #1076.
Stacked on #1552 (SL6.8c).
What and why
The landing page and the crate README still presented
nvxas "the NVX mechanics" with the supervision of NVX's microVMs, laid out the split platform, store and supervisor modules, listedexecamong the modules without default features, kept an uncompiled copy oflib.rs's example, and gave modules that leave the public API, or the crate, rows and long sections of their own. Nothing told a program that uses the library what it owns now that the library keeps no stores, drives no restore and applies no path or image rules. This PR does SL6.10a's Scope and no more, and writes for the final public library: the stack below it (SL6.6c, SL6.7b, SL6.6d, SL6.5a2, SL6.5b, SL6.8c), the tip offeature/nvx-refactor(SL6.11b #1542, SL6.14, SL4.4b), and the slices that merge before it, SL6.11d (#1547), SL6.13b (#1548), SL4.4c (#1541) and SL4.4d (#1545). Each statement was checked against the code of this branch and, where it concerns those slices, against their branches.doc/library.md(new, the one guide): a host program's three workflows, each linked to code that CI compiles through the public API alone rather than a copy of it:vm::create_private_dir,VmDir::open,vm::create,vm::spawn(orPrepared::into_commandfor a launcher of the caller's own),transport::connect_verifiedandHostConnection::attach,vm::stop. Linked: the example of the crate documentation innvx-rs/src/lib.rs(a rustdoc test),cold_bootandstopinnvx-rs/examples/host-workflows.rs(compile-only), andexternal-launch.finish_capture,Snapshot::open, the caller's per-snapshot lock on Linux,vm::create(.., Some(&snapshot), ..),Prepared::activation_record, aRestoreMachinethat the program drives with its own I/O, and the guest'sActivation. Linked:captureandrestoreinhost-workflows,captureandactivateinguest-workflows.SavedVm,vm::reattach,vm::verify,RuntimeMismatch. Linked:reattachinhost-workflows, and the rustdoc test ofhost::transport.host::{vm, snapshot, restore, filesystem, transport, process}(for example the Linux per-snapshot lock, the Windows spawn's inheritance window andwindows_breakaway,ExportPlan's paths-only race and rechecks,RestoreError's attribution,StillRunning).nvx-rs/README.md, slimmed to the final public library:mains. Features come first (execgone).guest::{exec, spawn, process, cgroup, entry}are gone;guest::{root, view, gpt}, the mapper and an activation's application are nvx-init's space, private to the crate, which a shortnvx-init's spacesection under the guest binaries describes and the guidelines detail;host::platformis private andhost::reporta module of its own;nvx::protocol::mapsandnvx::Errorgain rows. The table keeps the convention of.github/copilot-instructions.md: 36 rows, each one line of at most 200 characters that links its section after the table, above the floor of 30 that guest: delete the process modules and cgroups (SL6.11b) #1542 set (test_readme_gives_each_module_a_short_row_and_a_section). It lists no private module.nvx::protocolsays that NVXC is private and speaks version 2 alone, as SL4.4c and SL4.4d make it;ExportPlanholds paths only;nvx::Errorhas no public codes or constructors, and library callers tell errors apart by their kinds alone (the old text also had them match message fragments, whichError's rustdoc reserves to the CLI's callers). The uncompiled Example gives way to the guide.doc/usage.md,doc/ci.md,doc/contribute.md, the repository instructions) and the slices that change them keep them current: the CLI's sections (Egress policy files through Scenario tests), the table of error codes, the binaries' table and Testing; only a stale sentence on an API change of the now-privatehost::sandboxgoes. The table of error codes keepsguest-features-missing, whicherror::tests::the_readme_documents_every_code_with_its_kindreads at this base, until SL4.4d's own commit removes it, and theUnavailablekind's meaning already reads as SL4.4d leaves it.README.md: the landing page's note on integration and its usage list link the guide, its crate entry describes the library and NVX's programs in it, and the guest-agent guidelines join the list. No other root section changes.Rebase at my turn. The README conflicts with the tip, SL6.13b, SL4.4c and SL4.4d's README edits; I will keep this structure, take their changes to the sections kept above, and check every statement again against the rebased code. At this stack base, whose test still has the floor of 40,
test_readme_gives_each_module_a_short_row_and_a_sectionfails (36 rows): it passes on the tip's floor of 30, which the rebase brings.Case matrix. No test changes. Its Docs row for the README's Example already records the fate (rewritten; "the library's guide (SL6.10a) replaces the example"), so no row changes.
Not in this PR, per #1130: CLI reference material (SL6.10d), design pages (SL6.10b, SL6.10c), other guides or a cookbook, build and CI docs (SL6.10e, SL6.10f), the rustdoc (SL6.10g), the migration guide (SL6.10h), and examples beyond cold boot, restore and reattach.
Size. 0 core lines and 0 counted files (estimate 0): two READMEs and one new guide.
BOOT_CONTRACT_VERSION,CONTROL_CONTRACT_REVISIONand the public API are unchanged.Validation
local_gates.py(dev's) selects markdown-links, test-layout, test-changes, thenvx-rschecks and validate-nvx for these files; the ones that the change affects ran from this branch's action definitions, on Windows, at761fc1a1338; the later fold of Copilot's finding changed only prose, after which the link check ran again:python scripts/check_markdown_links.py, at each of the three commits (git rebase --exec)python scripts/check_test_layout.pypython scripts/check_test_changes.py --base origin/agents/slim-sl6-8c-error-codes-privatecargo test --locked --lib --manifest-path nvx-rs/Cargo.toml -- error::tests(reads the README's error codes throughinclude_str!)compilealland the unittest listcompileallpassed; 1803 tests, all passed but the expectedtest_readme_gives_each_module_a_short_row_and_a_section: 36 rows against this base's floor of 40, which the tip's floor of 30 replacesguest-agent-guidelines.md#ownership,#build-the-space,#the-hosts-mapping-table,ci.md#cratesio-releases,run.md#run-openvmm-directly), on the tip, SL6.13b and SL6.10c/e/f's branchesnvx-rs/src, the examples, the public-API snapshots and the pending branches. Its five findings are folded: a VM outlives its program on Windows only withwindows_breakawaywhen the program runs in a job;vm::stopreturns the report's read apart from the exit;KeyIdentitydigests the key's compatibility prefix;bytes_readcounts reaped children on Linux; library callers classify errors by kind alone. Copilot's finding is folded too: the program sends the mapping table only when it holds a mapping, sinceencode_maps_payloadsrefuses an empty onenvx-rs/README.mdis not the crate's documentation (lib.rsdoesn't include it), so no doc test orcargo docoutput changes, and nothing here is guest-gated: no Linux host, build or microVM run.