Skip to content

RTX 4080 release qualification

miniVERL has a version-controlled qualification path for the one machine on which CUDA behavior is maintainer-measured. Candidate construction runs on a GitHub-hosted runner; only CUDA qualification runs on the private runner. The workflow is manual, not continuous GPU CI and not a pull-request required check.

Two levels

v0.15 adds direct-config PPO/GRPO workflows to the existing full qualification. The installed candidate must auto-select v4, retain the upstream source bytes, use explicit runtime bindings and complete run → inspect → resume → handoff without editing native YAML. The evidence validates both repeated actor passes, PPO critic counts, exact tensor replay, the IR/rules digests and launch status.

level cadence executed scope
release smoke diagnostic use install the hosted-runner candidate wheel, verify import/CLI origin, run CLI doctor/plan/dry-run, pinned Qwen actor and teacher, one rollout/score/update, PEFT export/reload and CUDA teardown
full qualification every formal release release smoke, canonical resume workloads, rollout-backend matrix, GRPO/PPO/RM evidence and installed PPO/GRPO product workflows

The smoke budget is intentionally small and is never substituted for a frozen full workload or a scientific benchmark. Both levels record runtime correctness only. Other hardware is unmeasured; distributed verl execution is not_tested. gpu-release-smoke is diagnostic and cannot authorize a formal release. The release gate requires candidate-distributions and gpu-full-qualification from the same successful run and first attempt.

Repository contract

.github/workflows/gpu.yml runs only through workflow_dispatch. Its GitHub-hosted build-candidate job creates exactly one wheel and one sdist with the pinned build toolchain, validates them with Twine, and uploads candidate-distributions with canonical checksums and a strict manifest. The dependent [self-hosted, cuda, rtx4080, wsl2] job downloads that same-run artifact, validates it before installation, then installs the candidate wheel in a fresh virtual environment using the known-good stack. It does not build a distribution. qualification.json binds the candidate manifest, full source SHA, exact wheel hash, workflow run, profile identity, model revisions, inputs, measured environment and output hashes. It also proves that both the imported package and miniverl executable came from the qualification environment rather than a checkout or user site. For a v0.11 full run, the workflow additionally performs three real one-update profiles, all 24 preregistered cells on each rollout backend, eight policy refreshes per backend, conformance and teardown. Promotion verifies the exact source, wheel and environment bindings; speed and memory thresholds; grouped trajectory identity; reward/advantage completion; and vLLM's policy-gradient fail-closed boundary. Loose result files cannot claim the higher level.

For v0.12 and later, promotion also requires a compiled verl-rl-v0.9-single-gpu-v1 plan and two Qwen3-0.6B NF4 LoRA GRPO cycles on the exact candidate wheel. The deterministic target-length formatting reward must vary within at least one prompt group, produce nonzero advantages, commit two parameter-changing updates, remain below 14.5 GiB peak reserved memory and retain the runtime-only scientific scope.

For v0.13 and later, promotion additionally requires the v2 PPO compiler, two Qwen3-0.6B actor updates, two independent critic updates, nontrivial GAE advantages and returns, complete actor/critic checkpoints, and tensor-exact interruption/resume for both roles. The same record exercises a pinned DistilBERT sequence-classifier reward role with deterministic nonconstant scores and post-phase CPU offload, plus a locally diagnosed v0.9 handoff bundle.

For v0.14 and later, promotion also requires the installed-package PPO/GRPO walkthrough, executed from a fresh working directory outside the checkout. Both cases import packaged upstream-derived inputs, validate/plan, train, inspect/report, replay from a checkpoint, export and diagnose the handoff. The gate verifies the candidate wheel hash, compiler identity, all 25 CLI invocations, exact actor/critic/optimizer tensor replay, unduplicated records and measured VRAM. The release evidence archive contains v014/product-workflows.json with per-case rewards, losses, time, peak memory, model revisions and transcript. A dirty-tree rehearsal cannot satisfy this gate.

Every dispatch is single-use. Both jobs reject GITHUB_RUN_ATTEMPT values other than 1; if infrastructure fails, start a new workflow_dispatch instead of using GitHub's rerun button. This prevents a hosted candidate from attempt 1 being combined with GPU evidence created by attempt 2.

The release workflow queries GitHub Actions for one successful manual gpu.yml run whose repository, workflow identity and head_sha equal the release target. It accepts only the unexpired candidate and qualification from that same run, safely extracts both, and verifies the candidate manifest, API artifact digest when provided, wheel byte hash and qualification bindings. It also checks each declared evidence file's regular-file type, byte count and SHA-256. Cross-origin artifact redirects retain ordinary API headers but strip authorization, proxy authorization and cookies. It publishes the accepted wheel and sdist without rebuilding them. Future release runs retain the full qualification record, four principal workload JSON files and a deterministic subordinate-evidence archive. For v0.11, that archive also contains the three profile/backend qualification records; v0.12 adds the critic-free RL record and v0.13 adds the PPO/RM/handoff record. A committed JSON file, manual upload, fork run, different workflow or cross-run artifact pair cannot satisfy this gate.

Canonical future Release assets

The release-asset builder uses an explicit evidence-role mapping. It never derives public filenames from internal paths or appends a guessed extension. The top level is exactly:

dist/<wheel and sdist>
SHA256SUMS
candidate-manifest.json
release-verification.json
qualification.json
qualification-SHA256SUMS
qualification-release-smoke.json
qualification-direct-gkd.json
qualification-pg-k1.json
qualification-smollm2.json
qualification-evidence.tar.gz
qualification-evidence-manifest.json

The four principal workload records remain directly inspectable. Adapter configuration and safetensors, its miniVERL manifest, input prompts, run summary and version-specific qualification records live once in the deterministic archive; its manifest binds every member to its semantic role, byte count and SHA-256. SHA256SUMS covers only the wheel and sdist. qualification-SHA256SUMS covers the nine provenance and evidence assets in canonical order. Hashes prove byte integrity, not code signing or third-party endorsement.

The historical v0.10.1 assets are immutable and retain the names emitted by the original flattening step, including duplicated suffixes on some subordinate files. They are not rewritten or re-uploaded. The canonical layout applies to future releases only and does not prove distributed verl execution or hardware beyond the one measured RTX 4080.

Local validation is torch-free:

python scripts/validate_release_chain.py \
  --candidate-dir path/to/candidate \
  --candidate-manifest path/to/candidate/candidate-manifest.json \
  --qualification path/to/qualification/qualification.json \
  --commit <full-release-sha> \
  --known-good-sha256 <known-good-manifest-sha256> \
  --required-gpu-name "NVIDIA GeForce RTX 4080"

Runner setup and safety

Runner registration is an external maintainer action. Use a dedicated local account and working directory, apply the labels exactly, disable unattended access by other repository users, and allow only maintainer-dispatched jobs. The runner needs repository read access and Actions artifact download/upload; it does not need PyPI credentials or a publishing environment. Keep it offline when not qualifying a reviewed commit. Do not add pull_request or pull_request_target: model downloads and training execute repository code on the workstation. Keep the runner application and GPU driver patched, keep credentials out of the service environment, and review the exact SHA before dispatch. Prefer an ephemeral runner for one new dispatch. A rerun is not a recovery mechanism: let the runner leave, fix the cause, register a fresh runner and create a fresh dispatch.

The job deletes and recreates its qualification virtual environment, clears PYTHONPATH and PYTHONHOME, never uses an editable package, uploads only portable bounded artifacts, and checks cleanup targets remain under GITHUB_WORKSPACE. Model caches remain runner-local and are not uploaded. Rotate the runner token after suspected exposure.

The current release runner is Ubuntu under WSL2 with Python 3.12.13 and the checked known-good-rtx4080-wsl2-cu130 stack. The older Windows qualification record remains historical and cannot authorize a current release.

Measured release state

The first exact-commit full run completed for v0.10.1 on attempt 1: GPU qualification 31932226695, dry-run 31933844796 and tag publication 31934196365. Future release commits still require their own new exact-SHA, same-run, attempt-1 full qualification; the v0.10.1 record cannot authorize them. This remains a manual maintainer process, not continuous GPU CI.