# RVBox implementation test workflow All Go, protobuf, and harness work runs in the pinned toolchain container. No host Go installation is used. Run the normal pre-commit gate with: ```sh make verify ``` Run focused unit tests with: ```sh scripts/test-unit --package ./internal/domain --run UUIDv7 --race ``` Build all supported binaries without installing `make` or Go on the host: ```sh scripts/build build ``` For a native Windows run, create the immutable per-run test bundle with the pinned toolchain. Supply a test-specific config whose endpoint and CA path are valid for that run; the command refuses to replace an existing bundle. ```sh scripts/windows/build-test-bundle \ --run-id windows-smoke \ --config .test-runs/windows-smoke/client.toml \ --ca .test-runs/windows-smoke/ca.pem scripts/windows/test-host prepare --run-id windows-smoke scripts/windows/test-host stage --run-id windows-smoke \ --bundle .test-runs/windows-smoke/windows-bundle ``` The bundle manifest records the source commit and SHA-256 of every bundled file. It is a test artifact, not a signed release package; release signing, version resources, and publication are Phase 8 gates. The integration harness provides the Phase 0 `sample` suite, the incremental Phase 2 `store` suite, and the incremental Phase 3 `server-session` suite. The resumable E2E harness adds `smoke`, `script`, `recovery`, and `all` scenarios. Each run writes its manifest and run ID before starting work. The storage suite uses a real temporary SQLite database in WAL mode and a real segment/audit filesystem. The session suite uses a real HTTP/WebSocket listener, binary protobuf frames, SQLite fencing, and the race detector; neither mocks its respective durability or wire boundary: ```sh scripts/test-env doctor scripts/test-integration --suite sample --run-id my-sample scripts/test-env status --run-id my-sample scripts/test-env collect --run-id my-sample scripts/test-env reset --run-id my-sample scripts/test-env reuse --run-id my-sample scripts/test-integration --suite sample --run-id my-sample --resume scripts/test-env reset --run-id my-sample scripts/test-env purge --run-id my-sample scripts/test-integration --suite store --run-id store-smoke scripts/test-env logs --run-id store-smoke scripts/test-env collect --run-id store-smoke scripts/test-env reset --run-id store-smoke scripts/test-env purge --run-id store-smoke scripts/test-integration --suite server-session --run-id session-smoke scripts/test-env logs --run-id session-smoke scripts/test-env collect --run-id session-smoke scripts/test-env reset --run-id session-smoke scripts/test-env purge --run-id session-smoke scripts/test-e2e --scenario smoke --run-id e2e-smoke scripts/test-env status --run-id e2e-smoke scripts/test-env recover --run-id e2e-smoke scripts/test-e2e --scenario smoke --run-id e2e-smoke --resume scripts/test-env reset --run-id e2e-smoke scripts/test-env purge --run-id e2e-smoke ``` The client runtime unit lane also exercises a real child process through the portable supervisor adapter. `internal/client/agent/executor_test.go` verifies that command text is accepted once, output is journaled, lifecycle/terminal events are durable, and a script cannot launch before its contiguous upload is committed. The Windows build uses the same executor contract with the platform-native adapter: a verified token is selected, the child is created suspended, assigned to a kill-on-close Job, and held behind an authenticated per-command launcher pipe. The daemon records `launch_prepared`, then the durable `launch_authorized` transition sends the launcher's release frame; the launcher resumes the shell only after that acknowledgement. The durable `launch_phase` barrier is recovered as `interrupted` after a daemon restart, so an uncertain release is never redispatched. The Windows artifact is linked with the GUI subsystem (`-H=windowsgui`) so service, launcher, and tray startup do not flash a console. Human-facing modes still attach to a parent console explicitly when one exists. Suite output is capped at 1 MiB and stored as `artifacts/suite.log`. A failed run remains inspectable and can be moved back to `ready` with `recover`, then resumed with the same run ID and deterministic shuffle seed. Test-run cleanup never removes the shared Go module or build-cache volumes. Each run owns only `.test-runs/` and resources explicitly recorded in that run's versioned manifest. The journal is append-only and fsynced. `purge` validates the run ID and manifest identity, refuses symlink targets or manifests that still list runtime resources, and then removes only that exact run. Purged artifacts are not recoverable. Dependency cache volumes are never part of run cleanup. `test/coverage.toml` is the incremental requirement-to-test inventory. The `make verify` lint stage checks unique stable IDs and verifies every implemented test reference against source. A resettable Windows smoke VM is now available. The authoritative fixture record is [testing-vm.md](testing-vm.md): it lists the VM/host UUIDs, Windows build, hardware and device profile, NAT and VRDE endpoints, snapshot UUIDs, credential-file contract, and the required reset sequence. At the last check the VM was powered off with `baseline-disk-first` selected. The guest address `10.0.2.15` is DHCP state only; use SSH plus VirtualBox Guest Control rather than treating it as a stable endpoint. VRDE is enabled at `192.168.50.162:3389` for diagnostics, while native Windows RDP is disabled in the baseline. The canonical headless VirtualBox/Guest Control adapter is `scripts/windows/test-host`. It is a POSIX controller script because the fixture's VirtualBox host is Arch Linux and has no PowerShell runtime. The controller connects to Helium over SSH; `VBoxManage` and the host-only password file never need to exist on the Linux development controller. It takes the VM identity, baseline snapshot, guest identity, and password-file only from host environment variables, acquires an exclusive remote lease, and never writes secrets to the repository, run manifest, or command line. Set `RVBOX_TEST_GUEST_PASSWORD_FILE` to the mode-600 host-side file; the adapter passes it only as VirtualBox `--passwordfile`. The provisioned fixture's non-secret identity values, including the host-local password-file path, are safe defaults in that script and may be overridden for another documented fixture; the password itself is never embedded. The native lifecycle is `status`, `prepare`, `stage`, `run`, `collect`, `stop`, and `reset`. `prepare` verifies the VM and snapshot UUIDs, restores the baseline, starts headless, waits for Guest Additions, and records the selected login fixture. `stage` copies a versioned non-secret test bundle through a run-specific host directory to a run-specific guest directory. `run` starts the real RVBox SCM service and observes it through SCM, the local health/tray pipe, durable artifacts, and the test agent endpoint; it must not invoke the GUI-subsystem `rvbox.exe` directly through Guest Control. `collect` obtains only bounded/redacted artifacts, and `reset` restores the exact baseline and leaves the VM powered off. This service-driven protocol is required because VirtualBox Guest Control 7.2.16 does not reliably complete a direct GUI-subsystem `rvbox.exe` run; wrapping it in `cmd.exe` can leave the Guest Control wrapper waiting. Guest Control is therefore limited to console-safe setup tools (`sc.exe`, `whoami`, `query`, bounded file operations) and artifact collection. A native E2E run also performs a bounded guest-to-nginx HTTPS/TCP readiness probe before it starts the service. Wine and protocol stubs are not equivalent Windows coverage. The fixture needs a one-time operator-approved service bootstrap before the SCM smoke lane can run: Guest Control supplies the split-token administrator's medium UAC token, so it cannot safely install services. The bootstrap installs the test service in the reset baseline and grants the test account only the SCM query/change-config/start/stop rights plus access to its dedicated test subtree. Each run then reconfigures and starts that one service. This does not add a product broker or use Task Scheduler; it is fixture setup. See [testing-vm.md](testing-vm.md) for the exact boundary. The VM is the minimum smoke lane, so native multi-session/ambiguous-session, Server Core, and older-build entries remain explicitly blocked until their own fixtures exist. Their pure selector tests remain mandatory.