Changelog archive — 2026-10-08 through 2026-10-12#
Entries moved out of the root CHANGELOG.md on 2026-10-17 so the live file stays
readable (its own rule: archive past ~700 lines, never delete). Newest-first, running
back to where changelog-archive-2026-10-07.md picks up. One mechanical edit, no
rewording: relative links are re-based on this directory.
2026-10-12 — ai-edge-litert for Python 3.15, built from source with clang-cl (CON91)#
The Windows images build ai-edge-litert themselves. No release has a cp315
win_amd64wheel or sdist, so media-litert’s second RUN builds upstream’s own target//ci/tools/python/wheel:litert_wheelatLITERT_VERSION(Build-LitertWheelBazel.ps1). The merge copies the wheel intoC:\runtime\wheels, and the torch venvs install it.Compiler and pins:
Bazel 7.7.0 (pinned by SHA256) builds with its own clang-cl toolchain from
C:\llvm-patched. An aquery gate fails the stage on any action that is not clang-cl, lld-link or llvm-lib.Bazel’s hermetic Python is the image’s CPython 3.15, with a hash-pinned numpy/setuptools/wheel lock.
Only the closed-source WebGPU accelerator comes from the pinned PyPI wheel.
The floating
@litert_prebuiltszip and the unhashed OpenVINO nightly are never fetched.
Proven by probe P12. The production driver built the wheel in 272 s (530 s for the RUN); all 4522 compile, link and archive actions ran LLVM tools. It passed the wheel contract and a CPU smoke through both Python APIs.
The rocm check now needs CompiledModel and Environment.create(). An interpreter-only wheel with the accelerator copied in can no longer pass it.
WindowsBazel.Commonnow owns the helpers both bazel drivers share. Rides the next chain.
2026-10-12 — the torch venv’s sdists compile with clang-cl and link (CON93)#
The in-tree CPython links extensions like an install. Under 3.15, line-profiler 5.0.2 and pyyaml 6.0.3 have no cp315 wheel, so the torch stage’s
uv syncbuilds them. setuptools then failedLNK1104 python315.lib: it links againstsys.base_exec_prefix\libs, which the in-tree build lacked. The toolchain stage now copiespython3XY.libandpython3.libthere (Install-CpythonInTreeImportLib), and smoke section 2 checks them.The sdists compile with clang-cl, not VS’s cl. setuptools took VS’s
cl.exeandlink.exe. The torch stage now syncs with copies of clang-cl, lld-link and llvm-lib first onPATHascl,linkandlib, underDISTUTILS_USE_SDK. A gate fails the stage when a PE of a distribution uv built from source carries MSVC’s Rich header. Probe P13 built and imported line-profiler that way on the 3.15 image. Rides the next chain.
2026-10-12 — meson in the Windows images verifies TLS through CryptoAPI (CON88)#
truststore beside every meson the chain installs. Python in Server Core trusts only the store’s 18 roots, so meson’s
oggwrap failedCERTIFICATE_VERIFY_FAILEDon downloads.xiph.org (whose chain ends at emSign) and fell back to a GitHub mirror unnoticed. meson’swrap.pyuses truststore whenever it imports, and truststore lets CryptoAPI fetch the missing root. truststore 0.10.4 (PY_TRUSTSTORE_VERSION) now installs with meson in the GStreamer and FFmpeg-codec builds, media-core’s site-packages carry it into the image for consumers’ meson too, and smoke section 2 imports it besidemesonbuild. The next chain proves it: noCERTIFICATE_VERIFY_FAILEDin the merge log.
2026-10-12 — every pip install in the Windows chain is pinned (CON89)#
No build installs a floating Python package any more. FFmpeg’s codecs installed an unpinned
meson, and the ONNX Runtime, GenAI, OpenCV, IREE and TVM builds installed numpy, setuptools, wheel, packaging, requests, scikit-build-core, setuptools-scm, typing_extensions, ml_dtypes, cloudpickle and psutil at whatever PyPI served that day.Install-CpythonPipPin(WindowsSourceBuild.Common) installs each at itsPY_*_VERSIONpin and throws for a package without one; five pins are new (requests 2.34.2, typing_extensions 4.16.0, ml_dtypes 0.6.0, cloudpickle 3.1.2, psutil 7.2.2, each with a cp315, abi3 or pure wheel). The Cython both media branches install comes through it too.Build.PipPins.Tests.ps1fails on a bare package name in anyInvoke-CpythonPip install. Rides the next chain.
2026-10-12 — the LiteRT-LM bazel build fetches only pinned, checked tools (#185)#
bazelisk, the JDK and git-lfs are pinned by version and SHA256.
Build-LitertLmBazel.ps1took bazelisk fromreleases/latest, fell back to Adoptium’slatest/21/gaJDK when the pinned asset failed, and installed git-lfs through scoop; nothing was SHA-checked, so a cold tool cache took whatever was newest.Get-PinnedToolnow fetches bazelisk v1.29.0, Temurin 21.0.5+11 and git-lfs v3.8.0 from their release URLs, checks each against itsversions.envpin (the releases’ own digests), re-fetches a corrupt cache entry and refuses anything else. The pins reachmedia-litert-envas ARGs and stay out of the merge.
2026-10-12 — CON91, second half: the Windows build side names no Python, and the twin store is Linux’s#
The arm64 tvm-ffi wheels carry the pin’s tag.
New-TvmFfiCrossWheel’s tags defaulted to cp314: on 3.15 the GIL wheel would have been tagged cp314 around acore.pydlinkingpython315.lib, and the twincp314-cp315t. The GIL call passes the pin’scpXY, the twin’s python tag drops the ABI’st, and both tags are mandatory.No literal 3.14 is left on the build side.
Get-CpythonFreeThreadedExeName,Get-FreeThreadedAbiTagand the placeholderpython314.libtakeGet-PinnedPythonVersion; OpenCV’sFindPythonInterpstub asks the interpreter for its version;Test-Containerfails without a pin instead of grading 3.14.The twin store is
C:\runtime\wheels-free-threaded(PYTHON_WHEELS_FREE_THREADED), Linux’s name, in the merge stage’s ENV and COPY, both producers’ default, the ORT census, the bundle manifest and the smoke’s env contract. Every reader still takesPYTHON_WHEELS_CP314T, and the device gate thewheels-cp314tfolder of an older bundle.Test-Containerfails when the image names a store that is not there, where it skipped.
2026-10-12 — GStreamer compiles through sccache (#182), and two vendored builds stop flooding the logs (#183)#
#182: meson’s
compilers/detect.pykeeps ansccacheprefix for MSVC’s compiler class and drops it for clang-cl, so theCC='sccache clang-cl'of 2026-08-04 never cached a compile: 16 sccache requests for 5,143 ninja steps, and every merge rebuild compiled GStreamer cold (515-663 s).New-SccacheCompilerShimbuilds aclang-cl.exethat runs sccache with the pinned clang-cl and the caller’s arguments, meson gets it asCC/CXX, and the stage fails when sccache counted fewer than 100 compile requests. Proven by a local buildctl probe; the next chain proves it at scale.#183: the Vulkan validation layers’ and x265’s GCC-style
-Wallreaches clang-cl as-Weverything: the arm64 VVL alone was 6,228,195 lines, 752 MB of a 768 MB merge log, and x265 added 27,423-Wunsafe-buffer-usagelines to every ffmpeg branch. Both builds run withCL=/w, which clang-cl reads before its own flags and sccache does not hash, and restore the caller’sCLafter it. The first fix used_CL_, which clang-cl appends: behind CMake’s-- <source>the/wread as a file name and failed x265’s compiler check (bk-20261012-190400).
2026-10-12 — CON91, first half: the Windows drivers and syncs follow the Python pin#
Get-PinnedPythonVersion(WindowsPythonWheel.Common) is the Windows twin ofpython_pinned_major_minor: the image’sPYTHON_VERSION, elseversions.env, as X.Y,cpXYandcpXYt; no literal fallback. It is not inWindowsScripts.Shared, whichDockerfile.basecopies aboveInstall-Vs, so an edit there would re-key VS.The drivers name no Python.
Invoke-CiPackaging.ps1,Invoke-CiStaticAnalysis.ps1andInvoke-PythonTestLegs.ps1defaulted to 3.14; empty now takes the pin, and a leg list readspinned/pinnedtasci_tests.shdoes.python-ci-windows.yml’sarm64-python-versionsdefaults to empty (WebDavClient, its only caller, passes its legs).Test-ExperimentalPython’s default is the pin’s X.Yt.Inside our images the Windows sync installs no PyPI ORT, as Linux’s since 2227be6e:
Sync-UvProjectDependenciespasses--no-install-packagefor every ORT entry ofuv.lock(the unlocked retry too), and the reconcile installs the chain wheels for those, uninstalling only what reached the venv. PyPI’s onnxruntime has no cp315 wheel.The arm64 bundle’s pytest stack moves its three native wheels to cp315
win_arm64(PyPI’s SHA256s), andBuild.Arm64WheelStacktakes the stack’s tag fromPYTHON_VERSION: red on the cp314 pins, green on these.ai-edge-litert: no release has a cp315
win_amd64wheel, so the torch app stage leaves it out ofuv sync(with a warning) until the chain builds one from source (owner decision). The rocm lane’s PyPI extra and its cp314 pin are gone; the pin becomes the source build’s accelerator carrier, and the accelerator DLL’s own SHA256 is pinned (the same bytes in the cp313 and cp314 wheels).Torch.Rocm.Tests.ps1is green again.
2026-10-12 — the LiteRT layer exports in 53 s instead of 19 min (#181); #184’s review fixes#
#181: bazel’s trees leave the LiteRT layer.
Build-LitertLmBazel.ps1leftC:\bzl(the output base),C:\llm(the checkout with its git-LFS prebuilts),C:\bzl-toolsand the bazel log in the layer, and the merge copies onlylib\litert-lmout of it. After the install’s contract check,Remove-LitertLmBuildTreenow stops the bazel server’sjava.exeand removes them; a junction inside never takes its target along (tested). On a local media-litert stage (bk-20261012-152007) 8.7 GB left the layer, and its export took 52.9 s against 1,126 s. The unpack, 1,047 s there, varies with the host. Bazel’s output streams to the stage log, its progress throttled to one line per 30 s, whereSelect-Object -Last 20used to hide 450 s.#184’s adversarial review found four defects, all fixed.
A throw between stages was charged to the stage that had just passed.
The failure manifest could read a caller’s
$started.A snapshot-mount contention retry was recorded twice.
-ConcurrentAuxchildren shared one driver log and manifest. The parent now passes-ParentRunId, and a child’s run is<parent>-<branch>.
The manifest culture test runs under de-DE, so an en-US runner catches that regression too. The first real run with the driver log showed
done in 2.415,0s, so its timed records are culture-invariant now.
2026-10-12 — the patched clang-cl relinks reproducibly (#180), and a stopped BuildKit run keeps its record (#184)#
#180: LLVM builds with the pinned clang-cl, so
/Breproapplies. CMake’s default compiler for the patched LLVM was MSVCcl, and LLVM’sHandleLLVMOptions.cmakeappends/Breproonly for a Clang compiler. Every relink therefore stampedclang-cl.exewith the link time, and sccache, which keys on the compiler’s bytes, missed nearly every media compile after a toolchain re-run (#153: onnx 9/1332, litert 0/5374).Build-LlvmFromSource.ps1now names the base image’s clang-cl (LLVM_USER_BIN) and refuses to fall back tocl.Assert-ReproducibleLinkfails the stage whenclang-cl.exestill carries a link-time PE stamp. A local toolchain stage (bk-20261012-144845) compiled LLVM cold with clang-cl in about 12 min, and the newclang-cl.execarries the content hash 0x35341D1A. This re-keys the toolchain stage, so the next full chain rebuilds the media lane once (CON89).#184: the driver records what the console alone lost.
The manifest carries
status=ok, or, written from thefinally,status=failed:<stage>with every finished stage. Stage seconds use the invariant culture: a German host wrotepatched-llvm=778,9besidetotal_s=13058.bk-<run>-driver.logrecords the run, stage starts, ends and failures, retry verdicts with the line that made them transient, and disk-gate verdicts.The resource CSV gains
diskFreeGB, and the summaryMinDiskFreeGB.buildctl’s output is decoded as UTF-8, so an em dash no longer arrives as
ÔÇö.
2026-10-12 — CON90: consumers name no Python version, and the image’s ORT no longer waits for PyPI#
pinnedin a leg list.ci_tests.shreadspinnedas the pinned X.Y andpinnedtas its twin, so a row that picks its legs (OrchestrANT’s riscv64 row wants the GIL one only) names no version;ci_build_docs.shpublishes the default leg’s reports aspytest-report.html/.mdandpytest-report-free-threaded.htmlbeside the versioned ones.Inside our images the Linux sync installs no PyPI ORT.
uv_sync_projectpasses--no-install-packagefor every ORT entry of the lock whenORT_CHAIN_WHEEL_DIRis set, and the reconcile installs the chain wheels in their place. Measured with uv 0.13.0 on python-build-standalone 3.15.0: a locked sync of a lock naming onnxruntime 1.31.0 fails (only has wheels with ... cp314, cp314t), and with the flag it syncs the rest. A free-threaded venv also finds the twins under the older images’PYTHON_WHEELS_CP314T. Windows’ sync: BACKLOG CON91.
2026-10-12 — CON90: Python 3.15.0, and an upgrade is one line#
PYTHON_VERSION=3.15.0(owner request; released 2026-10-09).PYTHON_TGZ_SHA256was computed from python.org’s tarball twice, by hand and bybump_versions.py. uv moves to 0.13.0, the first release that knows 3.15.0; numpy to 2.5.4, which ships cp315 and cp315t wheels (its twin-table row re-read at that pin).The images ship the source-built interpreter on every arch.
Dockerfile.packagemounts the toolchain’s staged/opt/python-cross/<arch>into its setup RUN, andinstall_staged_target_pythoninstalls it without the fat-LTO static libpython and checks it reportsPYTHON_VERSIONexactly. The distropython3(Ubuntu’s 3.14) stays apt’s alone. arm64 and riscv64 no longer copy apt’s numpy, gi, cairo and contourpy into the venvs (they were built for the distro interpreter); uv builds them from sdists, and thepycairo==1.27.0constraint that matched apt’s copy is gone.Nothing else names a version. X.Y, the wheel tags and the drivers’ defaults derive from the pin (
python_pinned_major_minor,PYTHON_ABI_TAG/PYTHON_FT_ABI_TAG);ci_tests.shruns X.Y, plus X.Yt for a project that declares free-threading; the free-threaded store is/opt/wheels-free-threaded(PYTHON_WHEELS_FREE_THREADED), which Windows’ readers take first too; the uv seed, the app bundle, the GStreamer cross paths, the smokes and the hub’s own workflows read the pin; Renovate’s rule names no version;bump_versions.pyrefills the tarball checksum after a hand-edited minor.Dockerfile.toolchaindeclares the Python ARGs right above the CPython RUN, so the next upgrade leaves GCC, LLVM and Rust cached. The procedure:docs/python-ci.md§ Upgrading Python.Not built yet: the chain (BACKLOG CON90), and the Windows half (CON91).
2026-10-12 — CON42: nvblender stays unusable, and the helper libraries stay out of lib/gst-plugins/#
Two owner calls, taken with the recommended option:
No
nvblendershim. TheLD_PRELOADshim that restoresGstMapInfoafter unmap makes its blends succeed, but it switches GStreamer’s check off for every caller in the process, and the two-input hang is NVIDIA’s own (1.24.2 too).nvblenderstays documented as “do not use”; a forum draft for NVIDIA waits for the owner’s review, unposted.NVIDIA’s stock configs keep needing one edit. A plugins-only link target would let
config_preprocess.txtnamelib/gst-plugins/libcustom2d_preprocess.sounchanged, but the registry scan would then segfault for anyone who puts NVIDIA’s documentedlib/gst-plugins/onGST_PLUGIN_PATH(itdlclose()s the helper libraries). The stock config fails loudly instead (Could not parse custom lib path), anddocs/consumer-image-contract.mdnames the edit.
2026-10-12 — CON66: the suite on the installed cp314t wheel is a hub step#
linux/scripts/02-toolchain/python/test-free-threaded-wheel.shruns a project’s tests on thecp314twheelci_packaging.shleft indist/: a fresh venv of the image’s free-threaded interpreter gets the lock’s set (uv export --locked --no-emit-project,--extraif given) and the wheel with--no-deps, and pytest runs in a directory outside the checkout that holds only the--copypaths, so the sources cannot shadow the compiled modules.--envreaches the pytest process,--isolatedaddspython -I, and the arguments after--go to pytest. It skips where the driver builds no twin (a cross build,PYTHON_FREE_THREADED_WHEEL=off,autowithout the classifier), and fails on a declared project without acp314twheel of this arch. It replaces OrchestrANT’sci_free_threaded_wheel_tests.shand WebDavClient’stest-free-threaded-wheel.sh, which differed only in those knobs (docs/python-ci.md§ The suite on the installed wheel).tests/test-python-free-threaded-wheel-tests.sh, 36 assertions, drives it against a fake uv.
2026-10-12 — CON83 closes: OrchestrANT imports pyplot lazily, its other two calls stay#
import orchestrantloads nomatplotlib.pyplot(OrchestrANT 9dbb86b). pyplot was 0.72 s of the import’s 0.80 s on x64, and under riscv64 QEMU the import cost 31-37 s per subprocess (bench_agent.py --listtook 41.9 s against a 60 s timeout). Now 86 ms on x64.MetricsPlotterimports pyplot on its first plot, and a test fails when the package import loads it again; no test patchedplotting.plt, and the Cython build needs nothing new.The other two owner calls stay as they are. bench_agent’s own grading keeps the venv’s pytest plugins: its self-tests already disable their autoload for nested runs, where the QEMU cost was, and a native run pays 1 s, so a change would only move verdicts against older reports. The process ceiling stays probed once per process, so it cannot drift between launch and assertion (
bench_coding._nproc_ceiling).
2026-10-12 — two WCOW probes settle #177’s precondition and narrow #179; clang-cl needs initialize() first#
#177: a secret reaches a Windows RUN as an env var, and leaves no trace. A buildctl probe over
bk-windows-toolchain(buildkitd v0.33.0) setsSCCACHE_WEBDAV_ENDPOINTthrough--mount=type=secret,…,env=in its RUN. The next RUN no longer sees it, and no file is left behind. The file form (target=) does leak on WCOW: the file stays in the snapshot, so the next RUN reads it and the layer carries it. Left: the ten compiling stages, at one planned re-key.#179: the ~120 s tail follows sccache’s graceful end. One RUN per variant shows the tail with
sccache --stop-serveron either backend, with or without a compile, and with the server process already gone. A server killed withStop-Process -Forcecosts 1 s, as no sccache does. TIME_WAIT under Windows’ 120 sTcpTimedWaitDelayis the leading suspect, not yet isolated.docs/python-ci.md: a project that sets the compiler’scctoclang-clmustinitialize()it first. The firstcompile()initializes lazily and putscl.exeback. OrchestrANT (563e0fb) and WebDavClient (3a7aa8c) compiled their first extension with MSVC’scluntil today. setuptools 84 never calls aspawnhook, so one cannot catch it.
2026-10-12 — #153 closes on three fresh chains; CON75’s wheel loads on the device#
#153, the step-time and silent-retry sweep, is done. The 2026-09-01/02 logs it named were pruned, so it read the three complete chains left: bk-20261011-184301 and bk-20261011-233025 (amd64, the second rocm) and bk-20261010-121545 (arm64), 51 logs in all. The 441.3 s lifecycle floor is gone, since a trivial RUN takes 4.9 to 9.0 s. One silent retry turned up in three chains: an
ActivateLayer 0x20on rocm-llama’s first RUN, green on attempt 2/3. No log has clipped output.What it found beyond its question is seven new rows,
docs/windows-refactor-backlog.md#179 to #185:#179: every RUN that started an sccache server idles ~120 s before DONE, 16 to 27 min per chain.
#180: a toolchain re-run relinks clang-cl, and the media stages then compile almost cold.
#181: the LiteRT layer keeps bazel’s output base and checkout, which costs 25 to 44 min of export.
#182: GStreamer’s meson build bypasses sccache on both arches, although the docs called it done.
#183: vendored code compiles under clang-cl’s
/Wall, so the arm64 VVL vertex is 97.9 % of a 768 MB log.#184: the driver keeps no manifest of a failed run.
#185: bazelisk, the LiteRT JDK fallback and git-lfs are fetched unpinned and unchecked.
CON89 points at #183 and #185, and the failure-modes and lanes docs are corrected where the sweep contradicts them.
CON75 is done. OrchestrANT run 38221408508 (9964cc1, hub 7a5ab23c) built
cp314-cp314t-win_arm64on the cross lane. Itswindows-11-armjob imported all 64 compiled modules on free-threaded 3.14.8 with the GIL disabled.
2026-10-12 — the arm64 device gate runs an inference, not only an import (CON30)#
Test-Arm64Bundle.ps1has an eighteenth step, and the floor follows to 18. It builds an ONNX Runtime session overTest-Container.ps1’s 63-byte Identity model and asserts thatIdentity(42.0)returns 42.0 on the CPU EP. The step before it only imported onnxruntime and listed its providers, which proves the DLLs load and nothing computes.DirectML is tried first and its outcome printed, never graded: a
windows-11-armrunner has no adapter. The CPU run is the step’s last command, so its exit code alone decides, also under the workflow’s$PSNativeCommandUseErrorActionPreference. In:winamd64the step passed with DirectML falling back onNo devices detected that match the filter criteria.Get-IdentityOnnxHexinTestHarness.psm1reads the model’s bytes fromTest-Container.ps1. The arm64 gate’s copy and the WebGPU probe’s are both held equal to it. A mutation test runs the step’s own body against a stand-in python that fails DirectML or the CPU run.docs/windows-cross-builds.md,docs/windows-refactor-backlog.mdandBACKLOG.mdCON30 no longer say that nothing executes on arm64 or that the gate has nine or seventeen steps. A camera and a GPU EP are what stays unproven.
2026-10-12 — the device gate’s twin proof installs again: a one-element array no longer splats into characters#
Since a2ce8627 (CON79),
Invoke-TwinDeviceProofbuilt pip’s arguments as$resolve = if (...) { @(...) } else { @('--no-deps') }. PowerShell unrolls a one-element array that anifreturns into a string, and@resolvethen splatted it one character per argument. pip refused-for all four twins, sowindows-arm64.ymlfailed three runs in a row (38180134179, 38205155401, 38209436310). OrchestrANT’s CON75 kit runs the same proof, so its device run would have failed the same way.Get-TwinInstallArgumentreturns the words as a[string[]]in every case. A behavioural test splats them intocmd /c echoand expects--no-depswhole, and--find-linkson the store and itsdeps\when that exists.WindowsFormatting.Common.psm1had the same shape: without a format config,$mode + @($cmakeFile)concatenated--checkonto the file name. It is wrapped in@()now.Lint.ScalarSplat.Tests.ps1scanswindows\scriptsfor anif/elsewith a one-element@(...)branch whose variable is splatted. It allows one known site, thevswhere -latestselector inWindowsScripts.Shared.psm1, and BACKLOG CON89 keeps it. That splat is why every chain logsvswhere returned no installation; using filesystem fallback. Fixing it re-keysDockerfile.base, so it waits for the next planned full rebuild.windows-arm64.ymlalso runs on a change toWindowsPythonWheel.Common.psm1, which the gate now imports.
2026-10-12 — the canonical .clang-format no longer reflows comments; CON71 is done#
shared/config/.clang-formatsetsReflowComments: Never, by owner decision today. WithtrueatColumnLimit: 120, clang-format split a one-line comment over 120 columns into two lines, whichverify_comment_size.pyrejects. OmniAccelerANT’s plugin sweep hit it (linux/runtime_paths.cc:1, shortened in its 39833e7).Neveris the spelling clang-format 23.1.3 dumps.Measured in
:latest(b52f8c34…) over each consumer’s format file set: nothing changes in AccelerANTgine (39 files) or OmniAccelerANT’s plugin (15). In BeschleunigerBallett 2 of 217 files change: three two-line trailing comments lose the alignment of their second line.shared/config/README.md§ReflowComments: Neversays to join such a pair into one line.CON71 is done and pruned from BACKLOG.md. The Linux half shipped in the
:latestof 2026-10-09 (hub 655a2c4e), the Windows half in:winamd64e96203a8…(21 tools at 23.1.3). Every consumer formats and checks with 23.1.3: AccelerANTgine e96b31b and its Linux format check, BeschleunigerBallett’s sweep d59d210f, and OmniAccelerANT’s plugin f3a0994 with its gate eca72a0.
2026-10-12 — tensorrt.conf only where a TensorRT build put its lib dir (CON31)#
The published
:latest-nvidia(23e3cc9e…) carried/etc/ld.so.conf.d/tensorrt.confnaming/usr/local/tensorrt/lib, which no nvidia build ships withENABLE_TENSORRT=false.configure-runtime.sh’swrite_tensorrt_confwrites it only when the lib dir exists, and removes a stale one otherwise; DeepStream’s TensorRT 10 keeps its own010-deepstream-tensorrt.conf.test-soname-precedence.shcovers both; the next nvidia chain proves it in the image.
2026-10-12 — DeepStream runs on the published :latest-nvidia; nvblender does not (CON42, CON31)#
The GPU run on the published image passed.
:latest-nvidia, index sha256:810f36b3 (amd64 sha256:23e3cc9e), ran as pulled on the RTX 2080 (driver 595.58.03, CDI, rootless nerdctl). Every row of the 2026-10-01 table holds:the gate engine was built for sm_75, and 1442 frames with 30214 objects went through
nvdsosd;the NvDCF tracker, the demux and
nvurisrcbinran, all as uid 1001 too;deepstream-verify.shwithDSV_WIRED=1passed with the GPU attached.
15 of the 21 prebuilt plugin files ran with sample data (CON42’s open question). All reached EOS with sound output, except the known legacy mux and:
nvblendertakes its output surface fromGstMapInfo.dataafter unmap, which GStreamer ≥ 1.28 clears. An unmap shim and GStreamer 1.24.2 each give it a valid surface.The AV1 encoder fails because Turing has none.
nvblenderalso stalls with two inputs on 1.24.2.Consumer facts, in a new
consumer-image-contract.md§ DeepStream in:latest-nvidia:The toolkit’s
enable-cuda-compathook may run CUDA on the image’s compat libcuda. DeepStream ran on it and on the host’s.A GStreamer registry scanned without a GPU keeps DeepStream blacklisted.
NVIDIA’s
config_preprocess.txtnames a helper path the image moved.nvdewarperneedsnum-surfaces-per-frameon the new mux.uid 1001 needs a writable engine path.
CON31: the published image has no TensorRT 11. Its only
libnvinferis DeepStream’s TensorRT 10.16.1, whichldconfig -presolves.tensorrt.confnames a/usr/local/tensorrt/libthat does not exist.docs/linux-accelerator-images.mdno longer calls:latest-nvidiaunpublished, and no longer claims the compat libcuda is for data-centre GPUs only.
2026-10-12 — the Linux backlog closes CON72, the CON83 lane and CON66’s consumer half; CON78 Linux and CON79 1b proved#
CON72 is done: every consumer is green on its post-image pin, Linux and Windows lanes alike: OmniAccelerANT 5a6492c, OrchestrANT b599448, WebDavClient 5ab44f4, BeschleunigerBallett b693d37, AccelerANTgine 2aefb1d/4b5dffd, OxidANT 4412001, jotrockenmitlocken 401acff.
CON79 1b is done: the
:latestof 2026-10-11 (index sha256:b52f8c34, run 20261011-125540) proves the riscv64 torch twin inFT-STOREand every cross twin on arm64 and riscv64.CON83’s lane is done: OrchestrANT run 38171396906 (riscv64) restored the uv cache seed, built no numpy, passed the cross wheel’s smoke and ran its bench rows with shellcheck and hadolint; 2539 tests green. The owner calls stay
[b].CON66’s consumer half is done: both consumers’
3.14and3.14tlegs logthe image's own interpreter, UV_PYTHON_DOWNLOADS=neveron x64 and arm64, OrchestrANT’s riscv643.14leg too, anduv_venv_create 3.14tin the published riscv64 child took/opt/python-freethreaded3.14.8 with the GIL off.CON78, Linux 0–3: read in the published
:latest-rocm—extras-10copied, no absolute or dangling link under/opt/rocm,000-rocm.confresolvinglibmigraphx_candlibamdhip64, the MIGraphX provider library loading.CON82’s last Linux item: OmniAccelerANT’s app flatpak (Linux x64 run 38158462860) and its cat cam flatpak (web run 38158462452, x64 and arm64, installed and removed by
test-catcam-package.sh) build onorg.freedesktop.Platform/26.08.CON84 (3): OmniAccelerANT’s Dart and Flutter floors follow its lock (467ca34), with the frb bindings and l10n regenerated rather than hand-formatted.
2026-10-12 — the Windows arm64 cross lane ships a free-threaded wheel and proves it on the device (CON75)#
Invoke-CiPackaging.ps1no longer skipscp314ton a cross arch. It startsNew-CrossFreeThreadedWheel.ps1, which builds the wheel and gates it.The build. The host’s x64 3.14t runs it in VS’s x64_arm64 environment, from a venv that pins
EXT_SUFFIXto the target. ADIST_EXTRA_CONFIGnames the target for everybuild_extandbdist_wheelinstance. The link uses the target tree’spython314t.lib.The gates. It checks the tags, the
python314t.dllimports and the ARM64 machine of every PE member.The kit. It packs the wheel into
dist\windows-arm64\free-threaded\with the target interpreter and the proof.
container-ci-windows.yml’s arm64 run job proves the wheel there withTest-FreeThreadedWheel.ps1. A product without the directory passes with one line.Invoke-TwinDeviceProofmoved fromTest-Arm64Bundle.ps1intoWindowsPythonWheel.Common.psm1, so the bundle gate and the consumer kit run one proof. The gate imports its modules throughImport-GateModule, andExport-Arm64Bundle.ps1packs the wheel module beside it.Get-FreeThreadedWheelPlantakes-TargetLib. A cross arch is skipped only when the image has no target tree.In
:winarm64(ba6bfaae…), OrchestrANT 0.0.30 builtorchestrant-0.0.30-cp314-cp314t-win_arm64.whlthis way. The wheel passed all three gates, and the kit came out complete. The project’s half is one line:clang-clneeds--target=aarch64-pc-windows-msvcon a cross build.
2026-10-12 — the rocm chain builds without the HIP/MSVC <cmath> overlay (CON78)#
Hub 28daad33’s
:winamd64-rocmchain (20261011-233025, then-Stages finalas 20261012-051453) built every stage with TheRock’s clang as AMD ships it, with noclang.cfgand no overlay:MIGraphX 2.18.0 and its EP in 11:44 min;
ggml-hipwith device code for gfx1201 and gfx1200;torch 2.14.1+rocm10.1.0 (HIP 7.16.26385) and torchvision 0.29.1 in 59 min.
Smoke gate: 265 passed, 0 failed, 1 skipped. All eleven rocm-checks passed, among them
kernel compiled for gfx1201. The publish gate was clean, and the image’s manifest iscea5c3fb….The first run stopped before the final stage on the disk gate: 18.4 GB free, below the stage’s 40 GB. BuildKit freed space on its own, so
-Stages finalran on cached stages at 46.8 GB.The llama stage’s first RUN failed at layer activation with
0x20(CON86), and the driver’s retry built it.
2026-10-11 — the arm64 bundle carries its cp314t twins’ dependencies (CON79)#
The
:winarm64bundle has shippedcp314ttwins of onnxruntime, av, apache-tvm-ffi and iree-base-runtime since 2026-10-07. Their dependencies were staged for cp314 only, so a consumer installed a twin with--no-deps, and the device proof did the same.Copy-TargetPythonDeps.ps1now runs a second pass after the GIL store. It reads each twin’sRequires-Distand downloads the requirements for the target intowheels-cp314t\deps, ascp314tor ABI-free wheels. It passes noabi3, which the free-threaded ABI cannot load.The pass fails when a staged wheel carries another ABI, or when a twin’s or a dependency’s requirement resolves in neither directory. The store’s top keeps the twins alone, so the merge’s mirror gate reads it as before.
PyPI carries all six dependencies today: numpy 2.5.4 and ml_dtypes 0.6.0 as
cp314t-win_arm64, and flatbuffers, packaging, protobuf and typing-extensions as pure wheels.The device gate installs each twin with
--find-linkson both directories, offline, beforefree-threaded-wheel.py prove. A bundle withoutdeps\still gets each twin alone.The download and the requirement gate are now functions that both passes share (
Save-TargetRequirement,Get-UnresolvedTargetRequirement), andSourceBuild.StageTargetPythonDeps.Tests.ps1covers them.
2026-10-11 — TheRock’s clang ships as AMD builds it: the HIP/MSVC <cmath> overlay is retired (CON78)#
Since 2026-09-25 the rocm image has carried
windows/scripts/hip: two wrapper headers that renameisgreaterand its five siblings around clang’s HIP math headers, loaded by aclang.cfgandclang++.cfgbeside TheRock’sclang.exe. Without them, every HIP compile against MSVC 14.51’s<cmath>failed with 20 errors.TheRock 10.1.0 no longer needs them. In the published
:winamd64-rocm(32c7cc51…; MSVC 14.51.36231, AMD clang 24.0.0git), the probe compiled its kernel with--no-default-config, which drops the overlay, throughhipcc,clang -x hipandamdclang++ -x hip.Dockerfile.rocmno longer installs the configs or the headers. The overlay, both configs and the probeTest-HipMsvcCmath.ps1left the tree, andRocm.Migraphx.Tests.ps1now holds every rocm Dockerfile free of them.The smoke gate’s one-line
hipcckernel stays the canary: a toolset or TheRock bump that brings the clash back fails it with the same 20 errors. The next rocm chain has to build MIGraphX, the EP,ggml-hipand torch without the overlay.
2026-10-11 — CON63, CON80, CON82 and CON87 proved, CON71’s Windows half done#
CON63: the hub’s own device gate passed 17 of 17 on
windows-11-arm, the WebRTC loopback included (windows-arm64.ymlrun 38170783445 on 5bcd214c,:winarm64ba6bfaae…). The arm64 WebRTC contract holds: the cross-built gst-plugins-rs and the aarch64ffi-7.dll(proved at the 2026-10-10 merge) carry a webrtcsink → webrtcsrc call over DTLS-SRTP on the device.CON80: the in-place site-packages merge passes in the published images. In
:winamd64(e96203a8…, smoke run 2026-10-11),Cython.Shadowimports and all 31 RECORD files spell their entries as on disk. The:winarm64(ba6bfaae…) passed the same two checks over its 12 distributions at its chain’s smoke gate (run 20261010-121545).CON82, the Windows items:
The published
:winamd64resolvesVULKAN_SDKto scoop’s vulkan 1.4.363.0, withBin-ARM64andLib-ARM64.The published
:winamd64-rocm(32c7cc51…) ships the 1.4.363.0 loader (C:\vulkan-loaderand the lavapipe copy). Its FFmpeg lists thevulkanhwaccel, andllama-cli --versionreports build 11476, commit 988190680.x265 4.2 built and verified its SHA256 in the 2026-10-11 chain.
The arm64 Vulkan-ValidationLayers load in
vulkaninfoon the device (run 38170783445).OmniAccelerANT built and installed its flatpaks on runtime 26.08:
web.ymlrun 38158462452 and Linux x64 run 38158462860, both on fafa9f3.
With the Linux half proved on 2026-10-09, the row is closed.
CON87: the Windows chain no longer rebuilds over a Linux-only
versions.envedit.The first full chain on it (20261011-184301, 3:37 h) rebuilt above base once. Smoke: 268 passed, 0 failed, 1 skipped.
Then
CMAKE_VERSION_RISCV64moved 4.4.4 → 4.4.9, a temporary edit, and the next chain (20261011-222153) took 14 min. base, toolchain, all seven media stages and the merge came back CACHED, with the same manifests as the run before (base1b332f1d…, toolchainf1353638…).Only torch re-ran, because OrchestrANT’s develop had moved 179e1e1 → b599448f. final followed it.
Smoke: 268 passed, 0 failed, 1 skipped. The publish gate was clean.
CON71, Windows: the published
:winamd64passesTest-Container.ps1’s 21-tool check, every tool at 23.1.3. The native plugin’s reformat in OmniAccelerANT is the row’s last item.CON88, new: Python in the Windows images trusts only the 18 roots that the Server Core store ships, so
ftp.osuosl.org, the target of downloads.xiph.org’s redirect, failsCERTIFICATE_VERIFY_FAILED. Meson’s wraps fall back to GitHub;truststoreverifies the same URL. Cause and fix in the BACKLOG.
2026-10-11 — a Python leg in the image takes the image’s interpreter or fails; it never downloads one (CON66)#
uv_venv_create(linux/scripts/01-core/python_uv.sh) runsuv venvwithUV_PYTHON_DOWNLOADS=neverforPYTHON_MAJOR_MINORand itsttwin when the shipped image’s ENV (PYTHON_MAJOR_MINOR,PYTHON_CROSS_ACTIVE_ROOT) says the image ships them, anduv_ensure_python_availableno longer runsuv python installfor those. A missing one fails the leg withpython3.14t is missing, though this image ships it. Other versions, runs outside the image and a caller’s ownUV_PYTHON_DOWNLOADSkeep their behaviour.Proved in the
:latestamd64 child against WebDavClient 3096c57: the3.14leg took/usr3.14.4 and the3.14tleg/opt/python-freethreaded3.14.8, both with downloads off, 22 and 23 tests green. Withpython3.14thidden fromPATH, the previous code downloaded a free-threaded CPython and the leg passed; this one fails it.test-uv-python-request.shcovers the image, a missing interpreter, the GIL leg, a version the image does not ship, the caller’s override and a bare host; with the image check disabled, 5 of its 21 assertions fail.
2026-10-11 — the WebRTC loopback waits for the producer to register (CON63)#
The first
windows-arm64.ymlrun uploaded the loopback’s logs, and they show a race in the harness, not a broken bundle. The consumer started as soon as the signalling server listened, and itslistreached the server 19 ms before webrtcsink registered as a producer. Withconnect-to-first-producerand no listener role it never heard of the producer, and the pipeline sat in PLAYING until the 90 s timeout.On arm64 webrtcsink needs ~0.8 s to pick its H.264 encoder: it probes Media Foundation devices and lands on
mfh264enc. On amd64 the choice is quick, so the producer won the race there.Invoke-GstWebRtcLoopbacknow waits up to 30 s forregistered as [Producer]in the server’s log before it starts the consumer, and fails with that sentence if the line never comes. It still passes in:winamd64.
2026-10-11 — the hub gates its own arm64 bundle; no consumer lane hosts it any more#
The bundle device gate grades the image’s whole
C:\runtime: GStreamer and WebRTC, HailoRT, IREE, ORT and the Python wheels. Since 2026-10-03 it ran inside consumer cross lanes that setbundle-artifact-name, and only BeschleunigerBallett did. Its first WebRTC failure (run 38156104572) turned the renderer’s lane red and skipped its GPU suites, which hang off the wholecontainer-ci-windows.ymlcall, over a component the renderer never uses.windows-arm64.yml(“Windows arm64 · bundle device gate”) now runs it, daily and on a push to the gate’s files. Awindows-2025job pulls the published:winarm64and packs its bundle withExport-Arm64Bundle.ps1. Awindows-11-armjob runsTest-Arm64Bundle.ps1, and uploadswinarm64-bundle-webrtc-logswhen it fails.container-ci-windows.ymllosesbundle-artifact-name, its export and upload steps and thebundle-gatejob. BeschleunigerBallett dropped the input first (9e029676).
2026-10-11 — the WebRTC loopback says why it stalls, and the arm64 device job keeps its logs (CON63)#
Its first device run timed out: BeschleunigerBallett run 38156104572 passed 16 of 17 on
windows-11-arm, and webrtcsrc reached PLAYING and decoded nothing in 90 s without a single error line from either process.Invoke-GstWebRtcLoopbacksetsGST_DEBUGto warnings plus INFO for webrtcsink, webrtcsrc, webrtcbin, nice and DTLS when the caller set none, and restores it. A failure now carries 12 lines of all four logs and their path. In:winamd64the loopback still passes, with 66 INFO lines in its stderr logs.The device gate writes them under
RUNNER_TEMP, andcontainer-ci-windows.ymluploads them as<bundle-artifact-name>-webrtc-logswhen the gate fails.
2026-10-11 — the arm64 device gate runs all 17 steps on every bundle, the WebRTC loopback among them (CON63, CON64, CON67)#
The published
:winarm64(ba6bfaae…) passed its device gate onwindows-11-armin BeschleunigerBallett run 38100828628: 16 of 16, the validation layer loading invulkaninfo(CON64) and the pinned pytest stack, pytest 9.1.1, installing offline from the wheel store (CON67). OrchestrANT’s arm64 run 38086634226 staged its tests from that store.So the four steps that ran only in a bundle that shipped their component (the free-threaded interpreter, the cp314t twins, the pytest stack, the validation layer) now run on every bundle, and
Invoke-ShippedBundleStepis gone.A new step runs the amd64 smoke gate’s WebRTC loopback with the bundle’s
gst-launch-1.0.exe: webrtcsink to webrtcsrc, 60 frames over DTLS-SRTP (CON63). Both gates grade it through the newAssert-GstWebRtcLoopback, whichTest-Container.ps1’s copy of that verdict moved into.Export-Arm64Bundle.ps1putsWindowsGstPlugins.Common.psm1and its arch sibling beside the gate. In that layout the step passed in:winamd64. Its first device run is the next BeschleunigerBallett arm64 run on a hub pin that has it.-MinPasseddefaults to 17, every step, andSmoke.Arm64Bundle.Tests.ps1holds the floor to the step count.
2026-10-11 — a Linux-only versions.env edit leaves the Windows chain cached (CON87)#
Dockerfile.basecopied all oflinux/scripts/01-core/versions.env, and the toolchain stage mounted it into its LLVM RUN, so a riscv64 pin bump (655a2c4e) turned the 2026-10-09:winamd64-rocmpublish into a 4:45 h rebuild.Build-Buildkit.ps1now writeswindows/generated/versions.envon every run (Write-WindowsVersionsEnv), and the base COPY, both toolchain mounts and the merge re-COPY read it instead.The filtered file keeps every key in source order and drops comments, plus the Linux-only keys: those
$script:LinuxOnlyVersionKeyPatternmatches (Android, DeepStream, Chrome, riscv64, Linux tarballs and the like), unless the name saysWINDOWSor a Windows script, Dockerfile or mounted Linux file names it. Today that is 101 of 412 keys;CMAKE_POLICY_VERSION_MINIMUM, which CMake reads from the environment, stays.Proved on the base stage: with
CMAKE_VERSION_RISCV64andDEEPSTREAM_VERSIONmoved and a comment added, a second-Stages basewas CACHED end to end, manifest1b332f1d…both times. The next chain run rebuilds above base once.BuildDriver.WindowsVersionsEnv.Tests.ps1checks the filter, that every key a Windows stage is forwarded or declares stays, and that no chain Dockerfile reads the unfiltered file. The context-path gate (verify_dockerfile_context_paths.py) lists the file underGENERATEDwith the driver as its producer.
2026-10-11 — the arch gate reports pip’s and setuptools’ launcher templates instead of failing on them#
OrchestrANT’s Windows x64 app bundle failed its gate on the new pin (run 38086634222):
4 violation(s), all in the runtime’sensurepip\_bundled\pip-26.2.1-py3-none-any.whl— distlib’st32/w32(I386) andt64-arm/w64-arm(ARM64). The gate machine-checks wheel members since fbf9c369, and pip ships one launcher template per arch on purpose: the installer copies the target’s when it writes a script. The image gate never saw it, because the Dockerfile’sARCH_GATE_HOST_TOOLSalready names those paths;New-PythonAppBundle.ps1passes no pattern.Test-TargetArch.ps1 -LauncherTemplatePattern(on by default) lists distlib’st32,t64,t64-arm,w32,w64,w64-armand setuptools’cli/guilaunchers per arch as templates, prints them and leaves them out of the count. A new test packs all six into a pip wheel: the amd64 bundle passes, and an ARM64 binary that is no template still fails beside them.
2026-10-11 — the hub’s own lanes are green again: the wheel smoke grades the import, two Windows tests caught up#
The riscv64 wheel smoke passed a package whose import raises. Since 9e3b7cba,
free-threaded-wheel.py’senclose()registers a package whose import fails with its body unrun, so the compiled modules under it can load.wheel-smoke.pycalledload_allfirst, and its ownimport_modulethen returned that stub without an error.test-wheel-smoke.shfailed on it in every preflight since, and the threewheel-smoke.*mutations read as vacuous. The smoke now imports the package beforeload_all; 18/18 assertions pass in:latestand all three mutations bite.media-core-viewandmedia-tvm-viewredeclareWINDOWS_TARGET_ARCH, asTargetArch.Common.Tests.ps1asks of every stage that RUNs over an external image (CON86’s views had none). The next Windows chain rebuilds the two empty views and the merge above them.Get-FreeThreadedTwinPlan’s test names an unlisted distribution that stays unlisted. It usednumpy, which 6276a9be added to the twin table (twin:FT_TORCH_TWIN), so the expected throw never came.
2026-10-11 — the nvidia and rocm ORT cp314t twins are proved in the published images (CON79 1)#
BACKLOG CON79 1 listed them as open (“one call each”). The call has been in
30-build-native-nvidia.shand30-build-native-amd.shsince e2651106 (2026-10-07), and both published GPU images already carry and prove the twin. The build logs show it:rocm, chain run 20261009-152508 (
:latest-rocm, index sha256:a5d68fbe). The MIGraphX pass overbuild_native_gpu_migraphxtook 57 s and rebuilt no HIP object (the GIL pass built 590) and 106 C++ objects. It storedonnxruntime_migraphx-1.30.0-cp314-cp314t.nvidia, media run 20261010-202726 (
:latest-nvidia, index sha256:810f36b3, run 20261011-040056). The CUDA pass overbuild_native_gputook 32 s, 192 s on the first run, 20261010-125556. It rebuilt no CUDA object (the GIL pass built 578), and its 664 C++ compiles came from the compiler cache. It storedonnxruntime_gpu-1.30.0-cp314-cp314t.Both runtime smokes pass
FT-STORE, with the flavour’s twin andonnxruntime_dnnlloaded with the GIL off. They pass the ORT census, which grades the twin’s members against the GPUort-provenance-cp314t.sha256.
Proved without a chain: the pass compiles against
3.14t. It rerunsbuild.shwith the GPU build’s ownBUILD_ARGSand build dir and appends onlyPython_EXECUTABLE=<3.14t venv>. On a scratch project with ORT’sfind_package(Python 3.10 COMPONENTS Interpreter Development.Module NumPy), CMake 4.4.4 then re-resolved a warm GIL cache to the3.14tinclude dir, NumPy include andcpython-314tSOABI, and its module built behind an#ifndef Py_GIL_DISABLED #errorguard. With a GILPython_INCLUDE_DIRcarried in the args, the include dir stayed the GIL one: the riscv64 torch twin’s bug of 2026-10-10.Tests.
test-free-threaded-wheels.shrunsonnx_build_free_threaded_wheelagainst a stubbuild.shwith CUDA-shaped and MIGraphX-shaped args. The pass must keep the GIL args (same--build_dir) and put the venv interpreter last, in argv and in the environment. It must name no include dir and store into<output>/wheels-cp314t. A failed pass stores nothing, and a cross MIGraphX build without--build_wheelruns none. The wiring case also holds each30-build-native*.shto ending on the pass over its ownBUILD_ARGS, with no Python include define. 8 mutations, all red: drop or reorder the override, add a GIL include, drop the env, store intowheels, use a fresh build dir, move the nvidia call up, add an include define to the rocm args.test-free-threaded-store.sh:FT-STORErequires the installed flavour’s own twin foronnxruntime_migraphxas well asonnxruntime_gpu, and fails it unproved.test-uv-chain-ort.sh: in a GPU image, a3.14tvenv’s reconcile takes theonnxruntime_gpuoronnxruntime_migraphxtwin and never theonnxruntime_dnnlone beside it. It fails when the flavour filter in_uv_chain_ort_wheelsis dropped.
Docs:
consumer-image-contract.md§ The free-threaded wheels (the GPU rows of the twin-pass table, why the warm reconfigure takes the3.14theaders, and the GPU images’FT-STORE),linux-accelerator-images.md.
2026-10-11 — :latest-nvidia published with DeepStream 9.1 (CON42)#
Index sha256:810f36b38714b423652902ed35f4b221d36f868639a83a3b4da47c476b4a033e (amd64 sha256:23e3cc9e5bbbfc64d8395e1d171faa56c89e9b09cbb95bedcba225110fe4bdd5), chain run 20261011-040056-e2d41cc6 on hub aabebdbc; media and android from runs 20261010-202726 (c9f638f0 + 804227fd).
The first nvidia build with
ENABLE_DEEPSTREAM=trueby default: 48 DeepStream components built from 581889df, the media stage’s DeepStream gates and the runtime smoke’scheck_deepstreampass, wrapper-smoke and the 15/15 runtime checks pass.
2026-10-11 — the registry blacklist check scans a GPU-less nvidia image with the CUDA driver stubs (CON42)#
The first
:latest-nvidiaruntime smoke with DeepStream (run 20261011e) passedcheck_deepstreambut failed_gst_check_blacklist: 30 DeepStream plugins link the driver’slibcuda.so.1, which a GPU-less smoke container lacks, so the core registry blacklisted them.The probe now links
libcuda.so.1andlibnvidia-ml.so.1to${CUDA_HOME}/lib64/stubson a private registry when the image has the stubs and no driver libcuda, asdeepstream-verify.sh’s element check does. In that image onlylibnvdsgst_ucx.sostays blacklisted (libucs.so.0, documented inDSV_ALLOWED_MISSING), which the check reports as a documented exception; every other blacklisted plugin still fails it.test-gst-validate-ssim.shcovers both.
2026-10-10 — Get-SelectedConfigurations returns the set, and a cleared selection selects nothing#
BeschleunigerBallett’s
Build-Windows.ps1 -SkipBuilddied after its format gate:Cannot bind argument to parameter 'SelectedConfigurations' because it is an empty string. The barereturnunrolled the HashSet into an array, whose.Clear()only nulls the elements, and a single selection (its agentic loop’s-Configurations clangcl-debug) came back a string that has no.Clear()at all.Get-SelectedConfigurationsreturns the set itself (return , $set), andTest-ConfigurationSelectedtakes an empty one ([AllowEmptyCollection()]). A test inWindowsConfig.Common.Tests.ps1needs both; without either half it fails.
2026-10-10 — DeepStream’s build-stage gates load /opt/gstreamer’s core, as the final image does (CON42)#
With the components building, run 20261010-193517 stopped in
deepstream-verify.sh:one GStreamer(every plugin’slibgst*resolved to/usr/lib/x86_64-linux-gnu),soname closure(libgstrtspserver-1.0.so.0not found) and six of nine elements not registering (nvinfer,nvstreammux,nvtracker,nvdsosd,nvstreamdemux,nvurisrcbin).Cause, reproduced with
--target deepstream: thegstreamerstage carries a distro GStreamer 1.28 core (the toolchain’ssoftware-properties-common->packagekit->libgstreamer1.0-0; the gstreamer stage’sgir1.2-gstreamer-1.0andlibgtk-4-devadd base, GL and extra) and no000-gstreamer.conf.ld.sohanded even/opt/gstreamer/bin/gst-inspect-1.0the 1.28 core, andGST_DEBUG=2shows it refusing each component built against 1.29:has incompatible version (plugin: 1.29, gst: 1.28), not loading. NVIDIA’s prebuilt plugins registered, which is why three elements passed. The final image purges the distro packages and writes the conf, so the 2026-10-01 spike never saw this.ds_buildnow writes the same000-gstreamer.confthatconfigure-runtime.shwrites (ds_write_gst_ldconf) before its gates. The stage’s/etcstays in the stage: the image copies only/opt/nvidiafrom it.A new gate,
dsv_check_gst_core, fails whengst-inspect-1.0itself loads a core outside/opt/gstreamer, so a registration verdict can no longer be made against another GStreamer. The local stage build passes every gate (48 components, 9/9 elements).test-deepstream.shcovers the conf, its order inds_buildand the new gate.
2026-10-10 — DeepStream’s components find /opt/gstreamer through pkg-config in the media build stage (CON42)#
The first nvidia chain with DeepStream on by default (run 20261010-125556) stopped in
Dockerfile.media’sdeepstreamstage:Package 'gstreamer-1.0' not found. The spike ran FROM the published image, whose final stage exports aPKG_CONFIG_PATHnaming/opt/gstreamer; the build stage (FROMgstreamer) exports none.ds_build_componentsnow prepends the directory of/opt/gstreamer’sgstreamer-1.0.pc(ds_gst_pkgconfig_path), and refuses by name when there is none.test-deepstream.shcovers both.
2026-10-10 — :latest republished: the cross cp314t twins, the riscv64 uv seed and the lint tools are in (CON75, CON79 1b, CON83)#
Index sha256:30dea85c2b3fbb89b79f042333cfd5e4940eb20027b44ed5c35639bd49fb0eea (amd64 ef6b32bd, arm64 f2a72d27, riscv64 0043342b), chain runs 20261010-002002 (riscv64 media) and 20261010-010337 (android, runtime) on hub 381431d1.
FT-STOREpasses on all three arches. amd64 keeps its five native twins; arm64 and riscv64 each prove apache-tvm-ffi, av, iree-base-runtime and onnxruntime_webgpu under the target 3.14t with the GIL off.FT_TORCH_TWINwas 0 for this run; the fixed torch twin (9e3b7cba) lands with the next chain.riscv64 builds hadolint 2.15.1 from source once (about 4 h under QEMU) and seeds
/opt/uv-cache-seedwith 8 wheels, proved by a fresh sync that builds nothing. Every arch’s contract readsOK lint-tools shellcheck=0.11.0 hadolint=2.15.1.Runtime smokes: amd64 and arm64 15/15; riscv64 14/15 with its known warning (no
iree.compileron riscv64).
2026-10-10 — the arm64 fan-in: VVL compiles without sccache, and the target deps gate reads markers#
The arm64 VVL build hung in sccache, twice. On Vulkan SDK 1.4.363 the compile of
vk_validation_error_messages.cppsat in the sccache server with no compiler running: 70 minutes at-j9, then again in the driver’s-j1retry, until both processes were stopped by hand. The file emits thousands of-Wc++98-compatwarnings. Without sccache it compiles in 82 s.Build-VulkanValidationLayers.ps1now clears the C/C++ launchers for the layer itself; its dependencies keep sccache. Only the arm64 lane builds the layer from source, since amd64 takes the SDK’s.The target deps gate failed on two requirements that do not apply. pytest 9.1.1, now a bundle wheel, declares
exceptiongroup>=1; python_version < "3.11"andtomli>=1; python_version < "3.11". The pip download skipped them for cp314, butCopy-TargetPythonDeps.ps1’s gate dropped onlyextra ==markers, so it called both missing.Select-ActiveRequirementnow evaluates each marker for the target (python_version,platform_machinefrom the wheel tag, win32) with pip’s vendored packaging, and a marker it cannot evaluate fails the gate. The next arm64 solve passed it: 53 wheels, every Requires-Dist resolved.SourceBuild.StageTargetPythonDeps.Tests.ps1covers it with three cases on the host Python.The arm64 arch gate then failed on 26 launcher EXEs in pure wheels: pip’s distlib
t32/t64/w32/w64.exeand setuptools’cli/gui(-32|-64).exe, in both target CPythons’ensurepipandtest\wheeldataand in the store’s setuptools 84.0.0. The merge Dockerfile’sARCH_GATE_HOST_TOOLSdefault already skips those launchers, butBuild-Buildkit.ps1replaces it on the cross lane with an older list that never had them. The launchers only arrived with the two target CPythons of 2026-10-07. The driver’s pattern now repeats every alternative of the default, andDriver.ArchGateHostTools.Tests.ps1fails when one is dropped; against the old driver it names the two.
2026-10-10 — HailoRT’s patch 001 guards the x86 include too, so arm64 compiles with the patches#
The first
:winarm64chain after CON85 stopped inhailort.cpp. clang’simmintrin.hrefused the aarch64 target (This header is only meant to be used on x86 and x64 architecture).quantization.hppincludes it under#if defined(_MSC_VER), which clang-cl defines on every arch.001-quantization-msvc-guard.patchhad narrowed only the guard inbankers_round, while the inline fallback that ran in every build until CON85 rewrote every#if defined(_MSC_VER)in the file. So the patch was never complete, and the fallback hid it.Fix: 001 narrows the include guard too, regenerated with
git diffagainst the 5.4.0 tarball. Its result now equals the fallback’s except for the comment block. GNU patch andgit applytake all four forward and reverse, and the patch gate passes them. 002 to 004 already matched their fallbacks.
2026-10-10 — the riscv64 torch twin compiles against the target 3.14t, and a failed proof is never silent (CON79 1b)#
Root cause. The twin pass appended its Python overrides to the GIL pass’s
CMAKE_ARGS, which kept-DPYTHON_INCLUDE_DIR=/opt/python-cross/riscv64/usr/local/include/python3.14.torch/CMakeLists.txtputs that dir first ontorch_python’s include path, so the “twin” recompiled nothing. Itslibtorch_python.soand_Cwere byte-identical to the GIL wheel’s (sha256b3978f91…). That library imports_Py_Deallocand no free-threaded refcount symbol. Under qemu-riscv64 the target 3.14t segfaulted indlopen, in its initializers, and printed nothing.The fix.
_torch_build_free_threaded_wheelbuilds its arguments afresh through_torch_cmake_args, now shared with the GIL pass.append_common_cross_cmake_argstakes the target fromCROSS_PYTHON_*when set. The twin adds-U _Python* -U Python_NumPy* -U Python3_NumPy*. The pass takes 233 s warm instead of 70 s, and itslibtorch_python.soimports_Py_DecRefShared,_Py_MergeZeroLocalRefcountandPyUnstable_Module_SetGIL.The proof could not prove any torch.
torch._C’s init importstorch, whose body needstyping_extensions, which a--no-depsvenv lacks. PyPI’s amd64 cp314t torch failed the same way. Withtyping_extensionspresent, the body re-importedtorch._Cinside its own init (SystemError: bad call flags).free-threaded-wheel.pynow imports a module’s enclosing package first. When that fails, it registers the package unrun, as an import in progress leaves it. numpy, av, apache-tvm-ffi, onnxruntime, pyyaml and markupsafe from PyPI give the same verdicts as before.Never an empty reason. The helper enables
faulthandlerand writes the module it is loading toFT_PROVE_TRACE._ft_prove_verdictadds the exit status or signal. The unfixed twin now reads… (killed by SIGSEGV, exit status 139; it died loading torch._C) (on riscv64 under qemu-riscv64)after the stack.Proved. A full riscv64
build_torch_wheelin:cross-sdk-riscv64stored the twin:1 compiled module(s) of torch loaded on free-threaded 3.14.8; the GIL stayed disabled (on riscv64 under qemu-riscv64).import torchthere runs with the GIL off.FT_TORCH_TWIN=1again inversions.envand bothDockerfile.mediaARGs.Tests, red before and green after: the twin’s arguments carry no GIL path; a crash names the signal and the module;
FT_PROVE_TRACE; the enclosing-package import and its fallback.
2026-10-10 — FT_TORCH_TWIN off until the riscv64 torch twin’s qemu proof works (CON79 1b)#
Run 20261009-233208 proved every arm64 and riscv64 cross twin but torch: riscv64’s cp314t torch built in 70 s in the warm tree, and its qemu-riscv64 proof returned non-zero with no output.
build_torch_wheelthen returned 1, which drops the whole riscv64 torch cross wheel to the native torch stage, and the store would expect a twin that never landed.FT_TORCH_TWIN=0inversions.envand bothDockerfile.mediaARGs; the store recordsskip torch FT_TORCH_TWIN=0. BACKLOG CON79 1b keeps the root cause open.
2026-10-10 — a cross stage’s store defers a twin that only lacks target libraries to the target image (CON79 1b)#
Run 20261009-224520 proved all four arm64 twins at build time (tvm-ffi, ORT, PyAV with 50 modules, IREE runtime), then the final media RUN’s store re-proof failed PyAV:
cannot load av._core: libgme.so.0: cannot open shared object file. A cross media stage installs host packages only (:<target>installs conflict there), so FFmpeg’s target codec libs are absent; the twin’s earlier proof ran in thepyavstage, which has them.Fix (
free-threaded-store.sh,_ft_store_prove): in a cross build, a re-proof whose everyERROR:is a missing shared object is logged as deferred, naming the libraries; the runtime image smoke’s FT-STORE proves the twin on the target, where the closure is installed. A GIL re-enable, a bad symbol or a wrong arch still fails; native builds are unchanged.test-free-threaded-store.sh86 -> 90, two failing without the fix.
2026-10-10 — the IREE cross twin’s reconfigure moves both FindPython spellings (CON79 1b)#
Run 20261009-215702 proved arm64’s tvm-ffi and ORT twins (the libstdc++ fix held:
onnxruntime_webgpu-…-cp314t-linux_aarch64.whl: 1 compiled module(s) … the GIL stayed disabled (on arm64 under qemu-aarch64)), then IREE’s twin reconfigure failed:Could NOT find Python (missing: Development.Module Development.SABIModule NumPy)at IREE’sCMakeLists.txt:780. The GIL cross configure’s toolchain file cachesPython_INCLUDE_DIR/Python_LIBRARYat the target GIL headers; the twin moved only thePython3_*spellings, sofind_package(Python)met GIL headers beside a 3.14t interpreter.Fix (
_iree_free_threaded_rebuild): it also passesPython_INCLUDE_DIR/Python_LIBRARYand drops the cached FindPython results (-U _Python* -U Python_NumPy* -U Python3_NumPy*). Reproduced incross-sdk-arm64with a minimal project configured the GIL way and reconfigured both ways: the old arguments fail with that message, the new ones find/opt/python-cross-ft/arm64/.../include/python3.14t.test-iree-wheelhouse-stages.sh76 -> 80, three failing without the fix.
2026-10-09 — the host 3.14t helpers drop a GIL cross build’s target sysconfig (CON79 1b)#
The next cross run (20261009-211609) proved arm64’s tvm-ffi twin, then stopped at IREE:
/opt/python-freethreaded/ bin/python3.14t is not a --disable-gil build.build-app-wheelhouse.shevals the target GIL Python’s sysconfig export (_PYTHON_SYSCONFIGDATA_NAME,PYTHONPATH) for its IREE cross wheels and leaves it set;ft_python_resolve, the GIL version lookups anduv venv/uv pip installthen ran the host 3.14t against the target GIL sysconfig, which-Idoes not drop. The riscv64 torch twin would have met it the same way.Fix (
free-threaded-wheels.sh,_ft_host): those host steps run without_PYTHON_SYSCONFIGDATA_NAME,_PYTHON_HOST_PLATFORMandPYTHONPATH; the twin builds keep setting the target 3.14t’s own throughft_target_env.test-free-threaded-wheels.sh187 -> 188, failing without the fix.
2026-10-09 — the cross cp314t proof loads the twin against the cross GCC’s own libstdc++ (CON79 1b)#
The first chain with cross twins (run 20261009-202203) stopped at arm64’s ORT step:
onnxruntime_webgpu-1.30.0-cp314-cp314t-linux_aarch64.whl is not proved: ... /lib/aarch64-linux-gnu/libstdc++.so.6: version GLIBCXX_3.4.36 not found. The twin is built by the cross GCC 16, whose target libstdc++ carries 3.4.36; the qemu proof’sLD_LIBRARY_PATHnamed only the 3.14t prefix and the sysroot, whose distro libstdc++ is older. The shipped image puts GCC 16’s runtime on the loader path, so only the build-time proof was wrong.Fix (
free-threaded-wheels.sh,_ft_target_cxx_runtime_dir): the proof asks<triplet>-g++ -print-file-name= libstdc++.so.6and puts that directory right after the 3.14t prefix. In the sdk image it resolves to/opt/gcc-16.2.0/aarch64-linux-gnu/lib64(AArch64, has GLIBCXX_3.4.36) and/opt/gcc-16.2.0/riscv64-linux-gnu/lib.test-free-threaded-wheels.sh186 -> 187, failing without the fix.
2026-10-09 — the riscv64 wheel smoke warns, not fails, on a consumer pin older than CON83#
python-ci-linux.ymlresolves at@develop, so eda97a90’s pin check (“missing ci-wheel-smoke.sh”) would have turned OrchestrANT’s riscv64 row red on its next run, before its own hub gitlink could move. The check now writespresent=falseand a::warning, and the smoke step runs only whenpresent == 'true'.test-wheel-smoke.shasserts the gated step.
2026-10-09 — the riscv64 Python lane: a uv cache seed, the cross wheel installed, shellcheck and hadolint (CON83)#
In source; the chain must prove it in the image. OrchestrANT’s riscv64 lane spent 108 min of its 6 h job building numpy, matplotlib, contourpy, pillow, line-profiler, psutil and pyyaml under QEMU, never installed the riscv64 wheel it cross-builds, and graded its coding bench without shellcheck or hadolint.
A uv cache seed, not a wheel store (
06-packaging/uv-cache-seed.sh,PYTHON_UV_CACHE_SEED=/opt/uv-cache-seed). A lockeduv syncinstalls what the lock names by URL and hash, so a--find-linkswheel is never used; uv finds a built sdist in its cache by that same source. The torch stage fetches the app atAPP_REF, syncs--locked --dev --extra testwithout the project through theuv-seed-<arch>cache mount, and keeps auv cache prune --cicopy holding only the versions the sync installed. riscv64 only; the other arches get aseeded norecord.Proved at build: a fresh copy syncs the same lock into a fresh venv and must build nothing (no
Builtline, no new wheel undersdists-v*/).uv sync --no-buildcannot be the proof: it refused pyyaml with a cached build present (can't be installed because it is marked as --no-build but has no binary distribution, uv 0.12.23).Measured in
:latest’s riscv64 child under QEMU (indexaf7252a0…, 32-core host), OrchestrANT 3bdf80a7: cold 3172 s, 8 wheels (the 7 above plus the pure-Python sdist antlr4-python3-runtime), seed 21 MB; warm 89 s; the proof passed andverifyreadseeded for riscv64: 8 wheel(s), proved.Consumers copy it.
ci_tests.shand the newci-wheel-smoke.shcalluv_cache_seed_restore(ci-common.sh), which copies a seed of the running arch intouv cache dir. Probe, as uid 1001 in the riscv64 image: a lock with pyyaml and psutil synced with no build from the seed; without it,Building psutil,Building pyyaml.The cross wheel is installed where it runs.
python-ci-linux.yml’s riscv64 row withpackage-emulatedrunsci-wheel-smoke.shin the riscv64 image after packaging: the onecp314riscv64 wheel fromdist/, over the lock’s core deps,import <package>outside the checkout and every compiled module loaded (wheel-smoke.py). A host step fails the row first when the consumer’s hub pin lacks the script. Probe in the riscv64 image: a C-extension wheel passed (import smokeapp and 1 compiled module(s) of smokeapp load on riscv64), and the same wheel with an x86_64.sofailed it.shellcheck and hadolint in the image, every arch (the published amd64 child had neither on
PATHeither; the same install ran there green) (install-lint-tools.sh, thetool-pins.envpins, SHA-verified, each binary run on input it must flag). shellcheck has a riscv64 release (SHELLCHECK_LINUX_RISCV64_SHA256, alsolint-shell.sh’s riscv64 arm). hadolint has none:Dockerfile.torch’shadolint-buildstage builds the release tag’s source (HADOLINT_SOURCE_SHA256) with Ubuntu’s GHC 9.10.3 atHADOLINT_HACKAGE_INDEX_STATE, and caches the binary by those pins. The Hackage release alone does not resolve (timeagainst language-docker 16); the tag’scabal.projectcarries upstream’sallow-newer: time. Measured inubuntu:26.04riscv64 under QEMU: apt 469 s,cabal update138 s, the build 18221 s (5.1 h, ~105 packages), and the binary reportsHaskell Dockerfile Linter 2.15.1and flags DL3008/DL3015. It needs libgmp, libffi and libnuma, which:latest’s riscv64 child has:install-lint-tools.shinstalled it there beside the SHA-verified riscv64 shellcheck and both passed their checks.Gates: the
lint-toolsanduv-cache-seedcontract rows;test-uv-cache-seed.sh,test-wheel-smoke.shandtest-lint-tools.sh, 11 mutations (all bite).bump_versions.pyrefreshes the new SHA pins with their versions.Left for the chain: see BACKLOG CON83.
2026-10-09 — the CPU ORT build no longer takes ROCm 10.1’s flatbuffers 25 (CON78)#
The rocm chain 20261009-131840 stopped in the media stage’s ORT CPU step:
ort.fbs.h:11: static assertion failed: Non-compatible flatbuffers version included, (25 == 23), in
flatbuffers_utils.cc and lora/adapter_format_utils.h.
Cause. The gpu stage’s only flatbuffers is
/opt/rocm/core-10.1/include/flatbuffers(25.x), fromamdrocm-dnn-dev10.1(hipDNN). In 10.1/opt/rocm/libis the mergedcore-10.1/lib, so its CMake config sits at/opt/rocm/lib/cmake/flatbuffers./opt/rocm/binis onPATH, and CMake searches eachPATHentry’s parent, so ORT’sFIND_PACKAGE_ARGStook it (flatbuffers_DIR=/opt/rocm/lib/cmake/flatbuffers, andnlohmann_json_DIR=/opt/rocm/share/cmake/nlohmann_jsonbeside it).-I/opt/rocm/includereachedonnxruntime_flatbufferswith no pinned flatbuffers include at all. Reproduced by configuring the CPU step in the run’s gpu-stage image (sha256:fb44a2d5…).Fix.
append_onnx_native_base_build_argspassesCMAKE_DISABLE_FIND_PACKAGE_flatbuffers=TRUEto every native ORT build; the MIGraphX build’s own copy of that define goes. The newappend_onnx_rocm_isolation_argsgives the CPU buildCMAKE_IGNORE_PREFIX_PATH=${ROCM_HOME:-/opt/rocm}when the root exists, so no ROCm package reaches it. Rerun in the same image: noflags.makenames/opt/rocm, nlohmann_json and flatbuffers are fetched, andcmake --build . --target onnxruntime_flatbuffersbuilds; so do the whole CPUonnxruntimetarget and, through--step gpu,onnxruntime_providers_migraphxagainst/opt/rocm/extras-10.test-onnx-build-summary.shruns both helpers (red before, green after). Docs:docs/linux-accelerator-images.md§ Where ROCm 10.1 puts MIGraphX.
2026-10-09 — WEBDAVCLIENT_REF to WebDavClient’s develop head#
4f3f116d->050dfb2c(23 commits: lock maintenance, the free-threading declaration, a manylinux packaging extra, unit tests).webdav-download.shinstalls the client from the commit’s archive: the new archive installs into a 3.14 venv, and every calldownload-webdav-files.pymakes keeps its signature;webdavclient.py’s diff is comments only.bump_versions.py --checkhad reported it NEWER AVAILABLE since c40dc4bb.
2026-10-09 — the cp314t twins on the Linux cross lanes: arm64 cross and riscv64 (CON75 Linux half, CON79 1b)#
In source; the chain must prove them. :latest of 2026-10-09 ran FT-STORE with cross-built arch: no twins yet, as recorded on arm64 and riscv64. Those arches now build the native table’s twins, and
the smoke holds them to it.
Build (
03-media/free-threaded-wheels.sh).ft_twin_wantedno longer skips a cross build.ft_target_resolvereads the target’s3.14tfrom/opt/python-cross-ft/<arch>: the interpreter, headers,libpython3.14t.so, theEXT_SUFFIXfrom its_sysconfigdata_t_*.py(read, not run) and the platform tag. A missing tree fails the twin.ft_target_envgives a wheel build the target’s sysconfig and platform, which the host3.14tthen reports.PyAV compiles against the target headers with the target suffix.
tvm-ffi reruns in the cross pass’s build dir.
IREE reconfigures its runtime-only tree with the target
3.14tinclude dir and library.ORT passes
Python_INCLUDE_DIRand retags the twin.The riscv64 torch reruns its warm tree (below).
Gate.
ft_soabi_gatetakes the target suffix in a cross build. It now also fails a platform tag for another machine, such as a riscv64 module in alinux_x86_64wheel.Proof on the target.
ft_prove_wheel_on_targetunpacks the twin,.dataincluded, and runsfree-threaded-wheel.py provewith the target’s own3.14tunder qemu-user.-Lnames the root holding the target’s loader, and the target tree’slibleadsLD_LIBRARY_PATH.free-threaded-store.shproves the repaired store the same way, and the runtime smoke proves it again in the target image.Store and smoke.
A cross store is held to the table like a native one, and a cross GIL wheel without a row now fails too.
The record names each expected family (
want <family>).FT-STOREwants exactly those twins, so PyPI’s torch (amd64, arm64) and PyPI’s IREE compiler (cross arches) get anOKline rather than a demand.
torch and numpy rows. The new
twin:<KNOB>verdict is a twin only while thatversions.envkey is 1.torch(Module.cpp:PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED), v2.14.1) andnumpy({Py_mod_gil, Py_MOD_GIL_NOT_USED}, 2.5.3) aretwin:FT_TORCH_TWIN.FT_TORCH_TWIN=1is inversions.envand in bothDockerfile.mediaARGs.The riscv64 torch twin reruns the persistent scikit-build tree with the target
3.14ton the command line. Onlytorch_python/_Csee Python, so an estimated 10-20 min on the 1121 s GIL torch build. That is not the doubling that would have put it behind an off knob.No chain build ships numpy, so nothing expects its twin.
Windows reads a knob row as no twin, and its table test accepts the form.
Proved without a chain, in the published riscv64
:latest(sha256:af7252a0), under QEMU from an amd64 build container with the hub’s library:A minimal C module:
ftprobe-1.0-cp314-cp314t-linux_riscv64.whl: 1 compiled module(s) of ftprobe loaded on free-threaded 3.14.8; the GIL stayed disabled (on riscv64 under qemu-riscv64). Its control withoutPy_mod_gilwas refused:the GIL was re-enabled, first by gilprobe._m.PyAV 19.0.1, cross-built in 47 s against the image’s riscv64 FFmpeg, gated
.cpython-314t-riscv64-linux-gnu.so.FT-STORE’s probe and verdict in the riscv64 image gaveOK av-19.0.1-cp314-cp314t-linux_riscv64.whl: 50 compiled module(s) of av loaded on free-threaded 3.14.8; the GIL stayed disabled.
Tests.
test-free-threaded-wheels.sh(186 assertions) andtest-free-threaded-store.sh(86) fail 34 and 15 assertions on the old library. There are seven new or rewritten mutations: the target resolve, the target-suffix gate, the platform machine, the proof on the target, the knob, the record’swantlines and the unclassified cross wheel.FT_TORCH_TWINis inbump_versions.py’s non-version filter.
2026-10-09 — CON84 item 3: jotrockenmitlocken on sqlite3 3.7.0; ANThology has no lock to maintain#
jotrockenmitlocken 93083c3:
sqlite3 ^3.7.0, lock 3.6.0 -> 3.7.0 (nothing else moved), andweb/sqlite3.wasmreplaced (it was still 3.3.1) by the 3.7.0 asset, sha256fbcd2e82…=SQLITE3_WASM_SHA256. Dart gate in:latest: 122 tests; CI runs 37933329919 (web build + deploy) and 37933328272 (CodeQL) green.ANThology is a library:
pubspec.lockis gitignored, and Renovate reported nothing behind, so there is no commit. A freshflutter pub upgraderesolves sqlite3 3.7.0 and go_router 18.0.2 within its constraints; its gate passes (42 tests).
2026-10-09 — clone-into-short-path proved on a pull_request merge ref in CI (CON84 item 2)#
Why the selftest never hit it:
actions-selftest.ymlhad thepull_requesttrigger, but the hub had never had a PR, so every run was apushorschedule, where the SHA is already in the clone. The action also failed for a ref NAME such asrefs/pull/<n>/merge: the fetch fills onlyFETCH_HEAD, so the checkout of the name found nothing.Fix (05ea8a26): the action checks out
FETCH_HEADafter fetching a ref name and reports afetchedoutput; the selftest assertsfetchedper event and, on a PR, clonesrefs/pull/<n>/mergeby name and checks it is a two-parent merge whose second parent is the PR head.Proved: draft PR #3 (closed unmerged, branch deleted), run 37931553972:
refs/pull/3/merge is not in the clone; fetching it from origin,Checked out refs/pull/3/merge at 6d90b8fe… (fetched=true),merge ref checked out at 6d90b8fe… (base 05ea8a26…, PR head b4f86936…), every job green.
2026-10-09 — bump_versions.py --audit-unclassified: all 441 pin-file keys classified, 62 were not#
What failed:
--check’s self-audit listed 62 keys in no class. It only printed them, so nothing went red.--audit-unclassifiednow runs the same check offline and exits 1, andtest-bump-versions.shruns it on the real pin files. Before the fix it named all 62 keys (rc 1). A key added with no class still turns it red.13 derived: a spec writes these as extras of an owner key, and
derived_keys()reads them from that spec’s own table:ten
CUDA_WINDOWS_ARM64_*_VERSIONfromspec_cuda’s redist manifest;DEEPSTREAM_{CIVETWEB,PROMETHEUS_CPP,OPENTELEMETRY_CPP}_VERSIONand their commits.deepstream_pinsnow reads these from upstream’sinstall_opensource_deps.shat the DeepStream tag.
3 REPORT specs:
X264_MESON_BRANCH: thex264.wraprevision atGSTREAMER_VERSION. A bump re-pinsX264_MESON_COMMITto the head of that branch.PYTORCH_ROCM_INDEX: the newestrocmX.Yline on download.pytorch.org with a cp314 x86_64 torch atPYTORCH_VERSION.WEBDAVCLIENT_REF: the head of WebDavClient’s default branch.
42 wheel URLs are in the new
WHEEL_URL_GROUPS: 31PYTEST_WINDOWS_ARM64_*and 11TORCH_WINDOWS_ARM64_*. Each group gives one reason. A*_URLqualifies only with its*_SHA256beside it.2 MANUAL:
DEEPSTREAM_TENSORRT_{CUDA,REPO}, the CUDA line and apt repo that NVIDIA builds TensorRT 10 for.2 non-version:
ROCM_WINDOWS_GFX_FAMILYis a GPU target set, likeCUDA_ARCHITECTURES.APP_REFis a tracked branch.Verified against upstream: all 13 derived values and the x264 commit match their sources at the pinned versions. All 42 wheel SHAs match PyPI’s or download.pytorch.org’s published digest. The full
--checkhad 0 lookup failures. One finding: WebDavClient’s default branch is at050dfb2c, ahead of the pinned4f3f116d. It is reported as NEWER AVAILABLE and was not bumped. No pinned value changed.
2026-10-09 — CON79: the Linux ORT twin proved in the published :latest amd64#
Image:
:latestindex sha256:af7252a0 (hub 655a2c4e)./opt/wheels-cp314tholdsonnxruntime_dnnl-1.30.0-cp314-cp314t, and FT-STORE passed it plusPYTHON_WHEELS_CP314Tin chain run 20261009-022859.ORT census:
check-ort-provenance.sh --imagepasses in a fresh container. It reads the twin’s four.somembers asBINrows rooted at/opt/onnxruntimeand matches them toort-provenance-cp314t.sha256.Reconcile: a
python3.14tvenv got PyPI onnxruntime 1.31.0, anduv_reconcile_chain_ort(the image’spython_uv.sh) replaced it with the twin. The venv census passed.import onnxruntimekept the GIL off, and the loadedonnxruntime_pybind11_state.soandlibonnxruntime_providers_shared.somatch the manifest. Eight threads ran oneInferenceSessionwith the GIL off.Not a defect: the twin’s
libonnxruntime.so.1.30.0differs from/usr/local/lib/onnxruntime-cpu/lib’s, and so does the GIL wheel’s. The wheels’ own manifests are the reference. The pybind module links ORT statically.
2026-10-09 — CON82: bump_versions.py --audit-sha-pairs passes; 49 SHA pins gained refresh specs#
What failed: 93
*_SHA256keys had no refresh spec, hold or exemption, so Renovate or a hand bump could move their version while the SHA stayed put.SHELLCHECK_LINUX_AARCH64_SHA256was the plain bug:spec_shellcheckrefreshed the other two shellcheck assets but not this one.49 specced, each from the URL its consumer script downloads:
SAFE tier: cargo-audit/deny/tarpaulin, wasm-pack, gitleaks, mold, Renovate’s Node (same major) and lavapipe.
REPORT tier: flutter_rust_bridge, sqlite3.wasm, x265, DeepStream and its TensorRT debs, HailoRT, TAPPAS, libzmq, cppzmq and the Windows ROCm tarball.
Slaved derivations: dav1d from GStreamer’s
dav1d.wrapand HailoRT’s protobuf from itsprotobuf.cmake.Extras:
spec_cudarefreshes the ten Windows-arm64 CUDA redists from the same manifest, andspec_cudnnrefreshes the arm64 cuDNN zip.
44 not specced: 42 wheel SHAs sit beside the
*_URLthat is their version. No tool moves that URL, so the audit accepts such a pair unless the URL is Renovate-annotated. Two more were added to the newSHA_PAIR_EXEMPTwith reasons:QNN_SDK_LINUX_ZIP_SHA256(login-gated) andLLVM_WINDOWS_AARCH64_RT_SHA256(slaved to MANUALLLVM_WINDOWS_VERSION).The audit is stricter: only a quoted key counts as specced, so a comment naming a key no longer covers it.
Verified: every new spec’s pins were recomputed at the current versions and compared with the pin files. All 64 values matched (the refactored
NODE_*pair included). 24 were hashed from fresh downloads, the rest read from sums files, NVIDIA’s manifests, the CUDA apt index, GitHub’s asset digests and GStreamer’s wrap. The ROCm tarball (~2.2 GB) was only probed.--checkfinished with 0 lookup failures.Two lookup fixes: the GitHub token now goes only to GitHub hosts, because Bitbucket answers a foreign bearer with 400.
artifact_existssends a one-byte GET instead of HEAD, because a token-authenticated GitHub release redirect answers HEAD with 401. That had madespec_llama_cpp_hipfail underGITHUB_TOKEN.Tests:
test-bump-versions.shnow runs the audit on the real pin files and checks that one added key fails it. It also covers URL pairing, comment-only keys and the new parsers (70 -> 90 assertions). 13 of them fail against the old script.
2026-10-09 — CON76: the free-threaded proof runs for real in the hub suite#
test-python-free-threaded-wheel.shrunsproveon a real 3.14t (CON76). It compiles two C extensions against/opt/python-freethreaded/bin/python3.14t(orFT_PYTHON) into a fresh venv, each installed as a distribution:ftfix_freedeclaresPy_mod_gil = Py_MOD_GIL_NOT_USED,ftfix_gildoes not. The first must prove (1 compiled module(s) of ftfix_free loaded on free-threaded 3.14.8; the GIL stayed disabled, rc 0), the second must fail (ERROR: the GIL was re-enabled, first by ftfix_gil; …, rc 1). The stubbed cases are unchanged.Where: in the published
:latest(hub 655a2c4e) on amd64, and on arm64 and riscv64 under QEMU: 58 -> 66 assertions on all three. A host without a free-threaded interpreter, CI’s included, prints aSKIP [<case>]line and stays at 58.Mutation-checked: ignoring the GIL verdict, a GIL-warning regex that no longer matches, and a
load_allthat never creates the module each turned the suite red in the image (2, 1 and 2 failures); every stubbed case passed all three.
2026-10-09 — :latest published from hub 655a2c4e; CON56/58/65 closed, CON66/71/72/79/82 Linux halves proven#
Published
ghcr.io/kataglyphis/kataglyphis_beschleuniger:latest, indexsha256:af7252a01f7e5099e54265337fea42c94cc6cf79a0dea1ab9fde0aaa2853af58: amd64sha256:ba3115f1…, arm64sha256:15a905c6…, riscv64sha256:81db10eb…, each labelled revision 655a2c4e. Runtime stage from chain run 20261009-022859-db31d92c; earlier stages from runs 20261007-221241, 20261007-233233, 20261008-103605 and 20261008-113607. All three wrapper smokes passed, the runtime-image smoke had 0 failures on every arch.Closed: CON56 (
rg15.1.0), CON58 (aarch64-linux-androidinstalled) and CON65 (cargo-qa-toolsrow on amd64 and arm64), all three arches where they apply. Linux halves proven (BACKLOG): CON66 (python3.14t 3.14.8, GIL off), CON71 (26 LLVM tools at 23.1.3), CON72 (the 2026-10-07 pins), CON79 (FT-STORE on amd64 with the av, IREE and tvm-ffi twins) and CON82 (Vulkan 1.4.363.0, Chrome for Testing 155, Node 26.11.0, the 26.08 flatpak refs, vvdec 3.2.1).The chain needed c0fb66be, df0736cd, 815cfebe, 537b60f2, 6c11da0c, 02801990, d5b6d9db, f3b9ebb4 and 655a2c4e, each with its own entry above or below.
2026-10-09 — the media fan-in binds view stages, not the branch images#
The rocm chain stopped at the site-packages merge three times on 2026-10-09. robocopy reported
ERROR 3 … cannot find the path specifiedfor every entry of the bind-mountedmedia-tvmtree, after a first attempt failed withhcsshim::ActivateLayer … (0x20). buildctl probes showed the RUN listed the image’s 49 entries but could open none. The same files open in a RUN on the image and through a stage with one emptyRUNlayer on top. A-NoCacheStage media-tvmrebuild and a restart of containerd and buildkitd did not change it. The same merge passed three times on 2026-10-07/08. The cause is not established (docs/failure-modes.md).Fix:
Dockerfile.media-merge-builderaddsmedia-core-viewandmedia-tvm-view(RUN cmd /c exit 0over each branch image), and the mergeRUNbinds those. TheCOPY --from=steps still read the images. The next rocm solve merged both trees: 31 distributions, every RECORD entry spelled as on disk.
2026-10-09 — riscv64 advertises the cmake it runs: the venv’s pip wheel#
The riscv64 runtime-image smoke failed one row (chain run 20261008-200606; amd64 and arm64 clean):
the riscv64 image ADVERTISES CMAKE_VERSION=4.4.2 but actually has 4.4.4. In that imagecmakeon PATH is/opt/python/.venv/bin/cmake, the runtime venv’s pip wheel atPY_CMAKE_VERSION(4.4.4 since the 2026-10-07 Renovate bump); apt’s/usr/bin/cmakebehind it is 4.2.3.CMAKE_VERSION_RISCV64=4.4.2was right only while the wheel was 4.4.2, and its comment credited the Ubuntu archive.Fix (
01-core/versions.env):CMAKE_VERSION_RISCV64=4.4.4, the comment names the wheel, andtest-version-forwarding.shnow asserts the riscv64 forward equalsPY_CMAKE_VERSION, so a wheel bump alone fails it (proved by moving the wheel pin to 4.4.5). Only riscv64’s forwarded value changes; amd64 and arm64 keep their cache.
2026-10-08 — HailoRT’s .patch files apply again, and the patch gate runs GNU patch too (CON85)#
The four
windows/scripts/patches/hailo/*.patchhad never applied in a build. HailoRT comes from a tarball, which is no git repo, soInvoke-SourcePatchapplies its patches with GNU patch (Git for Windows’usr\bin\patch.exein the image). All four carried a hand-writtenindex 0000000..0000000line, which GNU patch reads as a new file (which already exists!); 003 also had 6 lines of leading context against 1 trailing, which GNU patch anchors at end of file. Every build since at least 2026-10-04 logged fourERROR: … does not apply cleanlyand went green on the inline fallbacks.git applyforgives both, and that is allTest-PatchesApplyClean.ps1ran.Fix: the four regenerated with
git diffagainst the SHA-pinned 5.4.0 tarball. The changes are the same; the index lines are real and the context is git’s 3/3. GNU patch 2.7.6 andgit applyboth take them, forward and reverse, on a fresh non-git extract.Gate:
Test-PatchesApplyClean.ps1now also dry-runs GNU patch (--force, never prompting) on each clone, cloned withcore.autocrlf=falseso the tree is LF like the tarball. It takes Git for Windows’ GNU patch, not the firstpatch.exeonPATH: Strawberry Perl’s patch 2.5.9, first on the dev host’sPATH, asserts on every patch. The old four FAIL there and the new four pass; all 20 patches pass both checks at their pinned refs.windows/scripts/patches/README.mdsays how to write a patch GNU patch takes.
2026-10-08 — the arm64/riscv64 images drop the Vulkan SDK’s builder-arch vkprofiles (CON82)#
The runtime-image smoke failed one row on arm64 (chain run 20261008-141457; amd64 0 failures):
tree-arch: /opt/vulkan ships 1 X86-64 object(s) in the arm64 image, e.g. /opt/vulkan/1.4.363.0/aarch64/bin/vkprofiles. Vulkan-Profiles atvulkan-sdk-1.4.363.0builds its newvkprofilesunconditionally with PyInstaller (add_pyinstaller_target, no option), which bundles the BUILDER’s Python, so a cross build installs an x86-64 executable into the target prefix. Earlier SDKs had no such tool, so no foreign-arch image loses one it had.Fix (
06-packaging/prune-vulkan-host-sdk.sh,_prune_host_built_tools): before the/opt/vulkanCOPY, an ELF in a foreign target prefix’sbin/whose machine is not the target’s is removed and logged. Libraries are not touched, so a wrong-arch library still fails the smoke. Run against the realcross-android-arm64artifact: it removes exactlyaarch64/bin/vkprofiles, and no foreign ELF is left among the prefix’s 52 tools.test-vulkan-host-sdk-prune.sh36 -> 41, two failing without the fix.
2026-10-08 — OpenCV’s libwebpdemux2 survives the package stage’s GTK 4 drop#
The wrapper smoke’s media check failed on gst’s
opencvplugin (chain run 20261008-132402, amd64), with the compiler smoke now clean. A fulllddsweep of the package image foundlibwebpdemux.so.2missing for 13 OpenCV libraries and the plugin: it arrived only as a GTK 4 dependency, anddrop_redundant_distro_gtk4’s purge left it to the autoremove.Fix: the native list in
03-media/runtime/install-deps.sh, which the package stage runs asfinal/install-deps.sh, now nameslibwebpdemux2besidelibavif16andlibhdf5-310, so it is installed as manual. Proved in the package image: the autoremove keeps it,gst-inspect-1.0 opencvloads, and the wholewrapper-smokeRUN (validate-compilers.sh smoke,smoke-media.sh,smoke-torch-venv.sh,smoke-cross-all-arches.sh amd64) passes.
2026-10-08 — the Vulkan SDK’s DXC llvm-tblgen no longer shadows the pinned one (CON71)#
The runtime stage’s compiler smoke failed one row (chain run 20261008-113607, amd64):
llvm-tblgen MISSING is not LLVM_RELEASE 23.1.3, while the other 25 tools passed. The pinnedllvm-tblgenwas built, installed, wired into/usr/binand/usr/local/bin, and runs. But the image’sPATHstarts with/opt/vulkan/active/bin, and the Vulkan SDK ships DXC’sllvm-tblgen(its LLVM 3.7 fork), which answers--versionwithUnknown command line argument. A consumer typingllvm-tblgengot that fork. A sweep of every PATH dir ahead of/usr/local/binin the package image found no other clash.Fix (
06-packaging/package-image-wiring.sh,unshadow_pinned_llvm_tools, called afterwire_pinned_llvm_tools): a Vulkan SDK executable whose name the pinned LLVM also has moves tovulkan-sdk-<name>. Proved in the package image:llvm-tblgenthen resolves to/usr/local/binand reports 23.1.3, and the compiler smoke passes.test-package-image-wiring.sh46 -> 53.
2026-10-08 — Android LiteRT takes Samsung’s LiteCore headers from a pinned, hashed download#
The android stage failed in LiteRT v2.2.0’s Samsung plugin (chain run 20261008-103605):
ai_litecore_manager.h:20: fatal error: 'graph_wrapper_api.h' file not found. LiteRT’s defaultLITECORE_HEADERS_URL(…/download-file/1.1.0/ai-litecore-ubuntu2404-v1.1.0.tar.gz) now answers HTTP 404 with a JSON body, and itsfile(DOWNLOAD)checks neither status nor hash, so the Samsung NPU plugin was configured against an empty tree. The pin did not move (v2.2.0 since 2026-08-18); the vendor’s URL did. Upstream main already drops the1.1.0/segment.Fix (
litert/android/build-android.sh): the script fetches that new URL itself, checks sha2567d79a04d…a07b2(21.4 MB, measured 2026-10-08), and handsexynos-ai-litecore-v1.1.0/includetoLITECORE_HEADERS_DIR, so upstream downloads nothing. Samsung dispatch keeps building, as it did before the 404.
2026-10-08 — the media smoke’s FFmpeg registry checks survive SIGPIPE; OpenCV’s avif/hdf5 in the media stage#
Third failure of the media stage, now in its smoke (chain run 20261008-100008): with FFmpeg’s runtime manifest installed (previous entry), ffmpeg runs in the media sandbox, so
smoke-media.shstopped deferring its FFmpeg and GStreamer checks there and failed 8 of them.Seven were false.
ffmpeg -encoders | grep -q x265underpipefail: grep exits at the match, ffmpeg dies of SIGPIPE, and the pipeline reads as “not registered”. Measured in the stage’s image:rc=141 PIPESTATUS=141 0, while the captured 222-line list carries libx265, libdav1d, libsvtav1, libvpx, libopus,drawtextandscale_vulkan. FFmpeg 9.0.2’s longer lists make the race likely; the package-stage smoke runs the same lines. The registry, buildconf and filter lists are now captured once and searched.One was real. gst’s
opencvplugin did not load:libavif.so.16 => not found. A fulllddsweep of/opt/opencv5,/opt/gstreamer,/opt/ffmpegand/usr/local/libin that image found two distro libs missing,libavif16(12 OpenCV libraries and the plugin) andlibhdf5-310(opencv_hdf); the native media stage now installs both, as the package stage already does.
2026-10-08 — the media stage installs FFmpeg’s runtime manifest before the cp314t store proves PyAV (CON79)#
Second failure of the same run, one RUN later (chain run 20261008-085555, after the
pyavfix proved and stored the twin):free-threaded-store.shre-proves every twin in the final media RUN, andavcould not loadlibopencore-amrwb.so.0.emit_runtime_apt_manifestrecords FFmpeg’s apt runtime libs in/opt/ffmpeg/runtime-apt-packages.txt, but only the package stage (setup-torch-venv.sh) installed them.Fix (
03-media/runtime/install-deps.sh): a native build adds the manifest to the final-stage packages. The package stage installs the same list, so the shipped image is unchanged; cross builds prove no twin there and keep their package set.
2026-10-08 — Windows FFmpeg links x265 4.2 again: its .pc gains advapi32#
The x265 4.1 → 4.2 bump of 2026-10-07 broke
:winamd64’s FFmpeg configure:ERROR: x265 not found using pkg-config. config.log shows the cause: 4.2’sthreadpool.cppreads the CPU frequency from the registry (RegOpenKeyExA,RegQueryValueExA,RegCloseKey), so the staticx265.libneedsadvapi32.lib, and thex265.pcthat x265 generates does not list it.Build-FfmpegCodecs.ps1now appends-ladvapi32to thatLibs:line (Add-CodecPcSystemLib, once, whole-name match), which FFmpeg’s msvc filter turns intoadvapi32.lib.SourceBuild.FfmpegCodecs.Tests.ps1covers it.
2026-10-08 — the PyAV cp314t proof sees the chain ORT (CON79)#
The amd64 media stage failed at
PyAV: no proved cp314t twin(chain run 20261007-233233): every module ofav-19.0.1-cp314-cp314t-linux_x86_64.whlfailed to load withlibonnxruntime.so.1: cannot open shared object file.libavfilterneeds the chain ORT and carries no RUNPATH; theffmpegstage bind-mounts ORT for its build RUN only, so thepyavstage built FROM it has none. The GIL wheel is never loaded there, which is why only the twin’s proof (CON79, which imports every compiled module) found it.Fix (
Dockerfile.media, thepyavRUN): the same read-only bind ofonnxruntime-cpufrom theonnxruntimestage, with itslibfirst onLD_LIBRARY_PATH, which is howmedia-inputsand the image load it.
2026-10-08 — the cross lldb finds zlib.h (CON71’s compiler stage)#
The arm64 compiler stage failed at
SymbolFileCTF.cpp:42: fatal error: zlib.h: No such file or directory(chain run 20261007-221241, 3092 s into the LLVM 23.1.3 build). CON71 added lldb to the cross superset; its CTF plugin includeszlib.hunderLLVM_ENABLE_ZLIBbut links noZLIB::ZLIB, so it never gets/usr/include, and the cross GCC (/opt/gcc-16.2.0/bin/aarch64-linux-gnu-g++ --sysroot=/) does not search it. LLVM’s own zlib users get the dir from the imported target, which is why only lldb broke, and only off the build arch.Fix (
02-toolchain/llvm-cross.sh):llvm_cross_stage_zlib_headerscopies the sysroot’szlib.handzconf.h(Multi-Arch: same) into<build_root>/<triplet>-zlib-include, and the C/CXX/ASM flag inits add it as-isystem. A dir holding only those two keeps the host’s glibc headers out of the target’s search path, which-isystem /usr/includewould not.test-llvm-cross-stanza.sh61 -> 65.
2026-10-08 — the lock maintenance report says how far behind each lock is (CON84 1)#
Each
LOCK FILE MAINTENANCErow ends with the tool’s own dry-run count (maint_behindinrenovate-locks.sh), in report mode only:uv.lock uv lock --upgrade (3 entries would move). Counted fromcargo update --dry-run,uv lock --upgrade --dry-runanddart/flutter pub upgrade --dry-run, each output measured against a held-back lock (cargo 1.96.0, uv 0.9.18, Dart 3.13.3 in:latest), none of which wrote it.Anything else is
behind: unknown -- <why>, never 0: npm 9.2.0, poetry 2.5.1 and pdm 2.29.2 have no dry run that diffs the lock (measured; npm’s saidup to dateover a lock its real run moved), pnpm has none known, and a missing tool, a failing dry run or output without the tool’s summary line say so too. The lock is hashed before and after; one that changed is put back.--applyruns no count.test-renovate-lockmaint.sh25 -> 45 assertions (M11-M16, verbatim tool outputs replayed by stubs; 15 fail without the change), 3 new mutations; docs/dependency-updates.md#how-far-behind-a-maintained-lock-is.
2026-10-08 — prune-safe.sh survives a store with no layer records; CON53 closed#
_disk_guard_du_jsonreads buildctl’snullas[](01-core/disk-guard.sh).buildctl du --filter type==regular --format '{{json .}}'printsnull, not[], when no record matches, and the old empty-only fallback passed it on:prune-safe.sh’s in-use count died in jq (Cannot iterate over null) before it pruned anything, on a store that held only cache mounts.test-disk-guard.sh121 -> 123, failing without the fix.CON53 closed. Measured 2026-10-08 on the dev host with no chain running: 130
exec.cachemountrecords (275 GB), every cache id with exactly one record. The 52 GB of surplus records the item listed is gone, so there is nothing left forPRUNE_DUP_CACHEMOUNTS=1to remove.