Environment & assets
August 23, 2026 · View on GitHub
This file is a factual registry of known development and gate environments. It
does not authorize connecting to a host, managing its services, using its
credentials, or assuming its paths exist. The untracked
developer-preferences.md selects which entries are available in the current
workspace and supplies local path/lock overrides. If no profile is selected,
use only the current local host and mark unavailable hardware gates PENDING.
Reaching a GPU: claim a lease, never ssh
The shared GPUs are managed by
resource-controller, whose
client is rc. Claim a device with rc run or rc hold before any GPU work,
and never ssh to a GPU box to run work directly. A bypass makes the fleet
report the box free while somebody is on it, which is the exact failure the
lease exists to remove. The procedure is in the leasing-a-gpu skill, which
this repository deliberately does not copy, because a copy goes stale without
saying so.
AGENTS.md §Work on a GPU happens inside a lease holds the rule, and its
condition is the DEVICE rather than the shell you are typing in. dgx:gpu0,
thor:gpu0 and orin:gpu0 are the fleet devices, so a lease is the required
path to each of them and it replaces the file mutex as the default. The three
names are listed in both files so that membership stays checkable when the
client is not at hand, and they are a lower bound rather than an upper one: a
device that rc devices reports is a fleet device even when this list has not
caught up. On a GPU that is not one of them, take
${GPU_LOCK:-$HOME/gpu.lock} as before.
rc devices lists the fleet when your shell has the client AND the controller
answers, so it reports your access and not the device's membership. It fails in
at least three ways that a reader must not collapse into one: command not found means this shell lacks the client, and a timeout or a refused
authentication means the controller is not answering. thor:gpu0 read unknown (no contact 1m0s) on 2026-08-17, so lost contact is a live state. On a fleet
device every one of those answers means get the client or report the controller
down. None of them means take the file mutex over ssh, because that is the
collision below, in which two mutexes could not see each other.
This REPLACED the ssh <host> plus flock mechanism that the profiles later
in this file still describe. Read a historical recipe as evidence of what ran
at the time, not as an instruction for what to run now.
"The file mutex is still real and still required" is the stale half of this
paragraph, and the Jetson Thor profile below now contradicts it. On a FLEET
device the lease IS the mutex — rc hands the whole device to one job — so a
job that also takes ${GPU_LOCK} serialises against nobody. That profile
deletes the flock wrapper from its recipe for exactly that reason. The file
mutex stays real and required on a GPU that is NOT a fleet device, which is the
conditional form AGENTS.md states, and where both apply it runs inside the
lease rather than instead of one.
The bypass has already voided a measurement, so this is a measured cost and
not a rule for its own sake. .agents/specs/minimax-music3.md §13.10 records
a whole speed axis retained as VOID on 2026-08-17: those runs went in by ssh
plus docker run serialised by the old mutex, while a concurrent session held
the SAME box through rc. The two sessions took different mutexes and neither
excluded the other, which is verbatim the #777 failure, and it is the likely
cause of a 3x swing in the samples. .agents/benchmark-record.md records the
other half of that row taking a real rc hold on thor:gpu0 and reports the
window in which the fleet showed thor:gpu0 FREE while it was in use.
The fleet, read from rc devices and rc describe on 2026-08-17:
| Device | Labels | /workspace on it |
|---|---|---|
dgx:gpu0 | gpu_model=GB10, class=train, k8s=true, driver 580.173.02, cpus=20, 128 GB | the house NAS |
thor:gpu0 | gpu_model=NVIDIA-Thor, class=train, k8s=true, driver 595.78, cpus=14, 132 GB | the house NAS, the SAME folder as dgx |
orin:gpu0 | gpu_model=AGX-Orin, class=train, k8s=true, cpus=12, 32 GB, and NO detected GPU labels because Jetson carries no nvidia-smi | LOCAL disk, invisible from dgx and thor |
Select on class or gpu_model, never on vram. rc describe reports
vram=[N/A]M and vram_free=[N/A]M on this fleet. That is a probe reporting
"unknown", not a value, so a selector such as vram>=40G matches nothing and
the job is rejected with no_matching_device. A device that carries no label
never matches, INCLUDING for !=, and orin:gpu0 carries no detected GPU
labels at all. class=train and gpu_model=GB10 do match. rc run has no
--image flag. Its flags are --as, --cwd, -d, --explain,
--idle-timeout, --max-runtime, --no-wait, --priority, --select and
--timeout.
What the dgx:gpu0 leased worker can and cannot do, measured 2026-08-17
Probed with one rc run -d dgx:gpu0 --max-runtime 2m job
(ff28ada1-0cd3-4867-bf9b-f67050d0608b). Verify this again before you plan work
around it, because the worker image can change under you. It did change. The
thor:gpu0 worker measured later the same day carries python3 and gcc, which
this list calls absent, so read this section as one box on one day. The thor
reading is in "A relocated CUDA runtime starts on thor:gpu0" further down.
The dgx:gpu0 worker then changed as well, so read the whole section as
history and take the toolchain from
#1213.
- The command runs as user
rcin a k3s pod, hostnamerc-worker-<id>./.dockerenvis absent and 8KUBERNETES_*variables are set, so it is a pod rather than a docker container. The toolchain question is therefore a worker-image question, not a per-job one. - Present:
bash,sh,ls,nvidia-smi(which reports the GB10 by UUID),flock, and/workspace. - Absent on 2026-08-17:
gcc,cc,clang,nvcc,ninja,cmake,make,python3,python,pip,docker,sudo,git,ssh,curl,/usr/include/stdio.h, and any/usr/local/cuda*toolkit. That probe read the worker as unable to compile, to start Python, or to install anything. That reading is SUPERSEDED.rc describe dgx:gpu0now states that the job runs as root in an Ubuntu 24.04 container carryinggit,curl,wget,ssh,gcc,g++,make,cmake,ninja,pkg-config,python3,pipandvenv, and it instructs the reader to install anything missing. The one limit the sheet names is the CUDA toolkit, which a job apt-installs per run (#1213). Do not carry a one-box reading to another device either. Onthor:gpu0the same day the worker ran asuid=0(root)with/usr/bin/gcc,/usr/bin/python3and a workingapt-get(#1146). - The host filesystem is not visible.
/home/mudlerdoes not exist inside the worker. /workspaceis the house NAS, measured as//192.168.68.102/Data 7.3T total, 4.0T available, 46% used, writable from the job, mounted on the dgx host at/usr/local/nas_share/rc(SMB, NodePort 31516, subfolderrc/). It is the SAME folder fromdgxand fromthor, and it is the one surface both ends can see. It is NOT shared withorin.
The consequence, and it is now narrower than a blocker. The pinned oracle
venv lives at ~/venvs/vllm-oracle-pin-555967922 on the dgx HOST, and a leased
worker cannot see it. The dgx host has carried no toolchain since the 2026-08-14
reimage, so host-side oracle work needs sudo -n docker run against
vllmcpp-build:gb10 or nvidia/cuda:13.0.1-devel-ubuntu24.04, reached over
ssh, which is the bypass. The sentence this paragraph used to carry, "no
vLLM leg of any row can currently run on dgx.casa by a lease-compliant path",
is FALSIFIED, for the BUILD step and for a MODEL RUN alike. On 2026-08-18
two rc run jobs built the pin from source inside a lease, installed the wheel,
imported it, and reported cuda True NVIDIA GB10
(#1185, and "The pinned oracle
builds inside a lease on dgx:gpu0" further down). On 2026-08-19 the same pin
then SERVED: vllm serve on a 52 GiB bf16 checkpoint, from a lease, no ssh and
no container image, three clean benchmark legs (.agents/benchmark-record.md,
BENCH-QWEN38-27B-BF16 c1, and "A model DOES run inside a lease" below). So
oracle-side MEASUREMENT from a lease is no longer blocked; what is still
unreachable is the image-based path SGLang needs
(#1265). Read the old reason
carefully before you quote it, because it was never the worker's missing
toolchain. "The lease carries bytes, and the exec bit is a mount option" below
measures staged content starting under the dynamic loader and after a copy to
/tmp. That is why recent GPU work reached for ssh, and the bypass is a
symptom of this gap rather than a discipline problem. Do not design the
migration here. ENV-LEASE-RUNTIME-STAGING owns the runtime staging, and
lease-runtime-staging.md holds its working
recipe for torch and triton. ENV-ORACLE-WHEEL-IN-LEASE owns the oracle
build, in oracle-wheel-in-lease.md.
This confirms and extends a finding that already landed, rather than making a
new one. .agents/specs/minimax-music3.md §13.10 probed thor's worker on
2026-08-17 and found the same absence (no gcc / g++ / cmake / ninja / nvcc / make), reported that the $HOME build tree is not mounted inside the worker,
and named what a valid re-measurement needs: either a worker image carrying the
CUDA devel toolchain, or the build placed on /workspace by something that
already has one. This row measured dgx's worker and adds the part that turns
an open gap into a blocker for the parity gates, which is that the ORACLE VENV
is also unreachable from a lease.
Clock pinning does NOT work inside an rc lease, measured 2026-08-19
#1354 owns this.
nvidia-smi -lgc is refused inside the leased worker, in a job running as
root:
$ nvidia-smi -lgc 2190
The current user does not have permission to change clocks for GPU 0000000F:01:00.0.
LGC_RC=4
Reproduced in three separate rc run jobs on dgx:gpu0 on 2026-08-19
(.agents/benchmark-record.md, BENCH-QWEN38-27B-BF16 c1/c8). The container is
root but lacks the capability the driver requires.
This outlives one campaign, and it is a records defect as much as a capability
one. benchmarking.md instructs "Pin the clocks before
measuring, under the lock", and every clock-pinned figure in this
repository's records was taken over the retired host + ssh + flock path.
The migration to rc leases silently removed clock pinning and no record said
so. Same class as #1265: a
capability the records assume, which the current access path does not provide.
Consequence for anyone measuring from a lease. The SM clock can only be
SAMPLED, never pinned. tools/bench/gpu_clock_state.py still works and is the
only attribution such a number carries. Plan for its within-run rule to fail:
the 2026-08-19 series recorded within-run spreads of 12.92% to 26.36% across
nine windows on a thermally throttling GB10, against the 5% ceiling, and
gpu_clock_state compare therefore returned PAIRING_VERDICT=DISCARD on every
c1 pairing even though the cross-arm rule passed perfectly. Two arms measured in
a lease may not be dividable, so budget for absolutes and say so in advance
rather than discovering it after the GPU time is spent.
The missing capability is CAP_SYS_ADMIN, and it is missing from the BOUNDING
set. Measured 2026-08-21 inside leases on thor:gpu0 and orin:gpu0.
/proc/self/status in the worker reads CapEff = CapPrm = CapBnd = 0x00000000a80425fb on both boxes, byte-identical -- the default 14-capability
OCI set, which holds neither CAP_SYS_ADMIN nor CAP_PERFMON nor
CAP_SYS_NICE. Those three are the whole Linux privilege surface of the NVIDIA
open kernel module: at tag 580.173.02, grep -n 'capable(\|CAP_' over
kernel-open/common/inc/nv-linux.h and kernel-open/nvidia/os-interface.c
returns NV_IS_SUSER() == capable(CAP_SYS_ADMIN) at nv-linux.h:537,
capable(CAP_PERFMON) at os-interface.c:390, and capable(CAP_SYS_NICE) at
os-interface.c:397, and nothing else. CapBnd is why no job can route around
it: a capability absent from the bounding set cannot be regained by setcap,
by a setuid binary, or by re-execing, so this is container configuration and not
job authorship. thor:gpu0 reproduced the refusal itself on driver 595.78
(LGC_RC=4), so the refusal is measured on two boxes and two driver versions.
/proc/driver/nvidia/params reads RmProfilingAdminOnly: 1 in the lease, which
governs PROFILING COUNTERS and is a different gate -- do not reach for an NVreg
knob expecting -lgc to start working. The ask, the acceptance test that
falsifies it, and the cost are in
lease-gpu-capability.md.
Clock pinning DOES work from the leased HOST, and the pod path is still
refused. Measured 2026-08-21. Under an rc hold lease on dgx:gpu0, over
ssh to the host, sudo -n nvidia-smi -pm 1 then -lgc 2100 held 0.29%
SM-clock spread over a ten-minute decode load (120 samples, min 2080, max 2086),
against the 12.92%-26.36% the unpinned windows above recorded. That path needs
an authorization most rows do not have: .agents/developer-preferences.md
scopes rc hold plus ssh to the BENCH-QWEN38-27B-SOTA campaign and leaves
the standing rule unchanged for every other row. So a ratio is derivable on that
box by that path, and the pod path -- the only path for every other row -- still
returns LGC_RC=4. Two caveats travel with the host path: persistence mode had
to be enabled first, and it can be lost when the last GPU client detaches, so
verify the clock DURING the run and never only before it; and the recorded
-lgc 2100 recipe is about 69% of this device's 3003 MHz maximum SM clock, which
is right for a RATIO and wrong for an ABSOLUTE.
nvidia-smi -pm 1 DOES work inside the pod, and it is a DIFFERENT knob from
-lgc. Measured 2026-08-22 on dgx:gpu0. The SPEC-DFLASH2 speed gate (job
ec9cf6cd-0aaf-4323-806d-6a12da2bd08f) found persistence_mode: Disabled when
it opened, because the box had rebooted — boot_id moved from db4ca4f3-... to
302145bc-4c57-4f78-803c-f9d644a24b9d — and a reboot resets the driver setting.
The job ran nvidia-smi -pm 1 INSIDE the lease, as a normal leased job with no
ssh and no host access, and it SUCCEEDED: "Enabled persistence mode via daemon
for GPU 0000000F:01:00.0." Both arms then sampled persistence_mode: Enabled.
-lgc in the same job still returns 4, so this does not weaken #1354 and does
not make clock pinning reachable; the two are separate driver operations and
only one of them is refused.
Why this matters enough to write down: without it the lease produces
NOTHING. gpu_clock_state.clock_reasons appends a refusal for any record
whose persistence_mode is not Enabled, so both arms of a two-hour paired
measurement would have been discarded on a setting one command fixes. Read
persistence mode at the START of a leased measurement and set it if it is off,
rather than discovering it in the refusal. Evidence:
/mnt/nas_share/rc/dflash2-1673/out-n1673b/m-pm.log and the DEVICE STATE
paragraph of /mnt/nas_share/rc/dflash2-1673/RUN-PROVENANCE.txt.
A settle-and-hold procedure CAN reach the clock gate on this box, and what
controls it is the window's REQUEST COUNT. Measured 2026-08-23 on dgx:gpu0.
Without any pin, a window holding one request of 1024 input and 950 output
tokens cleared the 5% spread rule and the throttle rule together in 2 of 3
attempts. A window holding six requests of 1024 input and 128 output tokens
cleared them in 0 of 3. Each request carries one SM-clock excursion about 3.6 s
after its own start, and the excursion carries a non-benign throttle bit with
probability 0.476, so a window's chance of being clean falls as (1-p)^requests.
Heat is not the discriminator: the labelled-sample rate is flat at 0.9-1.0 per
minute over the last three quarters of the job, whose busy rows span 69 C to
85 C.
No pairing was established, because a pairing needs both arms clean and
because that run never set persistence mode. Two traps travel with it. The job's
own thermal summary printed every 63rd row and therefore showed 0 of the 34
throttle-labelled rows, a 77 C maximum against the true 85 C and a 43.9 W
maximum against the true 81.1 W, so read thermal.csv and never the summary
printed from it. And a window shaped to satisfy the gate measures a different
workload than the one a ratio owes. Evidence and derivation:
specs/clock-gate-route.md §The 2026-08-23 settle
run, raw files at /mnt/nas_share/rc/clk1354/out/settle-20260823T004328Z/.
A model DOES run inside a lease. The same series ran the pinned oracle
0.1.dev1+g555967922 as a server on a 52 GiB bf16 checkpoint from a lease, no
ssh and no container image, and it served three clean benchmark legs. That
retires the "nobody has run a model that way" reading of
#1185 recorded above. What is
still unreachable is the image-based path SGLang used
(#1265). A wheel route around
it is specified by row SGLANG-ORACLE-LEASE-WHEEL in
sglang-wheel-in-lease.md, which needs no
source build and no image. That route is specified and NOT run, so the SGLang
oracle stays gateable = no.
And one instrument rule, paid for in the same series. A guard whose
threshold sits inside the guarded configuration's own operating point
manufactures the finding it was meant to detect. A 12,000 MB MemAvailable
watchdog killed a healthy vllm serve 18 s after it reached /health, which
read as "the denominator collapses in a lease" — and the arithmetic refuted it:
0.85 x 122,502 MB reserved by design predicts 12,223 MB free against an
observed floor of 11,917 MB, a 306 MB match, and the same server later ran three
clean legs at a ~7,500 MB steady state. A tripped guard is evidence about the
GUARD until its threshold is shown to sit outside the guarded thing's operating
point. Predict the number from the configuration before believing the verdict,
and keep instrument thresholds strictly apart from engine knobs: moving the
floor changes nothing about what is measured, and moving
gpu_memory_utilization changes what the number means.
The lease carries bytes, and the exec bit is a mount option, measured 2026-08-17
Probed with two rc run -d dgx:gpu0 --max-runtime 3m jobs,
1cb56f84-62bf-4c90-b138-9bd4c3b0617a and
c692d5a0-ec3d-4498-86e4-e86a2864e91a. Verify this again before you plan work
around it, because the worker image and the mount options can change under you.
/workspace in the worker and /mnt/nas_share/rc/ on a local host are the same
folder. A file written from the worker appeared locally under that path, and a
file staged locally was read by the worker. The worker's df reported
//192.168.68.102/Data, 7.3T total, 4.0T available, 46% used.
Direct execution off /workspace is refused, and the mount causes it rather
than a noexec flag. The worker mounts the share with file_mode=0664,
dir_mode=0775, nounix, forceuid and forcegid, and the option list holds
no noexec. The same bytes read -rwxr-xr-x on the local host, which mounts
the share with file_mode=0755, and -rw-rw-r-- in the worker, so the exec bit
is a presentation of each mount and not stored state. In the worker, chmod +x
failed with Operation not permitted, and a staged shell script and a copied
ELF binary each failed to start with Permission denied and exit code 126.
Three routes ran staged content anyway, and each measured green. Record the distinction, because a missing exec bit reads like a wall and is not one.
| Route | Measured |
|---|---|
sh /workspace/staged.sh | printed the script's output, exit 0 |
/lib/ld-linux-aarch64.so.1 /workspace/echo_copy | ran the ELF, exit 0 |
cp to /tmp, then chmod +x, then run | ran the script and the ELF, exit 0 |
/tmp, /var/tmp and $HOME, which is /home/rc, are writable, take a real
exec bit, and sit on a 3.6T overlay with 2.5T available. /dev/shm is 64M. The
job's working directory / is not writable.
So the lease carries bytes, and bytes are enough to run. A runtime staged on
/workspace can start under the dynamic loader, or after a copy to /tmp.
This paragraph used to add that the dgx:gpu0 worker cannot produce or fetch
that runtime, because it had no curl, wget, git, gcc, nvcc, cmake or
python3. That clause is SUPERSEDED. The worker runs as root and carries every
one of those names except the CUDA toolkit, and a job apt-installs nvcc from
developer.download.nvidia.com per run
(#1213). Present and useful
for staging: cp, cat, tar, chmod, perl, flock and nvidia-smi. The
thor:gpu0 worker produces one as well, because it is root and carries
apt-get and gcc. That is the section below.
This narrows #1129 and does
not close it. The HOST venv at ~/venvs/vllm-oracle-pin-555967922 stays
unreachable from a lease, and only a host-side actor reached over ssh can
place a copy of it on the NAS. That route is no longer the only one, because a
lease BUILT the pin on 2026-08-18 rather than copying it
(#1185). Whether a relocated CUDA runtime then starts is no longer
UNMEASURED. It starts, on thor:gpu0. The section below has the reading. A
CUDA virtual environment still holds absolute paths in its shebangs and its
RECORD files, so a pip install --target tree is the shape that was measured
and a copied venv is not.
Three fleet-side changes would each remove the staging problem, and none of
them is ours to make. Whoever owns the fleet picks one. A fourth route was
then measured, and it needs nobody's permission: the thor:gpu0 worker runs
as root with a working apt-get, so a job provisions its own container.
- The worker image gains a toolchain and a Python interpreter.
rc rungains an--imageflag, so a job selects an image that has them./workspaceis mounted so that a file there can carry an exec bit. This one removes the copy step only, because the two routes above already execute.
A relocated CUDA runtime starts on thor:gpu0, measured 2026-08-17
Probed with six rc run jobs on thor:gpu0: 6f4bdb03, 9c0ebeac, 8beba132,
f60d945f, 63c60a90 and fd5654c0. A torch, triton and numpy tree
staged on /workspace imports, initializes CUDA, runs a bf16 matmul, and
compiles and executes a Triton kernel. The job IDs in full, the staged-script
sha256 values, the four walls and the working recipe are in
lease-runtime-staging.md
(#1146).
torch.__version__= 2.13.0+cu130 cuda available = True
device 0 = NVIDIA Thor capability = (11, 0)
triton.__version__ = 3.7.1 TRITON_JIT_OK = 4096.0 PASS
The recipe, once per worker container:
apt-get update -qq && apt-get install -y -qq python3-dev
mkdir -p /tmp/tp && cp -a /workspace/oracle-probe/site/triton /tmp/tp/
chmod -R +x /tmp/tp/triton/backends/nvidia/bin/
export PYTHONPATH=/tmp/tp:/workspace/oracle-probe/site
export CPATH=/workspace/oracle-probe/pyhdr/python3.12:${CPATH:-}
Read the scope before you quote it. This is thor:gpu0 at capability (11,0)
and nothing else. The GB10 is sm_121a, and this tree was never staged there,
so nothing here licenses a claim about the Spark. Only torch, triton and
numpy are in this tree, so the pinned vLLM oracle is not shown to run by it.
The clause this paragraph used to carry, that the oracle "needs nvcc, which
the worker lacks", is FALSIFIED: a dgx:gpu0 lease built the pin against a
staged CUDA toolkit on 2026-08-18, in the section after the next one. The torch
wheel is +cu130 while the staged ptxas reports release 12.8, V12.8.93, and
that skew is recorded as observed rather than adjudicated.
A prebuilt wheel does not remove the nvcc requirement, and that is measured.
An aarch64 vLLM wheel exists in general: pip download --no-deps vllm on the
worker fetched vllm-0.27.1-cp38-abi3-manylinux_2_28_aarch64.whl, 307,180,998
bytes. Our pin is not reachable that way, because
https://wheels.vllm.ai/nightly/vllm/ lists wheels for exactly ONE commit and is
a moving pointer rather than an archive, and because the pin is a development
version that is not on PyPI. Four 404s under a per-commit URL scheme were also
seen, and they prove nothing, because that scheme was never confirmed against a
known-good case. So reproducing the pinned oracle needs a source build or a
deliberate pin advance. Nobody established that vLLM never retains per-commit
wheels. That source build was then run inside a lease and produced our own
wheel, so the route this paragraph names is open.
The pinned oracle builds inside a lease on dgx:gpu0, measured 2026-08-18
Two rc run jobs on dgx:gpu0. The pinned vLLM oracle builds from source,
installs, imports, and sees the GPU inside a lease. No raw ssh was used, so
the fleet reported the box as held for the whole window. The job details, the
staged-script hashes, the four staging walls and the non-claims are in
oracle-wheel-in-lease.md
(#1185).
HEAD = 5559679229bc961848b121ccdeaa8fa5d79bec98 PIN CONFIRMED
nvcc = release 13.3, V13.3.73 NVCC_RC=0
wheel = vllm-0.1.dev1+g555967922.cu133-cp312-cp312-linux_aarch64.whl
vllm.__version__ = 0.1.dev1+g555967922 IDENTITY_RC=0
cuda True NVIDIA GB10 CUDA_RC=0
The nvcc came from the CUDA toolkit that row MODEL-NEMOTRON-H-ABI-A3-E2E
staged on the NAS. The build script asserts HEAD against the pin before it
compiles anything, and it aborts when the two differ.
Read the scope before you quote it, because three things are UNMEASURED.
Running a model is untested: only the build, the install, the import and
torch.cuda.is_available() were measured, and the recorded failure mode of the
step after torch.compile on this host is a reboot of the box
(.agents/specs/mtp-k-gt-1.md). The wheel reports 0.1.dev1+g555967922 while
.agents/upstream-sync.md records
vllm_runtime_version = 0.23.1rc1.dev1511+g555967922, an OPEN discrepancy whose
cause is the shallow fetch that stops setuptools_scm counting the commits
since the last tag. The virtual environment is NOT staged, because that job was
killed at its 90-minute ceiling and its partial tree was removed, so only the
WHEEL is durable.
Two staging traps are worth carrying forward. A cp -a from the NAS
preserves file_mode=0664, so nvcc exits 126, and CIFS nounix stores no
symlink, so a copied CUDA toolkit loses include, lib64 and 32 library links
and CMake then reports
Could NOT find CUDA (missing: CUDA_INCLUDE_DIRS CUDA_CUDART_LIBRARY) (found version "13.3"),
which names the version and denies the toolkit in one line. The rc worker
container is REUSED between jobs, so a repair inside a staging branch is
skipped on the next run and reports nvcc already in place. Write an
environment repair unconditionally, and assert its postcondition.
Two packages a DFlash2 oracle lease needs, and the lease variable that exists, measured 2026-08-22
Measured on dgx:gpu0 across leases 11cee02a, 52ac5673 and a03f34e4
(#1660). This is the "install
what you lack" instruction above, made specific for the one job that has paid
for the gap.
cuda-libraries-dev-13-0, and the failure arrives 12 minutes late.
DFlash2's compute_candidates -> _topk -> flashinfer.topk JIT-compiles
topk.cu, which includes <curand.h>. The cuda-toolkit-13-0 metapackage does
NOT install that header. Leg B died on it INSIDE profile_run, after a
12-minute model load, and it presented as a model failure rather than as a
missing header; leg C installed cuda-libraries-dev-13-0 and got past it. A job
that compiles CUDA therefore installs both, not just the metapackage.
python3-dev, and it lies about what failed. Without it Triton's driver JIT
fails, and the failure surfaces as
Model architectures ['Qwen3_5ForConditionalGeneration'] failed to be inspected
— which names the model and not the toolchain. The thor:gpu0 staging recipe
two sections above already installs it for the same reason.
RC_LEASE_ID DOES NOT EXIST on this fleet. The leased worker carries
RC_DEVICE, RC_JOB_ID and RC_TOKEN. A script that defaults a lease id from
$RC_LEASE_ID therefore reads empty and refuses, which is what
scripts/dflash2-speed-gate.sh did when the ## Owed O26 recipe was run
verbatim. Take $RC_JOB_ID. Read the variable off the worker rather than out of
a document, including this one: the fleet is not ours and the names can change.
The flock orphan hazard that motivated the replacement
The harness family in this repository puts the flock handle on a subshell,
not on the timeout or wrapper process a reader would check. Kill the wrapper
and an ORPHAN survives holding the mutex, with its output pipe severed, and it
looks perfectly idle to every instrument a reader reaches for.
Measured 2026-08-17 (.agents/specs/mtp-k-gt-1.md, "What held the mutex"):
nvidia-smi --query-compute-apps was EMPTY and loadavg stayed near 1.1, which
reads as a finished holder. The holder was PID 333128, bash -s 8000, PPid: 1,
holding fd 3 on the lock file, with fd 1 and fd 2 still pointing at the
pipe its dead tee had been reading. It was not idle. It held a live container
and was inside a readiness poll, and it blocked its own owner's restart for about
50 minutes as well as the queued gate. Read the whole process chain and
/proc/<pid>/fd before you call a lock stale, and never kill an unowned PID.
Registering your own environment
The profiles below are per-developer facts, not requirements: nothing here is usable unless your own setup provides it. To make your hardware a gate environment:
-
Copy
.env.exampleto the untracked.envat the repository root and fill in what your setup has (reference checkouts, oracle, gate host, GPU lock, device arch and toolchain). Empty means unavailable, and the gates that need it stayPENDINGfor you. -
Copy
developer-preferences.example.mdto the untrackeddeveloper-preferences.mdfor the policy choices (Git integration, which remote hosts you may use, contention policy). -
Set
CHECKPOINT_ROOTin your.envif you have shared or network storage, and download model weights there rather than onto a box's system disk. A 30B bf16 checkpoint is ~60 GB; a build tree is ~169 GiB on its own, and a full disk surfaces as unrelated test failures rather than an obvious disk error. Fetching once to shared storage means every host, worktree and agent reuses it instead of each pulling its own copy. It states an INTENT and nothing more: no code in the tree readsCHECKPOINT_ROOT, so it neither redirects a download nor resolves a bare directory name — you place the weights under it and pass the full path onward. A setup with no shared mount leaves it empty and uses whatever the tool defaults to (usually the Hugging Face cache under$HOME).Two rules travel with it. Pin an explicit revision when you fetch: publishers re-quantize in place under an unchanged repo name, so a bare branch name is not reproducible and a checkpoint you gated against can change under you. And setting the variable authorizes nothing on its own — a large asset download still needs authority for the task.
-
Add a profile entry to this file, in the same shape as the entries below: hardware, arch, toolkit versions, oracle availability, and the box's quirks. A PR for it is welcome, so the shared record says where each gate can run. New accelerator classes (an AMD/ROCm box, an Intel GPU) register the same way and become the gate environment for their backend rows.
-
Rich local development/GPU profile (re-verified 2026-07-25): NVIDIA GeForce RTX 5070 Ti, 16 GiB, compute capability 12.0 (
sm_120), driver 595.71.05. The cachedQwen/Qwen3.5-4Bsnapshot is the only model large enough for the local direct-load performance diagnostic; it cannot run the 27B/35B gates. The CUDA Nix shell must put/run/opengl-driver/libbefore toolkit stubs.flake.nixnow does so directly and no longer emits a malformed literalLD_LIBRARY_PATHexpansion. A cleannix develop .#cudareportstorch.cuda.is_available() == Trueand TritonGPUTarget(backend='cuda', arch=120, warp_size=32)without a manual override. Build the current diagnostic with CMake CUDA arch120a, Triton vendored targetsm_120, CUTLASS and FlashAttention-2 enabled. -
CPU development path: CPU reference backend + engine logic + CI development.
-
Ettore DGX release-gate profile: device
dgx:gpu0, hostdgx.casa(claim it withrc, and read "Reaching a GPU" earlier in this file before you use thesshrecipes recorded here). DGX Spark, GB10 (Blackwell, sm_121), ~119 GB unified memory, 20 cores, CUDA toolkit 13.0.88 (nvcc); compute capability 12.1 → sm_121. Unified memory: both gate models fit in bf16; the machine is memory-bandwidth-bound (~273 GB/s class) — decode parity is a bandwidth/launch-overhead game, hence CUDA graphs + fused kernels in T0. Give each active claim its own~/work/<claim>/directory; never share a build tree between agents.- Non-interactive SSH does not put nvcc on PATH — prepend
export PATH=/usr/local/cuda/bin:$PATHin remote build commands. - The NAS mounts at
/usr/local/nas_share, and/mnt/nas_shareis GONE (re-verified 2026-08-16)..envsetsCHECKPOINT_ROOT=/usr/local/nas_share/checkpoints, where 18 checkpoint directories resolve,nemotron-3.5-lightning-30b-nvfp4andnemotron-3.5-lightning-30b-ggufamong them. Do not restore the old path as a convenience symlink./mntis on the EPHEMERAL root overlay of this immutable Kairos OS, so anything created there is gone after the next reboot;/usr/localisCOS_PERSISTENTand survives. That is the same property that made an earlier/oemrootfs-stage change cost a boot (see [[kairos-oem-rw-paths-change-cost-a-boot]]). Measured 2026-08-16, after the box returned from an 8 h 19 min outage: the mount itself came back because the/oemboot-stage unit worked andfindmnt /usr/local/nas_sharewas clean, and/mnt/nas_sharedid not come back. Every path built on/mntbroke while.envstill declared it, which blocks a checkpoint-loading gate silently — a gate that reads a path.envdoes not declare is not the gate its spec names. Checkfindmnt /usr/local/nas_sharebefore you conclude that a checkpoint is missing (#1073). - MANDATORY gate-build flags on this box (re-proven 2026-07-29). A model
gate configured WITHOUT
-DVLLM_CPP_CUTLASS_DIR=$HOME/cutlass-4.5.0and-DVLLM_CPP_TRITON=ONis NOT the production stack: cutlass-off silently disables the sm120a NVFP4 fp4×fp4 GEMM and FlashAttention-2, triton-off swaps the vendored Triton-AOT GDN kernels for the hand kernels. On the 27B that flips the documented tok6 near-tie and turns the SACREDtest_qwen27_paged_enginered (234/235 or 233/235 vs 235/235) with the source untouched — measured three-arm from ONE tree at maind4492c03. Hard- verify the configure log printsCUTLASS found … enabling sm120a NVFP4 cutlass GEMM,FlashAttention-2 prefill/decode: ENABLED, and theTriton AOT: … <- vendored … sm_121alines before trusting any gate or A/B. Never read the arch fromCMakeCache.txt(CMAKE_CUDA_ARCHITECTURESthere legitimately reads75, theenable_language(CUDA)probe default shadowed inCMakeLists.txt); readVLLM_CPP_CUDA_ARCHITECTURES,flags.make, orcuobjdump -lelf. This defect has voided work three times (2026-07-16 ×2, 2026-07-28); the 27B gate now refuses to run without both flags. - Oracle venv: PIN ADVANCED 2026-07-26 (see
specs/pin-advance.md).
~/venvs/vllm-oracleis now a canonical symlink to the from-source~/venvs/vllm-oracle-next— the new active stack is vLLM 0.26.0.dev0+g5559679 (source55596792, built for sm_121a: the exact commit has NO aarch64 wheel, so the oracle is a ~1.3 h from-source build not a pip install), Transformers 5.14.1, Torch 2.13.0+cu130, FlashInfer 0.6.15.post1, CUTLASS DSL 4.6.0, Triton 3.7.1, torchvision 0.28.0. This advance unblocks DFlash (vllm#40898 mixed-attn fix, underVLLM_USE_V2_MODEL_RUNNER=1), Gemma-4 (transformers.models.gemma4), and OLMo-3 (nested rope). It was validated by the W0–W4 pin-advance re-gate: zero real golden drift (27B-W4A4 + 32B-NVFP4A16 bit-identical, 35B/Coder byte-stable — the W0-W2 "27B drift" was a capture-config near-tie, not the oracle), fullctest296/299 GREEN on GB10 (the 3 fails pre-exist on main, unrelated). ROLLBACK (immediately restorable):ln -sfn ~/venvs/vllm-oracle-v0.25.0-stage ~/venvs/vllm-oraclerestores the prior pip vLLM 0.25.0 stack (FlashInfer 0.6.13, Torch 2.11.0+cu130, CUTLASS DSL 4.5.2, Transformers 5.13.1, Ninja 1.13.0; install/serving SHA-256ab786eee…c297/536385d8…f506, vLLM/Ninjaec6d76ff…96c/abf71487…10b, freezecf1636cc…fa5f); the v0.24.0 dir remains at~/venvs/vllm-oracle-v0.24.0-retired. The §2D mechanical re-sync of upstream-changed mirrored files (rmsnorm-fusion #46998, ReplaySSM #48018, MoeWNA16 #44120, olmo3.py, …) is a DEFERRED follow-on (gate-correctness does not depend on it — goldens are bit-identical). - The only dependency-check exception is NVIDIA's
nvidia-cusparselt-cu13==0.8.0wheel: PyPI served the aarch64 wheel (sha256:400c6ed1…77c), its library is an AArch64 ELF and directctypes.CDLL/Torch imports pass, but its internal WHEEL tag ismanylinux2014_sbsa, sopip checkreports it unsupported. This is a recorded vendor-tag defect, not silently treated as a greenpip check. - Lock-held production-graph validation on the exact 27B snapshot passed both
offline generation (16 input IDs, one output ID) and the actual text-only
server:
/health200 plus/v1/completions200 with exact 1+1 usage andfinish_reason=length. Server log/response SHA-256 aref56be69a…3787/82307db4…8e1under~/work/vllm-oracle-v0.25.0-stage-validation/2026-07-12-server-smoke. The smoke rate is non-binding. Its first offline inference emitted one causal-conv Triton JIT warning, which remains a warmup/trace audit item. Online-gate manifests hash pandas package/distribution files plus Ninja and reject missing/drifted dependencies before the GPU lock; profiler launches prepend the venvbinto spawned EngineCorePATH. - Run the CUDA
ctestsuite with-j 1. GB10 memory is UNIFIED, so agpu_memory_utilizationreservation is HOST RAM: concurrent model gates stack into the same ~119 GB and the kernel starts killing. Measured 2026-08-09 on a default-ON Triton build,ctest -j 4OOM-rebooted this box (NVRM ... Out of memory [NV_ERR_NO_MEMORY]), which is why the parallel-flake advice in the Apple/Metal profile below does not transfer here. Serialising also means every other probe queues behind the suite, so run attribution arms BEFORE a full suite, never during one. - ★ TREAT A SERVING LEG AS AT RISK OF A REBOOT TOO, NOT ONLY A BUILD OR A
LOAD — THOUGH ONLY THE REBOOT IS OBSERVED AND ITS PLACEMENT NEXT TO THE LEG
IS DERIVED — AND FROM INSIDE A LEASE
boot_idIS THE ONLY INSTRUMENT THAT SEES A REBOOT AT ALL (measured 2026-08-19, #915). Read the heading at the strength of its parts. Whatboot_idobserves is that a reboot happened somewhere between two readings about 11.2 hours apart, and across the same unpinned clock boundary: the old value is last recorded inclock-vllm-c1-r3.json, written 10:18:51.7Z ondgx, and the new one landed in a log written 21:29:35.6Z on the local host. The serving leg occupied about 6.5 minutes of that span. Putting the reboot next to the leg needs the DERIVED/proc/uptimebound below, and tying it to the worker's death is not claimed at all. So "under a serving load" is the working assumption this bullet is written for, not a measured fact. The pinned oracle's c8 denominator leg forQwen/Qwen3.8-27Bbf16 — vLLM's production graphed shape at--gpu-memory-utilization 0.85 --max-num-batched-tokens 8192— answeredGET /health 200 OKat 10:25:07Z with about 9,950 MB ofMemAvailable, read 6,261 MB at 10:25:26Z, and the worker was then lost inside one 2-second sample, during the untimed warmup. That is OBSERVED, and it is the loss rather than the reboot. That configuration leaves roughly 6-7 GB of headroom on this box. The earlier reboots this file records for this machine are actest -j 4and an oracle LOAD; this one is only ASSOCIATED with a server that was already healthy and serving-ready, and on that association "survived startup" is not a safe state. Readboot_idin every leased job that loads anything large. A lease gives you a pod, not the box's history:uptimeresetting andjournalctl --list-bootsare host instruments a pod does not have, and a lost worker looks identical whether the pod died or the machine did. That ambiguity stood unresolved in the campaign record for a day./proc/sys/kernel/random/boot_idis kernel-wide and regenerated per boot, so a changed value is a reboot and nothing else can forge it: a later job (97cf3e63-e4a4-4506-bde7-f19f19be3bbf) read64c495a3-8c9c-4b20-8496-a97efda0e332against the benchmark's3fd9745a-d25a-426c-ba3c-97c958a85515. Do not promote a boot TIME derived from/proc/uptimeto the same strength. Read inside a pod,/proc/uptimeis the host's only if the worker does not virtualize/proc—lxcfsdoes, and it cannot touchboot_id— so the identity change is observed and any derived timestamp carries that assumption. State it beside the number. The bound is also ONE-SIDED: the log mtime you subtract from is when the LAST line landed, so it is an upper bound on the read instant and never a midpoint. Here that gives a boot at or before 10:41:47.6Z with no lower bound, and the mtime is on a different host's clock from the uptime, with the offset unmeasured. And a sampling watchdog cannot guard the REBOOT CLASS of failure at all. A userspace sampler dies with the kernel, so there is no floor and no cadence at which it reports a reboot; that holds on its own and needs no link to any particular worker loss. Here the 2-second sampler never even saw a value below its own 5,000 MB floor. Detail inspecs/qwen38-27b-bf16-gate.md. - GPU mutex: this runs INSIDE an
rclease, never instead of one. The lease decides who gets the box. The mutex serialises the work of whoever holds it. Every CUDA test/model/serve/benchmark/profile holds the${GPU_LOCK}file mutex —$HOME/gpu.lock, which is what.env.exampleships and what every script here falls back to via${GPU_LOCK:-$HOME/gpu.lock}— for the whole job or multi-arm series WHEN other agents may run GPU work concurrently (sole owner verified idle vianvidia-smimay skip). Mechanism: run GPU work asflock ${GPU_LOCK:-$HOME/gpu.lock} -c '<command>', or take the lock once around an entire benchmark series so arms are never interleaved; waiting on the lock is normal, stealing it is not. Compilation, source inspection and file transfer do not need the lock. Never kill an unowned PID. Check your.envbefore you measure anything: aGPU_LOCKnaming any other path takes a mutex nobody else holds, andflocksucceeds on it, so the run is unserialised and only looks like someone else misbehaving. That cost a whole Marlin series (#777); an existing.envpredating that fix must be repaired by hand. - Disk cleanup 2026-07-10 reclaimed ~368 GB from unrelated cached model sets, April-era autoresearch logits/F16-GGUF cache artifacts, the vLLM compile cache and stale rebuildable CUDA build trees. Active latency/PR workspaces, gate checkpoints, APEX GGUF evidence and sources were preserved; the volume had 359 GB free afterward. Maintain at least 200 GB headroom before adding competitor images.
- Non-interactive SSH does not put nvcc on PATH — prepend
-
Ettore Jetson Thor profile (sm_110 CUDA runtime gate): device
thor:gpu0, host192.168.68.23(claim it withrcfirst) — NVIDIA Jetson Thor (Blackwell, sm_110), aarch64, 14 CPU cores, ~122 GB UNIFIED memory.nvidia-smi --query-gpu=compute_capreturns 11.0. Host of the first non-GB10 runtime proof (CLAIM-CUDA-SM110-RUNTIME, 2026-07-27).-
REIMAGED, re-verified 2026-08-11. The box is hostname
kairos-4db2(Ubuntu 24.04 under Kairos), driver 595.78, and there is NO host CUDA toolkit, no cmake, no nvcc, no huggingface_hub — the JetPack R38 //usr/local/cuda-13.0profile described here before is GONE. The GPU is usable only from inside a container (developer statement, confirmed on box), and the leasedrcworker IS that container. There is nolocal-ai-workercontainer on the host; the worker-restore discipline below does not apply in this state. -
The hand-run
sudo -n dockerrecipe that used to sit here is DELETED, not demoted to an alternative, because this FILE ALREADY FORBIDS IT. The section that opens this document — "Reaching a GPU: claim a lease, neverssh" — says to claimthor:gpu0withrc runorrc holdand never tosshto a GPU box to run work. The Thor profile then taught the opposite in four places, so the document contradicted its own header, and a reader who scrolled to the profile for a recipe was taught to break the rule they had read twenty lines in. Bringing this section into line with its own file is the whole of the change;rcis not a new local convention.What the deleted recipe said, kept as history because it was measured and true on 2026-08-11, and because a future host-side operator may need it:
dockerneededsudo(the user is in groupadmin, notdocker); the run needed--runtime=nvidiaand NOT--gpus all, because the hook refuses the latter outright; and it needed-e NVIDIA_DISABLE_REQUIRE=1, because the image'sNVIDIA_REQUIRE_CUDAenumerates bounded driver ranges topping out atdriver<576while this box runs 595.78, which is newer and forward compatible. None of that is a procedure to follow now. Takethor:gpu0withrc run; the section below is the whole recipe. -
"Every sm_110 fast-path cell resolves EMPTY" was wrong, and it mattered. Configure on
[110]DISABLESfp4-mma,cutlass-nvfp4,cutlass-nvfp4-sm100,cutlass-fp8,scaledmm-c3x-sm90,scaledmm-c3x-sm100andfa2, and printsCUDA feature marlin-nvfp4: ENABLED for [110]. Read live at944d7d947on 2026-08-22. Seven of eight is not eight, and the difference is the whole of #962: a Marlin NVFP4 kernel that disagrees with itself across block sizes ON THIS ARCH. The wrong line makes a live kernel defect read as an absent feature, which is exactly backwards..agents/backend-matrix.mdhas said "FOUR of the five fast-path cells resolve EMPTY;marlin-nvfp4resolvesENABLED for [110]" since 2026-08-11, so this line was already contradicted by another record. -
nsysfromnsight-systems-cliin thenvidia/cuda:13.0.1image was 2024.2.3 and could not trace CUDA here ("does not contain CUDA trace data"). That was a property of that image. In the leased workernsysis ABSENT altogether (measured 2026-08-22), so a graph or kernel-count measurement on Thor still needs one installed, and still needs a newer one. -
★ BUILD AND TEST IT INSIDE A LEASE —
rc run -d thor:gpu0(dots3-noteW0.5, issue #699). One job configures, builds CUDA-ON for sm_110, runs kernels on the device and produces thectestbaseline. Copy it rather than re-deriving it.This REPLACES the
ssh+sudo -n docker build+sudo -n docker runrecipe W0.5 landed on 2026-08-15, and replaces it rather than joining it. Two things were wrong with that recipe, and only the first is a rule.It reached a fleet device outside its lease.
thor:gpu0is in the fleet, so a job that arrives bysshmakesrcreport the box FREE while a build is on it — and this file's own opening section already said not to do that. The contradiction was internal, not a matter of taste: a reader who took the header seriously and a reader who scrolled to this profile for a recipe were given opposite instructions.And the digest-pinned image was never needed — though NOT for the reason an earlier draft of this section gave. It claimed the leased worker already supplies everything the image did, and for the CUDA toolkit that is FALSE; see "The toolkit is not in the image" below. The image is unnecessary because a job installs the toolkit itself in one step, which is what
dgx:gpu0jobs already do (#1213), not because the toolkit is waiting there.What the worker DOES supply, measured 2026-08-22 in
rc run -d thor:gpu0job55810add-082e-461b-828b-b7cfe4dbb645(log and artifacts under/mnt/nas_share/rc/thor-w05-repair/, which the worker sees as/workspace/thor-w05-repair/):user uid=0(root) gid=0(root)in the k3s podrc-worker-<id>, 14 CPUs, aarch64present bash sh git curl wget gcc/g++ 13.3.0 make cmake 3.28.3 ninja 1.11.1 pkg-config python3 3.12.3 pip flock— this list is exactly what was probed, andreadelf/objdumpwere NOT among themnvccNOT part of the image. Install it. Both of this lane's jobs happened to find /usr/local/cuda-13.0and nvcc 13.0.88 already there, and that was another job's leftover — see belowABSENT shellcheck,cuobjdump,nsys,sudo,docker— andcuobjdumpstays absent after thePATHprepend, which matters belownvidia-smiplain, no sudo, exit 0 with ZERO bytes on stderr, reportingNVIDIA Thor, driver 595.78,compute_cap 11.0/workspace//192.168.68.102/Data, 7.3 T, CIFSfile_mode=0664 nounix— the SAME folderdgxsees, and/mnt/nas_share/rcon the devbox. NOT shared withorin.rccopies nothing for you/tmpthe worker's own overlay, 918 G — but it was 94% used with 58 G free on 2026-08-22. Read "Disk is shared" below before you build swap 30.7 G of zram(/dev/zram0, PRIO 100), withvm.overcommit_memory=1. Compressed RAM, not a backing store — see the reboot warning belowreuse the container is REUSED between jobs, so /tmpcarries other jobs' trees and your own from last week★ The toolkit is not in the image, and BOTH of this lane's jobs were fooled by leftover state. The
rc describe thor:gpu0usage sheet says it plainly: "There is no CUDA toolkit (nonvcc). The driver is injected andnvidia-smiworks, but compiling CUDA needs the toolkit — install it, or keep the build on the host." The worker container is LONG-LIVED, so one job'sapt-getis still sitting there for the next job, and theleasing-a-gpuskill warns about exactly that leak.The chain is visible inside this file. The 2026-08-19 job ran in pod
rc-worker-hqfj4and found nvcc 13.0.88 already present. The pod was then recreated — the#1380note further down records that the NEXT worker,rc-worker-m4d7t, had lost/tmpand/usr/local/cuda-13.0, "so the job had toapt-getthe toolkit again". The 2026-08-22 job then ran inrc-worker-m4d7tand found the toolkit present. It was present because that other job had just installed it. Neither observation is a property of the image, and the pod has since been recreated again byworker_lost, so neither is true now.So install it as a step and assert the postcondition. Never write a recipe whose first requirement is that somebody else ran a job on the same pod first. This is the same shape as the
shellcheckdefect this section already documents: a recipe that works only because of undocumented state on the box, which the next reader cannot reproduce.Probe it with
command -vand an explicit else-branch, never withtool --version | tail -1.nvcc --version 2>/dev/null | tail -1 || echo absentprints nothing and exits 0 whennvccis missing, becausetailsucceeds on empty input and the||never fires. That reads as "present but quiet" and it nearly put a false line in this table.1. Stage the tree where the worker can see it.
rccopies nothing.# WHERE THE SHARE IS MOUNTED DEPENDS ON THE HOST YOU TYPE THIS ON. # On the devbox it is /mnt/nas_share/rc; on the dgx HOST that path is GONE # and the share is /usr/local/nas_share/rc (see the DGX profile). Resolve it, # never assume it -- staging to a stale path silently stages nothing, and the # job then fails for a reason that looks unrelated. for c in /mnt/nas_share/rc /usr/local/nas_share/rc; do [ -d "$c" ] && NAS=$c && break; done test -n "${NAS:-}" || { echo "FATAL: no NAS mount on this host"; exit 96; } D=$NAS/<your-dir> # the worker always sees this as /workspace/<your-dir> mkdir -p "$D" git rev-parse HEAD > "$D/BASE_SHA" # a baseline with no SHA beside it is not a baseline git archive --format=tar HEAD | gzip -1 > "$D/src.tar.gz"A
git cloneinside the worker also works — it hasgitand egress, and other rows use it — but only for a branch you have pushed. The archive is how you test a tree that is not on the remote.2. Submit one bounded job, and NAME the device.
rc run -d thor:gpu0 --max-runtime 120m \ -- bash /workspace/<your-dir>/run.sh # the job prints a heartbeat; see belowName it rather than selecting on
class=train, which also matchesdgx:gpu0andorin:gpu0and neither of those is sm_110;gpu_model=NVIDIA-Thoris the only selector that means this box. Naming queues you behind whoever holds it, which is the lease working. Never select onvram— it reads[N/A]here and matches nothing.--idle-timeoutcounts the job's OWN stdout, and a build that logs to a file is silent for its whole duration. Acmake --buildredirected into a log prints nothing for twenty minutes, and the idle killer does not care why.Print a heartbeat. That is the remedy that was actually proven here, and
--idle-timeout 0is NOT a second way to do the same thing.rc run --helpreads--idle-timeout duration kill the job if it produces no output for this long (0 = device default), so zero selects the DEVICE DEFAULT rather than disabling the kill. An earlier draft of this section prescribed--idle-timeout 0as the fix, which would hand a future agent a long quiet build and a false belief that it is protected. A one-line background loop is the whole of it:( while true; do sleep 60; echo "### hb $(date -u +%H:%M:%S)"; done ) & HB=$! # ... the quiet work ... kill "$HB" 2>/dev/null; wait "$HB" 2>/dev/nullThe margin this closes is not theoretical. The 2026-08-19 run built for 22 min 44 s in silence against
--idle-timeout 25mand survived with about two minutes to spare.--max-runtimeis the bound that matters and it is not optional; the heartbeat is what stops the idle killer from firing inside it.3. What the job does.
This script is the whole recipe, including the disk discipline the prose below mandates. An earlier draft printed a shorter version and left the disk rules to the prose; "copy it rather than re-deriving it" means the script is what actually gets run, so a guard that lives only in a paragraph is a guard nobody executes.
#!/bin/bash set -u SRC=/tmp/src # NEED_GB is an UNMEASURED PLACEHOLDER. Nobody has recorded `du -sh` of a # finished build-cuda on this box, so this number was chosen, not derived. # The two real data points are: a build that COMPLETED with 154 G free # (2026-08-19) and one that did NOT complete with 58 G free (2026-08-22, # though the worker was lost and disk is a hypothesis rather than a proven # cause). Replace it with the figure the block at the end of this script # prints, and delete this comment when you do. NEED_GB=${NEED_GB:-60} free_gb() { df -BG --output=avail /tmp | tail -1 | tr -dc '0-9'; } # --- clean up on ANY exit, including the kill. A job that dies holding its # --- tree is what took this box out of the pool. cleanup() { rm -rf "$SRC"; kill "${HB:-}" 2>/dev/null; wait "${HB:-}" 2>/dev/null; } trap cleanup EXIT INT TERM ( while true; do sleep 60; echo "### hb $(date -u +%H:%M:%S) disk=$(free_gb)G"; done ) & HB=$! # --- DISK, before anything else. The container is REUSED, so other jobs' # --- trees are still here and the free space is shared with them. df -h /tmp du -sh /tmp/* 2>/dev/null | sort -rh | head -10 rm -rf /tmp/src /tmp/thor-w05-src* # reclaim this lane's old trees, not just mine if [ "$(free_gb)" -lt "$NEED_GB" ]; then echo "REFUSING: /tmp has $(free_gb) GiB free, below the NEED_GB=${NEED_GB} floor." echo "That floor is an UNMEASURED placeholder -- read its comment above before" echo "believing it, and raise NEED_GB deliberately if you think it is wrong." echo "A CUDA build that runs out of space fails as unrelated compile errors." exit 95 fi # --- The CUDA toolkit is NOT in the worker image. Install it UNCONDITIONALLY. # --- `command -v nvcc` is NOT a sufficient precondition: a partial leftover # --- puts nvcc on PATH while `include`/`lib64` are missing, and CMake then # --- dies with "Could NOT find CUDA (missing: CUDA_INCLUDE_DIRS # --- CUDA_CUDART_LIBRARY)", which names the version and denies the toolkit # --- in one line. apt-get is idempotent, so paying it every run costs # --- seconds and removes the whole class. # `cuda-toolkit-13-0` is NOT in Ubuntu's own archive. Add NVIDIA's repo # first, or the install fails to resolve on a freshly recreated pod -- and # succeeds on a pod where some earlier job already added it, which is the # same leftover-state trap in a second guise. apt-get update -qq apt-get install -y -qq wget ca-certificates gnupg wget -q https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/sbsa/cuda-keyring_1.1-1_all.deb -O /tmp/ck.deb dpkg -i /tmp/ck.deb apt-get update -qq apt-get install -y -qq cuda-toolkit-13-0 export PATH=/usr/local/cuda/bin:$PATH CUDA_HOME=${CUDA_HOME:-/usr/local/cuda} # --- Assert the POSTCONDITION the build actually needs, not the binary. command -v nvcc >/dev/null || { echo "FATAL: no nvcc after install"; exit 90; } test -f "$CUDA_HOME/include/cuda_runtime.h" \ || { echo "FATAL: nvcc present but no cuda_runtime.h under $CUDA_HOME"; exit 90; } ls "$CUDA_HOME"/targets/*/lib/libcudart.so* >/dev/null 2>&1 \ || ls "$CUDA_HOME"/lib64/libcudart.so* >/dev/null 2>&1 \ || { echo "FATAL: no libcudart under $CUDA_HOME"; exit 90; } nvcc --version | tail -2 # record WHICH toolkit built this mkdir -p "$SRC" tar -xzf /workspace/<your-dir>/src.tar.gz -C "$SRC" test -f "$SRC/CMakeLists.txt" || { echo "FATAL: untar"; exit 92; } cmake -S "$SRC" -B "$SRC/build-cuda" -G Ninja -DCMAKE_BUILD_TYPE=Release \ -DVLLM_CPP_CUDA=ON -DVLLM_CPP_CUDA_ARCHITECTURES=110 -DVLLM_CPP_TRITON=OFF cmake --build "$SRC/build-cuda" -j 4 ( cd "$SRC/build-cuda" && ctest -j1 --timeout 1800 ) # --- MEASURE what this actually cost, so NEED_GB stops being a guess. # --- Record these two numbers in this file and replace the placeholder. du -sh "$SRC" "$SRC/build-cuda" echo "### /tmp free at end: $(free_gb) GiB" # cleanup() removes $SRC on the way out, on success AND on the kill path.cuda-toolkit-13-0is the package, and a barecuda-nvcc-13-0is NOT a usable fallback. An earlier draft of this script fell back to it when the full toolkit failed, and that fallback is worse than no fallback: it satisfiescommand -v nvcc, so the guard passes, and thenCMakeLists.txt:1717runsfind_package(CUDAToolkit REQUIRED)and:1719linksCUDA::cudart CUDA::cublasLt, neither of which a compiler-only package supplies. The build dies at configure with the same misleading missing-CUDA line as a partial leftover. This build's ownlddresolveslibcudart.so.13andlibcublasLt.so.13, so those are requirements and not conveniences. If you must install a minimal set rather than the metapackage, it iscuda-nvcc-13-0 cuda-cudart-dev-13-0 libcublas-dev-13-0— and the postcondition assertions above are what tell you whether you got it right.The
sbsapath in that keyring URL is the aarch64 one, and it is what both this box anddgxneed; anx86_64URL resolves and then installs nothing usable here. The concurrentgate-fp8-thorbuildjob took the same route on 2026-08-22 and its configure reportedThe CUDA compiler identification is NVIDIA 13.0.88at/usr/local/cuda-13.0/bin/nvcc, which is independent corroboration of both the package and the version.cuRAND is NOT among the requirements, in case a reader reaches for it:
grep -rn curand src include CMakeLists.txt cmakereturns nothing, so this tree never uses it. Thecurandmention elsewhere in this file belongs to DFlash2's flashinfer JIT ondgx, which is a different lane.Build in
/tmpor/root, never on/workspace: the share is CIFS withnounix, so it stores no symlink and presents no exec bit, andchmod +xthere fails withOperation not permitted. Write every environment repair UNCONDITIONALLY and assert its postcondition, because the container is reused and a conditional repair is skipped on the second job and then reports success. Copy what you want to keep back to/workspace.★ Disk is shared, and getting this wrong took the box out of the pool. A run on 2026-08-22 wiped only its own tree, left an earlier tree of this same lane in place, and built on an overlay that was already 94% used with 58 G free. Partway through the build
thor:gpu0wentunhealthy (no contact)without of the pool: worker_lost, and the job died at SIGTERM. Host memory was NOT the cause — the sampler read 116 GiB available one minute before contact was lost, so this is not the overcommit-collapse signature below.worker_lostdid not self-heal QUICKLY, and it did eventually clear. The device still readunhealthy (no contact 2h38m)two and a half hours later; by 2026-08-22 it wasreadyagain withdisk_free_bytesback to about 123 GiB. Do not clear a quarantined device yourself — that needs an admin token and is a human's call — and do plan for hours rather than minutes, because there is no second sm_110 device to fall back to and an sm_110 gate simply stops meanwhile. Report free space, reclaim every tree the lane has left behind rather than only your own, refuse rather than build into a nearly full disk, and remove your tree when you finish. A CUDA build that runs out of space surfaces as unrelated compile errors, which is the [[enospc-makes-checkers-emit-false-policy-refusals]] shape.No CUTLASS directory is passed, and that is correct rather than lazy: every CUTLASS-dependent cell is arch-gated off for
[110], so supplying CUTLASS changes nothing here.-DVLLM_CPP_TRITON=OFFis deliberate — the vendored Triton-AOT path has never been built for sm_110, and turning it on is a separate measurement rather than a default.4. Prove the build is really a CUDA build, because a silent CPU fallback is the failure mode this exercise exists to catch. Configure at
944d7d947on 2026-08-22 printsCUDA target architectures: 110and resolves/usr/local/cuda/bin/nvcc(NVIDIA 13.0.88); at0764ded2bthe completed build'sldd build-cuda/libvllm.soresolvedlibcudart.so.13andlibcublasLt.so.13out of/usr/local/cuda-13.0/targets/sbsa-linux/lib, over 32*.cu.oobjects.The cubin check that used to be step 5 CANNOT be run as written, and that is a defect in the old record rather than in the build. It said to run
cuobjdump --list-elfover every*.cu.oand read30 sm_110.cuobjdumpis ABSENT from the leased worker even after prepending/usr/local/cuda/bin(measured 2026-08-22), so that command produces nothing. Worse, it produces nothing quietly: piped intogrep -owith stderr discarded, an absent tool and a clean-but-empty result look identical, which is how a run on 2026-08-19 recorded an empty histogram without noticing. Install the reader explicitly and assert it (apt-get install -y cuda-cuobjdump-13-0), and assert the binary is there before you trust the histogram. Areadelf -Sfallback reading the.nv_fatbinsection, plus the arch strings in the fatbin headers, would be a weaker substitute — weaker because it shows what an object CONTAINS but not that each object carries exactly one cubin — and whetherreadelfis even in the worker is itself UNMEASURED, so do not plan on it without probing first. Until somebody runs it with the reader present, treat "30 objects, onesm_110cubin each" as an unverified 2026-08-15 claim rather than a standing fact. It is recorded here as owed.5. Runtime proof, on the device. At
0764ded2b,./tests/test_cuda_backendreportedCUDA compute capability: sm_110andpageable=1 integrated=1 UnifiedMemory=true, 6/6 cases, 25/25 assertions, exit 0. A hand-writtennvcc -arch=sm_110kernel also compiles and runs in the worker:kernel_returned=1234 err=no error, exit 0.6. Parallelism, and what is actually measured. Build at
-j 4, runctestat-j 1.ctest -j1is not caution; it is the same rule the GB10 profile above states, for the same reason. Memory here is UNIFIED, so a model gate'sgpu_memory_utilizationreservation is HOST RAM, concurrent gates stack into the same ~122 GB, and this box reboots rather than OOM-kills. Serial costs 419.97 s for 553 tests, so there is nothing to buy by stacking them, and it means the shipped baseline IS a-j1reading rather than a-j4reading with a separate-j1re-run asserted beside it.The two numbers the earlier record used to justify
-j4are corrected here. It claimed "all 14 reproduced at-j1" and "peak host memory ~6 GB of 122 GB". The-j1claim's artifact (#955 cites/home/mudler/thor-w05/ctest-j1-rerun.log) is on the Thor HOST, which a lease cannot read, so it can no longer be checked; the ~6 GB figure had no artifact at all. Re-measured with a 2-secondMemAvailablesampler beside the job:Phase MemAvailableminmax own footprint build -j4, 1364 s114.3 GiB 117.8 GiB ~3.5 GiB ctest -j1, 420 s111.2 GiB 118.6 GiB ~7.4 GiB Neither phase goes near the wall, so
-j4for the build is cheap and now has an artifact. That is a statement about a BUILD and a unit suite and it transfers to nothing else — a model load here is what took the box down three times, and the whole-tree build that correlates with a laterunknown (no contact)on this device is #1380, recorded further down this same profile.7.
nvidia-smi, corrected. The earlier record said it "dies" unprivileged withNvRmMemInitNvmap failed: error Permission denied, works only undersudo -n, and reads[N/A]in its memory columns. Three corrections, with different provenance, so read which is which.Measured here, in the lease: it runs with no
sudo, exit 0 and ZERO bytes on stderr — not oneNvRmline — reportingNVIDIA Thor, driver 595.78, CUDA 13.2. Inside a leased worker there is no privilege problem to work around at all.Reported by the developer from the HOST, and deliberately NOT re-measured here, because doing so needs the
sshthis recipe refuses to take: an unprivileged host call also exits 0 and prints the table, with theNvRmlines going to STDERR beside a successful report. On that reading, "it refuses" was stderr being taken for a verdict.The memory field has two spellings, both in the same job's output: the table column reads
Not Supported, while--query-gpu=memory.total,memory.used --format=csvreads[N/A]. Either way this is an integrated GPU with no separate VRAM counters, the same shape as [[gb10-has-no-dram-counters-ncu-memory-pct-is-a-lie]]. Do not build a memory-headroom check onnvidia-smihere; readfree -gor/proc/meminfo, which is what the sampler above does.The
flock ${GPU_LOCK}wrapper this section used to prescribe is gone with thesshrecipe. On a fleet device the LEASE is the mutex —rchands the whole device to one job. The file mutex is for a GPU that is not a fleet device, and taking one oversshwhile another session holds the box throughrcis precisely the two-mutex collision recorded at the top of this file, which already retained a speed axis as VOID.8.
ctestBASELINE —0764ded2b, 2026-08-19,ctest -j1 --timeout 1800inside anrc run -d thor:gpu0lease, 419.97 s wall:553 tests: 534 passed | 3 skipped | 16 FAILEDArtifacts, because this section indicts the previous record for citing none. Job
1b2512f0-0a43-44cb-b4a4-b54c22b59bd9onthor:gpu0, written to/mnt/nas_share/rc/thor-w05-repair/out/(the worker sees it as/workspace/thor-w05-repair/out/):ctest-j1.log119,929 bytes carries every failure with--output-on-failure,build.log148,351 bytes,configure.log2,346 bytes,memsample.txt44,933 bytes is the 2-second sampler behind the table above, andctest-shellcheck.logis the single-test re-run after installingshellcheck.BASE_SHAandsrc.tar.gzbeside them are the staged input. This is scratch on a shared NAS and may be reaped, which is a reason to quote the numbers here as well as the paths, not a reason to omit the paths.The follow-up job
55810add-082e-461b-828b-b7cfe4dbb645at944d7d947wroteout-v3/and reportskilled (cancelled)inrc, because it is the run that lost the worker; itsconfigure.logis complete and is the source of the live feature-cell reading, and it has noctest-j1.logbecause it never got there.Skipped for an absent checkpoint:
test_modelopt_mixed_precision_checkpoint,test_voxtral_e2e,test_qwen35_paged_engine. These 16 are the sm_110 baseline and are NOT to be "fixed" by a row that merely builds here.★ This baseline is STALE, and the distance is 144 commits rather than the "one
mainbehind" an earlier draft of this section claimed. Measured0764ded2b..08c81a892: 144 commits, 100 of them touchingsrc/,include/,tests/orCMakeLists.txt, for 319 files and +76,570 lines. The re-measure rule two paragraphs down has therefore fired a hundred times over. "One behind" was literally true of the branch base and reads as "essentially current", which is the opposite of the truth.One of those commits lands directly on the mechanism this table blames for two of its entries.
cffe59b02(2026-08-20, "the reference tier gated on unified memory, not on whether the host can address it", #844/#1435) rewritessrc/vt/op_provider.cpp, which is the dispatch that prints[vt reference-tier] op=... has NO native kernel; running the PORTABLE CPU fallbackimmediately beforetest_ops_fp8_cutlassandtest_ops_matmul_fp8_block_cudasegfault. It changes that gate on the axis of unified memory, and Thor is a unified-memory box. So both FP8 SEGFAULT rows below are specifically suspect at currentmain— they may be fixed, they may have moved mode, and nobody has looked.A re-measurement at
944d7d947got as far as configure — which is where themarlin-nvfp4: ENABLED for [110]reading above comes from — and then lost the box to theworker_lostevent described under "Disk is shared". Re-measuring is OWED (#955). It WAS blocked on the fleet whilethor:gpu0satunhealthyon 2026-08-22; that excuse has since expired — the device returned to the pool the same day — so the debt is now simply unpaid rather than impossible, and it needs a build plus a fullctestfrom somebody holding a lease. Recording a stale baseline with its SHA and its true distance attached is honest; recording it as current would be the exact trap the next paragraph warns about.The gate is
(name, failure mode)PAIRS. A row regresses on Thor when it adds a NAME, or when it changes a recorded MODE FOR THE WORSE. Counting names is provably too weak, and this baseline's own history is the proof: between5a0ffe9e3and2daa3287ffive tests wentFailed→SEGFAULTwith no name change, and the list lengthened by one only because the same upstream change also shipped a new test file — so a name-counting gate would have scored #960 GREEN on five of the six crashes it introduced. The Mode column is part of the baseline, not decoration, and it costs no extra measurement becausectestprints the mode beside every failure. Recorded as #955, the sm_110 counterpart of #907.Direction matters, and an earlier draft of this gate left it out. Two kinds of movement are IMPROVEMENTS and must not be scored as regressions. A name LEAVING the list is one. A mode getting BETTER is the other, and it is not hypothetical: this lane's own 2026-08-19 run saw three of them, the
qwen3_5_gdn_spec_routingfamily goingSEGFAULT→Failed. As first worded — "adds a name or changes a mode" — the gate would have told the author of that fix they had regressed the box three times.Rank the modes, worst first:
SEGFAULT/Subprocess aborted/Timeout, thenFailed, thenSkipped/Not Run, then PASSING. A crash becoming a clean assertion failure is progress, because a crash takes the rest of its binary's cases with it —test_capireports61 skippedbehind its SIGSEGV. Only movement DOWN that ranking, or a new name, is a regression. Record every move in either direction; score only the bad ones.Skippedsits BELOWFailedon that list and is NOT an improvement, which is the trap in ranking at all. Three tests already skip on this host for an absent checkpoint, so the mode is live in this very baseline: a red test that starts skipping has stopped being measured, not started passing, and a checkpoint that quietly goes missing looks exactly like a fix. So a name that LEAVES the failure list is only an improvement when you have seen it PASS. That is not a counsel of perfection — it is what was done here, and it is onegrep: whentest_ops_fp8_cpuandtest_ops_fused_chainleft the list, both were confirmedPassedin the same log rather than assumed. A departure you cannot show green is an unexplained change, and it goes in the report as one.The table is keyed on NAME, never on the
ctestordinal. Ordinals move whenever a test file is added, and they moved between every pair of runs this lane has taken.Test Mode First failing assertion Cause test_serve_low_toolsFailed tests/tools/test_online_gate_startup.py:260FileNotFoundError: [Errno 2] No such file or directory: 'shellcheck', 1 error in 330 testsan ABSENT INSTRUMENT, #961, NOT an sm_110 fact. See the note under the table test_platformFailed test_platform.cpp:307CHECK(cu.is_device_capability_family(120))falsethe TEST hardcodes the sm_12x family. Thor is 11.0 test_gguf_device_fit_reachFailed :278CHECK(Backend().queues_destroyed == destroyed_before + 1)→0 == 1, case "device fit: the AUTO arm refuses when the accelerator queue CAN be created"NEW since the 2026-08-15 baseline and UNATTRIBUTED. Whoever picks it up owes an issue test_linear_methodFailed :247after == before + 1→0 == 1, case "MXFP4 fused gate_up … fused path ran"the MXFP4 fused path does not run on sm_110. Also red on GB10 (#907) test_qwen3_5_gdn_spec_routingFailed :530CHECK(bad == 0)→10116 == 0, case "GDN merged FP8 qkvz == the two split fp8 GEMMs, bitwise"MODE CHANGED from SEGFAULT: #960's crash is gone, the disagreement is not. Also red on GB10 for a reason of its own (#907), so do not expect green from #960 alonetest_qwen3_5_gdn_spec_routing_glue_fuse_offFailed same assertion, same case same, mode also changed from SEGFAULTtest_qwen3_5_gdn_spec_routing_fused_chain_offFailed same assertion, same case same, mode also changed from SEGFAULTtest_deepseek_v2_forwardFailed :559THREWcuda mla_prefill_attention: built without the vendored FlashAttention-2no FA-2 on sm_110 test_capiSEGFAULT test_capi.cpp:487SIGSEGV, case "capi: custom logits processor forces the generated token (ABI v8)"pre-existing and arch-independent; same crash on GB10 (#907). The single name UNDERSTATES what is red — #994 — and doctest reports `4 cases test_ops_fp8_cutlassSEGFAULT :191SIGSEGV, after[vt reference-tier] op=MatmulFp8Cutlass device=cuda has NO native kernel; running the PORTABLE CPU fallback#1725. NOT #960 — see below test_ops_matmul_fp8_block_cudaSEGFAULT :345SIGSEGV, after the same reference-tier line forMatmulFp8BlockScaled#1725. NEW NAME since 2026-08-15 test_ops_moe_groupedFailed :1262CHECK(bitdiff == 0), logged at:1260asNVFP4 block8-vs-block16 M=8 K=4096 N=4096 bitdiff=15/32768the one substantive standing sm_110 finding, #962. marlin-nvfp4ISENABLED for [110], so this is a live kernel disagreeing with itself across block sizes, not an absent feature. Its MXFP4 sibling readsbitdiff=0/32768in the same runtest_ops_mla_prefillFailed :340and:437THREW FA-2 absentno FA-2 on sm_110 test_ops_mla_chunked_contextFailed :790THREW FA-2 absentsame test_mla_attention_blockFailed :999and:1044THREW FA-2 absentsame test_op_parityFailed :2490output_cbor_sha256mismatch TWICE in "qwen27 GDN BA BF16 projection matches vLLM 0.25 oracle (dgx-only, CUDA)"dgx-captured goldens replayed on Thor; the case names itself dgx-only and runs anyway ★ These two do NOT belong to #960, and an earlier draft of this table said they did. #960 was CLOSED COMPLETED on 2026-08-16 by
d607fec4c, three days before this measurement, and a closed issue cannot own a live crash. Its fix was real and is visible in this very run —QuantFp8Staticmoved into an unconditional TU,test_ops_fp8_cpuis GREEN, and the threeqwen3_5_gdn_spec_routingtests improved fromSEGFAULTtoFailed. ButkMatmulFp8CutlassandkMatmulFp8BlockScaledare different ops, registered from TUs thatCMakeLists.txt:1790-1791compiles only forVT_CUTLASS_FP8_ARCHS(12.0a, 12.1a), so on sm_110 the same fall-through shape survived the fix on two more ops. They now have an open owner, #1725.And the source asserts the opposite outcome, which is the part that needs a measurement rather than an argument.
src/vt/cuda/cuda_matmul_fp8_block_cutlass.cu:56-58says an arch outside the cell "keeps refusing by name — which is the honest answer and not the #960/#844 fall-through". At0764ded2bit did not refuse; it fell through and crashed.cffe59b02has since rewritten that dispatch on the unified-memory axis, so either it is already fixed and these rows are stale, or two live SEGFAULTs were unowned. Nobody has looked, and no CI lane can:cutlass-fp8is ENABLED on GB10, so the fallback is unreachable on the gate host. That is the original #960 blind spot, unchanged.What moved between 2026-08-15 (
2daa3287f, 485 tests / 15 red) and 2026-08-19 (0764ded2b, 553 tests / 16 red), which is the differential gate demonstrating itself. Three names arrived:test_serve_low_tools(instrument),test_gguf_device_fit_reach(unattributed) andtest_ops_matmul_fp8_block_cuda(#1725). Two left, and they left by turning GREEN rather than by disappearing — checked, not assumed:test_ops_fp8_cpuandtest_ops_fused_chainboth ran and bothPassed. And three MODES changed, all in theqwen3_5_gdn_spec_routingfamily,SEGFAULT→Failed. A count of names reads 15 → 16 and calls that one regression. The pairs read three arrivals, two departures and three mode changes, which is what actually happened.Re-measure whenever the base SHA moves across
src/,include/,tests/orCMakeLists.txt. A stale baseline is worse than none, because the next agent reads a regression as the floor.Two things NOT to conclude from this table. The FP8 and FA-2 groups are feature absence surfacing as a thrown exception, which is the loud failure the seam is supposed to produce, and they are not sm_110 numerical bugs. And the FA-2 message reads "MLA prefill on sm_121 IS FlashAttention" while running on sm_110: the text is hardcoded to the GB10 arch, so do not read an arch out of it.
shellcheckis ABSENT from the leased worker, and the baseline OWNS that entry rather than hiding it. In the deleted image the test passed, so the 2026-08-15 list read 15 rather than 16 — but the record explained that by saying "shellcheckis in the Dockerfile above", and the Dockerfile printed directly above it installedcmake ninja-build git python3 python3-dev ca-certificatesand nothing else. The page designated the repo copy authoritative, so the authority contradicted the behaviour it was cited to explain, and anyone rebuilding from it would have got a 16th failure with no explanation.The decision, stated rather than left implicit: the canonical baseline does NOT install
shellcheck, and carries the failure as a named entry.tests/tools/test_online_gate_startup.pyshells out toshellcheckand raises rather than skipping when the binary is absent, which is an absent instrument reading as a code verdict (#961); installing it here hides that, exactly as the image did, while leaving it armed everywhere else.The entry is the instrument and nothing else, proved in the same job. After the baseline, that job ran
apt-get install -y shellcheck(0.9.0) and re-ran only that test:1/1 Passed, 27.88 s. So a worker image that growsshellcheckwill read 15 red rather than 16, and under a(name, mode)gate a name LEAVING the list is not a regression. If you would rather have the shorter list,apt-get install -y shellcheckat the top of the job is one line — but the failure is cheap, named, and a standing reminder that #961 is still armed.One
rcdetail worth carrying. A job whosetrap ... EXITleaves a background sampler running exits throughkilled: stragglers reaped after exit, with a non-zero client exit code AFTER### ALL DONEhas already printed. Every phase result is on stdout by then. Do not read that line as a failed measurement;killandwaiton explicit PIDs if you want a clean code. -
★ THIS BOX REBOOTS INSTEAD OF OOM-KILLING — size every load for it.
vm.overcommit_memory=1("always overcommit"): the kernel grants memory it cannot back, and touching those pages takes the WHOLE MACHINE down. Signature: containerexit=255,OOMKilled=false, NOdmesg/journal OOM line, host reboot (uptimeresets). Observed three times on 2026-08-11 loading a 27B: bf16 (52 GB target + 8.2 GB draft) twice, and NVFP4 (25 GB + 8.2 GB) once, the last of which left the box unreachable pending a power cycle. A 27B target alone loads and runs fine; it is target+draft that crosses the line, consistent with the documented transient double-hold in the load path (114→67 GiB, see [[gb10-nvfp4-load-recipe-context-first-shard-release]]). Do not run a >25 GB model plus a second checkpoint here. Measured OK on this box: Qwen3-4B bf16 spec-off warm ~24.6 tok/s; Qwen3.6-27B bf16 spec-off warm 4.42 tok/s (portable kernels, no fast paths — absolute numbers are NOT comparable to GB10).The "zero swap" clause this warning used to carry is STALE as a reading of
free, and the warning is UNCHANGED in force. Measured 2026-08-22 inside a lease:free -greadsSwap: 30 total, 0 used, 30 free, and/proc/sys/vm/overcommit_memorystill reads1. Butswapon --shownames what it is —/dev/zram0, 30.7 G, PRIO 100 — and zram is a COMPRESSED BLOCK DEVICE BACKED BY RAM. It adds no storage behind the 122 GiB; it trades CPU for a compression ratio on pages that stay in the same physical memory, and its own pool grows in RAM under pressure. So the original clause was wrong about the literal reading and right about the thing it protected: there is no backing store here. Do not read 30 GiB as headroom. #1363 still owes two questions: whether it changes the observed failure mode at all, and when the device appeared. Nobody has re-run the load that took the box down, and nobody should do so casually. Run aMemAvailablesampler beside any load here;nvidia-smiis blind to all of it. -
★ A BUILD CAN DO IT TOO, and the load list above is not the whole envelope. Measured 2026-08-19 (#1380). An
rc runjob onthor:gpu0rancmake --build <dir> -j 8over the whole tree — 1098 targets, which is a compile phase followed by a link phase that runs severalldprocesses at once, each mapping a multi-hundred-MB static image. Roughly five minutes in,rc deviceswent frombusytounknown (no contact)and then tounhealthy, the job vanished fromrc ps, and its/workspacelog stopped mid-phase with no error written. The box recovered on its own about twenty minutes later and now readsready. It was NOT re-leased while unhealthy — AGENTS.md forbids clearing a quarantined device, and nothing was cleared. "Most likely" is the honest register here. The signature matches the reboot-instead-of-OOM shape this file already documents, and a parallel link of that tree is the largest concurrent host-memory demand in the build. What was NOT measured is the kernel's own account: nobody readuptime,dmesgorjournalctl --list-bootson the host afterwards, so "the parallel link exhausted memory and the box rebooted" is inference from the fleet's view alone. One piece of corroboration WAS measured, on the next job. The worker that picked up the following lease reported a DIFFERENT pod name (rc-worker-m4d7tagainstrc-worker-hqfj4before), and its/tmphad lost the source tree and the build directory the earlier jobs had left there, and/usr/local/cuda-13.0was gone so the job had toapt-getthe toolkit again. So the worker container was certainly recreated. That still does not distinguish a host reboot from a pod restart, which is exactly the gap the boot list closes. What would settle it: re-run the same full build at-j 8while samplingfree -mfrom inside the job, and readjournalctl --list-bootson the host afterwards — a GAP in the boot list is the evidence ([[kairos-oem-rw-paths-change-cost-a-boot]]), and a host that did not reboot would falsify it and point at the worker pod instead. The instruction that already existed is the one to follow. The build recipe above prescribescmake --build ... -j 4. It used to say "-j4is deliberate"; that phrasing is gone, replaced by the measured sampler table under "Parallelism, and what is actually measured", and the instruction is unchanged. Every NAMED-TARGET build in that campaign — five jobs,-j 8, one to four targets each — completed without incident. It is the whole-tree build that correlates. Use-j 4for a full build, and prefer named targets. This is the SECOND recordedunknown (no contact)for this device. The first was 2026-08-17, cited in AGENTS.md as the reason a lost controller contact is a live state rather than a hypothetical. Two readings do not make a rate, and neither one's cause was established, so what this second occurrence adds is that the state recurs and must be planned for — not that the box has a property. Treatingunknown (no contact)as a state a long job can enter is warranted by either occurrence alone. Whether the two share a cause is exactly what the boot list above would answer, and until somebody reads it, the count is a reason to keep looking rather than a finding. -
k3sruns here and isenabled. Thercworker is one of its pods, so stoppingk3sstops the lease mechanism itself and takesthor:gpu0out of the fleet. The old note thatsudo systemctl stop k3sfrees its pods (5 containerd shims survive) is history from the host-toolchain era; do not run it. It was not the crash cause. -
Getting code and weights onto this box goes through the lease, not
ssh. Source:git archiveto/mnt/nas_share/rc/<dir>— never rsync, see [[dgx-transfer-git-archive-not-rsync]] — orgit cloneinside the worker for a branch you have pushed. Weights:/workspaceis the SAME NAS folder fromdgxand from Thor, so a checkpoint placed there once is visible to both and no host-to-host copy is needed at all. The recipe this replaced moved weights dgx→Thor withtar -ch | ssh ... tar -x, which is the bypass; its footnote that the reimage changed the host key is history rather than an instruction. -
Oracle CAVEAT UPDATE (2026-08-12,
CLAIM-MM-SPEED-AUDIO-ENC-FA2): both venvs import cleanly now —vllm-oracle-nextreports0.23.1rc1.dev1511+g555967922. That string is asetuptools_scmnearest-ancestor-tag artefact, NOT an identity mismatch: HEAD is5559679229bc, which IS the pin, and setuptools_scm names a dev build after the newest tag reachable from the commit, not after the release the commit belongs to. Assert the oracle BY COMMIT, never by version string — the recorded0.26.0.dev0string will not match and nothing is wrong. Its source tree~/work/vllm-src-5559679is present again (890 MB). -
soundfile==0.14.0is required in~/venvs/vllm-oracle-nextfor Voxtral (2026-08-12). Without it the pin cannot tokenize the audio prompt at all, so the pinned oracle is not gateable for the Voxtral vehicle. Installed; recorded here and against issue #375.~/venvs/vllm-oracle-v0.25.0-stage(vLLM 0.25.0 + mistral_common 1.11.5 — the Voxtral golden-capture stack) ran a full teacher-force to completion, so the "crashes in EngineCore KV-cache/model init" below is at least partly a PATH artefact: in a non-login shell Triton's JIT diesRuntimeError: Failed to find C compilerAFTER the weights load, which surfaces asEngineCore failed to start. ExportCC=/usr/bin/gccalongside the documentedninjaPATH fix and it runs. Thevllm-oraclesymlink still points at the 0.25.0 rollback rather than the pin (issue #375, open). -
★
CC=/usr/bin/gccis STALE for the reimaged host, and the correction is to run the oracle IN A CONTAINER (2026-08-17,SPEC-MTP-K-GT-1). The bullet above is right about the failure and wrong about the cure on this host. Measured onkairos-17dd: there is nogcc, nocc, noclang, noninjaand nonvccanywhere on the host, and/usr/includecarries neitherstdio.hnorpython3.12/Python.h, so there are no glibc headers and no crt objects either. ExportingCC=/usr/bin/gcctherefore names a file that does not exist. Triton 3.7.1 in the pinned venv ships onlyptxas/cuobjdump/nvdisasm, no C compiler, so nothing in the venv supplies one. What this looks like if you do not know it: the weights load, the engine then diesRuntimeError: Failed to find C compiler, and vLLM reportsEngine core initialization failed. See root cause above. Failed core proc(s): {}. That is an INSTRUMENT failure wearing the shape of a verdict about the model. Do NOT reach forenforce_eagerto get past it: it is forbidden as a denominator, and it would silently change the thing being measured. The cure, and the shape~/rs35b/run_oracle.shalready used: run the host venv insidenvidia/cuda:13.0.1-devel-ubuntu24.04withpython3 python3-dev ninja-build build-essential libnuma1installed,-v $HOME:$HOME,CC=/usr/bin/gccand/usr/local/cuda/binonPATH. The image ships python 3.12.3, which matches the venv'spyvenv.cfgexactly, so the HOST venv resolves inside the container. Bake the toolchain into an image (~/mtpgate/Dockerfile.oracle,mtpgate-oracle:1) rather thanapt-geting it per leg: a leg that must reach the network to start can fail for a reason that has nothing to do with the measurement. AssertgccandninjaINSIDE the container before the model loads, so a broken image aborts by name instead of four minutes later as an engine error. Container egress WAS available on 2026-08-17; the box has been recorded without it before, which is the argument for baking rather than installing. ★ AND THE PINNED ORACLE CANNOT CURRENTLY LOAD A 27B HERE AT ALL: it eats the WHOLE MACHINE in the step aftertorch.compile, andgpu_memory_utilizationdoes NOT control it. Measured the same day, once the toolchain fix let an oracle get that far for the first time. Atgpu_memory_utilization=0.75the engine held about 110 GiB of HOST RAM whilenvidia-smireported only 26 GiB on the device, hung 45 minutes at loadavg 260 with 0 GiB available, andsshdstopped completing a banner exchange while the box still answered ICMP. Killing the container took it from 118 of 119 GiB used to 4 of 119 in under ten seconds. The obvious attribution to that 0.75 was tested and REFUTED. A second run at 0.30, with a 5-second host-memory sampler running, collapsed the same way:avail_mb87683 at 09:00:47 and 0 at 09:02:25, loadavg 1.19 to 39.90. Weight loading finished with 66 GiB free andtorch.compilefinished with 88 GiB free, so the collapse is neither of those. It is the step immediately AFTER compilation and it is insensitive to the KV-pool fraction, which points at the profiling forward and the graph capture (max_num_batched_tokens=8192,cudagraph_capture_sizes: [1, 2, 4, 8], every allocation host-backed here). That last part is a hypothesis with a located step, not a result. Vary those one at a time with the sampler running and believe nothing without an A/B. The 0.75 run THRASHED for 42 minutes and survived (boot_idanduptimeunchanged); the 0.30 run REBOOTED THE BOX —boot_idmoved5bbdc432…tobd5c6e7a…andjournalctl --list-bootsshows boot-1ending 09:10:15Z against boot0beginning 09:13:55Z. So a lower fraction is NOT a safety margin: assume the box is at risk on every attempt. Always run aMemAvailablesampler beside any load here;nvidia-smiis blind to all of it, and the sampler is what turned a 45-minute mystery into a timestamped 100-second collapse. While sshd was answering intermittently one connection returnedPermission denied (publickey); that is a memory-pressure artefact, not a credential problem, and the same key worked seconds after the reboot. A cleanup trap is not a stop button. Both DGX drivers usedtrap cleanup EXIT INT TERMwherecleanupresets the clocks and RETURNS, soSIGTERMreset the clocks and the script then started its NEXT leg on a box with no memory left. Put anexiton the signal path, anddocker killthe current named container inside the handler:timeoutsignalsdocker run, and the container outlives it. -
Oracle CAVEAT (2026-07-27): the pinned vLLM oracle on dgx.casa was found DEGRADED —
~/venvs/vllm-oracle→vllm-oracle-next(0.26.0.dev0) is an editable install whose source tree~/work/vllm-src-5559679was pruned (dangling;import vllmfails), and~/venvs/vllm-oracle-v0.25.0-stage(vLLM 0.25.0) now crashes in EngineCore KV-cache/model init. A fresh teacher-force could not be run this session; the sm_110 near-tie verdict rests on the COMMITTED gap-0 golden. Repair the oracle before the next gate that needs a fresh capture.
-
-
Ettore Apple/Metal profile:
ssh 192.168.68.103— Mac mini, Apple M4 (10 CPU cores), 16 GB unified memory, arm64, macOS 26.5.2. Use it for the MLX-backedvt::backend, Metal op parity, and small-model bring-up. It cannot hold the 27B/35B gate models; gate-scale Apple performance needs a larger-memory Mac. Re-verified 2026-07-22 (CLAIM-BACKEND-FANOUT-1), correcting the stale 2026-07-10 line: only the Command Line Tools are installed, NOT full Xcode — so the offlinemetalshader compiler is absent (xcrun -sdk macosx metalfails). That does not block MSL: runtime compilation vianewLibraryWithSource:was verified working, together with a numerically correct dispatched compute kernel. CMake IS already installed (brew 4.1.0 at/opt/homebrew/bin, missing from the non-interactive PATH — alwaysexport PATH=/opt/homebrew/bin:$PATHin remote commands);ninjais not (make works). MLX is NOT installed (brew install mlx-> 0.32.0, pullspython@3.14) and is not required for native-MSL bring-up. Device facts:hasUnifiedMemory=YES,MTLGPUFamilyApple9+Metal3, SIMD width 32, 32 KiB threadgroup memory, 11.84 GiB recommended max working set, ~30 GiB free disk. Our tree configures AND builds there under AppleClang 21 with three Clang-only-Werrorfixes, and 108,952 portable-tier assertions pass. Updated 2026-07-22 (W0 landed): the FULL tree (library + every test) now builds-Werror-clean on the M4 with the Metal backend ON, and the fix count is seven, not three — a full build surfaced four more than the spike's lib-only probe (see the fan-out spec § Work breakdown "W0 landed"). Configure with plaincmake -S . -B build -DCMAKE_BUILD_TYPE=Release:VLLM_CPP_METALdefaults toAUTOand turns itself ON for an Apple host with an ObjC++ compiler. Add-DVLLM_CPP_METAL=OFFfor a CPU-only A/B.TWO PRE-EXISTING macOS TEST GAPS — expected failures, not regressions. Both fail identically with
-DVLLM_CPP_METAL=OFF, i.e. they are unrelated to Metal, and neither is fixed yet:test_serve_low_tools— the Python bench tooling calls Linux-onlyos.sched_getaffinity(tests/tools/test_gdn_packed_component.py) andPOSIX_FADV_DONTNEED(tools/bench/drop_file_cache.py).test_safetensors—MappingRssKbreads/proc/self/smaps, which macOS does not provide, so it returns 0 and the RSS assertions cannot hold.
test_capiandtest_openai_conformanceare ctest-PARALLELISM flakes on this box (and on Linux); they pass on rerun. Preferctest -j 3here, on this 16 GB Mac mini only — it is not general advice, and in particular the DGX profile above requires-j 1because its unified memory OOM-reboots the box under a parallel CUDA suite.test_engine_core_procis likewise a timing flake under heavy parallel ctest: the case "EngineCoreProc: abort-mode shutdown aborts in-flight requests" (test_engine_core_proc.cpp:315) races the busy-loop teardown against the abort-output enqueue and intermittently missesabort_seen(measured ~1/5 in isolation under load, 2026-07-28); it is a pre-existing test-side timing race (untouched by the C7 sampling work) and passes on rerun. A dedicated fix would make the loop block for the abort frame (bounded wait) instead of a best-effort non-blockingtry_getsweep.LOCALAI WORKER — must be DOWN for any timing/benchmark work on this box (user-directed 2026-07-22). It is a root LaunchDaemon, not a container and not a user LaunchAgent:
Unit system/com.localai.workerPlist /Library/LaunchDaemons/com.localai.worker.plist(root:wheel)Program /Users/mudler/local-ai/local-ai worker(a NATS-driven worker)Properties `keepalive Log /Users/mudler/local-ai/worker.logState observed 2026-07-22 running, PID 327, RSS ~51 MB, up 1d08h, MEASURED idle: 0.0% CPU, and ioreg IOAccelerator PerformanceStatisticsreportsDevice Utilization % = 0,Renderer Utilization % = 0,Tiler Utilization % = 0— it holds NO GPU work. Log shows only periodicNATS backend.listevents (~1 per 6 h); no model loaded# inspect (works WITHOUT root) launchctl print system/com.localai.worker # stop (NEEDS root; bootout, because KeepAlive would restart a killed process) sudo launchctl bootout system/com.localai.worker # restore to the observed state sudo launchctl bootstrap system /Library/LaunchDaemons/com.localai.worker.plist launchctl print system/com.localai.worker | grep state # expect: runningNOT STOPPED during W0, for two reasons, both recorded deliberately: (1) stopping it needs an interactive
sudopassword and this box has no passwordless sudo (sudo -n true-> "a password is required"), so an agent cannot do it unattended; (2) W0 took no timing measurement whatsoever — every gate is a functional/correctness assertion — so contention could not affect any recorded result. The next agent doing MLX-vs-ours benchmarking MUST get the user to run the bootout above first; any Metal timing taken with this daemon up is VOID. Note also threeactions.runner.localai-org-*GitHub Actions runners as user LaunchAgents (PIDs 599/600/601) which can start CI jobs on this box at any time — quiesce those too before a benchmark series (launchctl bootout gui/$UID/actions.runner.localai-org-<name>.<label>).STILL NOT STOPPED as of the 2026-07-22 MLX baseline run — same reason (no passwordless sudo). The MLX numbers in docs/BENCHMARKS.md are therefore recorded
BLOCKED-ON-SUDO/ INDICATIVE, not binding; the recipe is a one-command re-run once the user boots the daemon out. Second contender found the same session and not anticipated by the earlier note: the desktop aerial video wallpaper —WallpaperAerialsExtension(PID 472, 8.2% CPU) plusVTDecoderXPCService(PID 518, 2.2%) — decodes video continuously and touches the GPU; it is the actual source of the ~1.47 load average on an otherwise idle box. Disable it (System Settings -> Wallpaper, or log the console user out) before any binding run. It was left untouched.MLX IS NOW INSTALLED (2026-07-22), via the venv route as recommended — brew was NOT used, so
python@3.14never entered/opt/homebrew/binand the PATH our macOS builds use is unchanged:/usr/bin/python3 -m venv ~/mlx-venv && ~/mlx-venv/bin/pip install -U pip mlx-lmResolved versions mlx0.29.3,mlx-metal0.29.3,mlx-lm0.29.1 — the CLT python 3.9.6 caps the resolve BELOW brew's 0.32.0. Record this: an unpinned competitor arm is not a floorLocation ~/mlx-venv(off every build PATH),~/hf-cache(3.2 GB model cache)Model mlx-community/Qwen3-1.7B-bf16@ rev9cd6692855d3e06772228e9a962b2606359b2d24Ships prebuilt mlx/lib/mlx.metallib104,894,650 bytes +libmlx.dylib— so CONSUMING MlX needs no Xcode, but BUILDING it from source does (xcrun metal), which this box cannot doDevice probe mx.metal.device_info()->applegpu_g16g,max_recommended_working_set_size12,713,115,648 (11.84 GiB),max_buffer_length9,534,832,640Removal rm -rf ~/mlx-venv ~/hf-cache— neither is on any PATH our builds consult
Benchmark models on Ettore's dgx.casa profile
~/.cache/huggingface/hub/models--nvidia--Qwen3.6-35B-A3B-NVFP4(snapshot complete, ~22G, 3 safetensors shards — re-downloaded 2026-07-03 after the original snapshot was found incomplete)~/.cache/huggingface/hub/models--unsloth--Qwen3.6-27B-NVFP4~/work/apex/qwen36_35b/Qwen3.6-35B-A3B-APEX-*.gguf(GGUF-gate inputs)~/.cache/huggingface/hub/models--Qwen--Qwen3-0.6B(fast tests)
Gate model architecture (from GGUF metadata, arch qwen35moe)
40 blocks = 10 × (3 GDN + 1 full-attn); hidden 2048; full-attn GQA 16q/2kv, partial RoPE 64 dims (MRoPE sections [11,11,10,0]), rope base 1e7; MoE 256 experts top-8 + 1 shared (expert FFN 512); GDN: conv kernel 4, 16 groups, inner 4096, state 128; context 262144.
Prior art on Ettore's dgx.casa profile (mudler's llama.cpp patch series — mine for GB10 kernels)
~/killgate_series/— NVFP4 W4A4 FP4 MMA prefill, qwen35moe NVFP4 quant/dedup, MoE decode regraph~/llama-phase93-qwen3next-gqa-bcast~/llama-phase84-attn-only-source
TODO
-
Binding immutable
3f256abremains 55/124 axes pass, 69 fail against vLLM v0.25.0. Finalized c2 root179a0fcalready maps the executed path and selects the complete 193 vs 97 GDN projection mismatch. W1 merged BA is implemented/GATING. Clean pushed581d335under~/work/vllm.cpp-gdn-ba/immutable-581d335…passes the exact CUDA 13.0.88 / CUTLASS / Triton-AOT build, packed F32/BF16 capture/replay, strict memcheck, merged/split 27B and inert native-35B gates; the isolated BF16/decomposed control fails the token near-tie. Immutable0091cd1, finalized by pushed8a1f923, iscomplete-structural: both exact-c2 arms pass all 24 local range contracts at merged 963/145 versus split 1,011/193, with 48 BF16-only removals and unchanged selected non-BF16 families. Cleanf344deccloses packed W1D2/G2 for default+rollback 27B 235/235, 35B/GGUF inertness and strict safety.benchmark_binding=false. Close paired node traces and the c2/c16 component before qkvz. Independently remove 22.920 GiB host-weight mirror and overlapping source pages. No 35B performance command runs before all 27B axes pass. -
Keep the existing SGLang v0.5.13 P1 evidence immutable. The distinct shared-prefix gate pins v0.5.15
f63458band image digestd0a667e; its PX1 deterministic 64k/256k harness/counter work is ready after the priority cache-off closure. Write the dedicatedKV-MAMBA-ALIGNspike before PX2, then require matched BF16/no-spec capacity, native hit/no-eviction evidence, full axes and traces. Never mutate the vLLM oracle while provisioning SGLang. -
Bootstrap CMake + MLX on the M4 host before the Metal backend bring-up.RESOLVED/SUPERSEDED 2026-07-22 by the backend fan-out spike: CMake is already present, and MLX is not a bring-up prerequisite (native MSL compiles at runtime with CLT only, so E2 precedes E1). The real prerequisite is spike work itemW0— chiefly theCMakeLists.txt:304-306Apple-force_loadfix, without which every static registrar is silently dropped on macOS and even the CPU backend fails to register.brew install mlxis deferred to work rowM5. CLOSED 2026-07-22:W0LANDED — the-force_loadfix is in andtest_backendis 7/7 on the M4, so the M4 is fully usable for backend work. REOPENED in a different role: MLX must now be installed on the M4 as the competitor BENCHMARK arm (user directive;BACKEND-GATE-METAL-MLXLM), which is independent of its demotion as an implementation path. Use the venv route recorded in the M4 entry above, and stop the LocalAI worker daemon first. -
Vulkan runtime is already usable and needs no acquisition. dgx GB10 enumerates as a real Vulkan
INTEGRATED_GPUat API 1.4.312 (loader 1.4.328 + NVIDIA ICD) withVK_KHR_cooperative_matrixv2 andVK_NV_cooperative_matrix2; the dev box enumeratesllvmpipe(Vulkan 1.4.318, CPU) for GPU-free CI. Optional still:libvulkan-devandvulkan-tools(neither is needed to build or gate — the backenddlopens the loader and vendors the Khronos TYPE headers). -
Vulkan shader toolchain — glslang 16.5.0, installed 2026-08-06 (
VK-A1).$HOME/tools/glslang-16.5.0/bin/glslang, from the upstream prebuilt Linux x86_64 release tarball; no root, nothing linked (it is a build-time tool, never a dependency —.agents/discipline.md). Put that directory onPATHto regenerate committed SPIR-V withscripts/gen-vulkan-spirv.py. Two measured facts about the pin. (1)src/vt/vulkan/vulkan_spirv.h:16recordsGlslang Version: 11:16.4.0, but 16.4.0 ships NO release assets — only16.5.0andmain-totdo, and Ubuntu packages15.1.0— so the recorded version cannot be fetched and cannot back a CI gate. (2) The committed SPIR-V nonetheless reproduces byte-for-byte under 16.5.0 (--checkpasses, exit 0), which proves the committed artifact is what it claims AND that the emitted SPIR-V is stable across a glslang minor bump. The freshness gate therefore pins the DOWNLOAD URL rather than asserting a version string. The older note here — that Ubuntu's shaderc 2023.8glslcis too old for the coopmat2 feature probe — still holds and is why the system package is not used. -
dgx Vulkan/llama.cpp comparison toolchain (2026-08-07,
VK-E). apt:glslc,glslang-tools,libvulkan-dev,spirv-headers. Ubuntu'sglslcis shaderc 2023.8 and is NOT USABLE for a fair llama.cpp-Vulkan build — it disables FOUR of five fast paths (GL_NV_cooperative_matrix2,..._decode_vector,GL_EXT_integer_dot_product,GL_EXT_bfloat16), leaving onlyGL_KHR_cooperative_matrix, and the build still configures and runs. A source-built shadercv2026.4-devlives at/tmp/shaderc/b/glslc/glslc; pass-DVulkan_GLSLC_EXECUTABLE=to it. Verify the runtime banner saysmatrix cores: NV_coopmat2before trusting any number. llama.cpp is unpacked at~/lcpp-vkwithbuild-vk/bin/llama-benchbuilt, and that tree is the SUPERSEDED fork237ad9b96, not the pin. Do not reuse it. The llama.cpp oracle is stockb10451since 2026-08-16 (oracles/llama-cpp.md).237ad9b96is a local-only commit on the developer'slocalai-pagedbranch, 65 of our own performance commits past upstreamb9827, built from a working tree with 27 uncommitted entries.~/lcpp-vktherefore reproduces neither the pin nor any identifiable object. TheBENCH-VK-LLAMAdecode4.36 vs 4.35 METmeasured with it is the most fragile verdict in the enumeration, a 0.23% margin inside a 0.69% spread, and re-taking it is owed under #1003. Unpack the pinned SHA fresh and assertgit status --porcelainempty before recording any number. Enumeration and the clean-tree rule:specs/oracle-llamacpp-repin-stock.md. -
No Intel GPU exists on any box here, so
BACKEND-XPUend-to-end work is HW-BLOCKED; only policy-port, compile coverage and oneAPI CPU-device unit numerics are available.