Windows backlog archive — closed items and history (archived 2026-08-11)#
Everything below was the live “Refactor Backlog (Windows container chain)” section of docs/windows-builds.md until the 2026-08-11 close-out. All items annotated (DONE …) are completed and verified (gates held after every sub-batch: Invoke-Lint 141 files 0/0 incl. the AST-trap pass, 457/457 unit tests, Test-PatchesApplyClean 12/12). Consult for evidence and rationale; do not resurrect items without re-verifying against the current tree. The lean OPEN-only backlog lives in docs/windows-builds.md § Refactor Backlog.
Addendum — closed 2026-08-14 (Batch D: nothing verified the artifact)#
Four items treated as ONE piece of work, because they all live in
Test-Container.ps1. The gate found 8 real failures in the shipped
image on its first run — see backlog P0c (#83-#87).
The gate’s own first lesson — 8 reported failures, ZERO image defects.
Pointed at bk-winamd64 the gate reported 8 failures, and they were written
into the backlog as P0c “the shipped image fails 8 assertions”. That writeup
was wrong in full, and is retracted. Final state after diagnosis:
184 passed, 0 failed, 1 skipped — “All smoke tests passed!”
Six were the GATE’s fault. A bare Dockerfile
RUNbypassesENTRYPOINT, andentrypoint.cmdis what loads VsDevCmd (-arch=amd64) and prepends LLVM’s versioned clang_rt ASAN dir to PATH. So msbuild-on-PATH,VCToolsInstallDir, MSBuild+ClangCL, nvcc (it needscl.exe) and the ASAN probe all failed against a perfectly good image, because the gate was testing a configuration no user ever runs. Fixed by invoking throughC:\temp\scripts\entrypoint.cmd→ 176→182 passed.Two were STALE ASSERTIONS, also not image defects. Probing the freshly built base settled both:
vcpkg zlib — the port DOES install, as
installed\x64-windows\lib\z.lib(+debug\lib\zd.lib). Upstream vcpkg switched zlib’s output to the Unix-style name; the check still looked forzlib.lib. Now accepts either, so the next rename does not re-open it.SCOOP_GLOBAL_SHIMS — the
--globalinstall works (C:\ProgramData\scoop\apps\flutterexists,flutterresolves by name); scoop simply never creates a globalshimsdir in this configuration. The assertion tested an implementation detail of scoop instead of the outcome. Rewritten to assert the GOAL — a--globalpackage resolves by NAME — with the shims dir as one acceptable way of getting there.
Generalised rule, the second instance in one day (after the ANSI-marshalled
LoadLibraryW probe): a new gate reporting a pile of failures is far more
likely mis-configured than the artifact is broken. Both times the fix was to
reproduce the real usage path — a known-good control, then the actual entrypoint
— rather than to “fix” the thing under test. Publishing the first reading as
fact cost a retraction; probe first, publish second.
44 (DONE) The smoke test was never invoked, and SKIP was not fatal.
grep -i smoke windows/build.ps1 windows/build-buildkit.ps1returned zero hits in both; the final Dockerfile has no RUN; CI never referenced it. A ~5 h chain ended with “Done” and zero evidence the image worked. Worse, the verdict read only$summary.Failed, so a run where every section skipped printed “All smoke tests passed!” and exited 0 — with 24Skip-Testsites and seven env-gated sections that is a reachable shape, not a hypothetical. Now:-MinPassed/-MaxSkippedcoverage floors plus anAbortedcheck, reported as exit 3 (INSUFFICIENT COVERAGE) distinct from exit 1 (failures) — “0 failures with too little executed is indistinguishable from a broken harness”. Wired into the BK driver afterfinalvia a newwindows/Dockerfile.smoke-gate, run as a buildctl solve, notnerdctl run, because containerd’s pipe is admin-only while the driver is deliberately non-admin.-SkipSmokeGateexists for chain iteration and says so loudly. The gate bind-mounts the current script and modules instead of running the copy baked into the image: otherwise a fix to the smoke test could not be re-verified without first rebuilding the whole image — exactly the friction that let it go unrun for a month — and a mount adds no layer, so the gate never alters the artifact it verifies.57 (DONE) Bulk DLL-load enumeration. New
Assert-AllDllsLoadwalks a root and LoadLibrary’s EVERY DLL, with an explicit-Allowlist for unloadable-by-design plugins and a-MinimumCheckedrot guard so a moved root cannot pass vacuously. Wired into the OpenCV section, where exactly ONE of ~25-30 module DLLs (opencv_core) had been load-tested and the rest were existence checks — the OPENGL32 defect verbatim. First run: 65 OpenCV DLLs loaded, 0 failures. Note the probing happens OUTSIDE theAssert-Testcondition on purpose:-FailMessageis a plain string evaluated at call time, so a message built from results computed inside the condition would always be empty.46 (DONE) DirectML could vanish with zero red at either end. The smoke test skipped itself when
DirectML.dllwas absent — keyed on the very artifact it exists to verify — while the staging helper onlyWrite-Warnings on a missing sidecar.USE_DML=ONis unconditional in Build-OnnxFromSource.ps1, so an absent redist is never legitimate, and on the AMD reference host DirectML is the ONLY working GPU path. Now a hard failure.67 (DONE) LiteRT exports are pinned. The build gates on
tensorflowlite_c.libbeing installed, but the documented failure was an import lib that existed while the DLL exported ZERO C-API symbols — invisible to a presence check, surfacing one branch later in gst’s meson link. Now asserts the DLL exists and exportsTfLiteInterpreterCreate,TfLiteXNNPackDelegateCreateandTfLiteXNNPackDelegateOptionsDefault— the three the/EXPORT:injection forces.
Addendum — closed 2026-08-14 (Batch G: the test net)#
Five items, tests 486 → 493, no rebuild required. #59 deliberately NOT closed — see the end.
55 (DONE)
.gitattributesdid not cover COPY-reachable files. The gap was live, not theoretical:windows/scripts/patches/litert-lm/held ONE CRLF.cmakenext to five LF siblings withattr/unspecified on all six, andcore.autocrlf=trueon the host — a fresh clone (this machine, or GitHubwindows-latest) would have written CRLF for all six, flipping bytes on five and busting media-litert plus everything downstream. The new test found more than the audit did: nine files acrosswindows/scriptsandwindows/downloadshad a worktree/index EOL mismatch, including001-allow-msys-builds.patch— already-text-protected, yet mismatched — anddownloads/README.md, which ridesCOPY downloads C:\temp\downloadsinto a layer. All nine normalized to LF (byte-identical to the index, so zero diff; verified withgit diff --quiet+ md5, sincegit statusreports a staleMafter an attribute change). Rules are now path-based (windows/scripts/** -text,windows/downloads/** -text) so a new file type needs no maintenance.Dockerfile.EolAttributes.Tests.ps1walks the real COPY instructions rather than a hand-kept list.56 (DONE) CMake patchers had 12 replace-ops and ZERO no-op guards, while printing “Patched …” unconditionally. New
patches/litert-lm/patch-assert.cmakeprovidespatch_replace_required/patch_regex_replace_required, whichFATAL_ERRORwhen the pattern matched nothing. It lives INSIDElitert-lm/on purpose: the Dockerfile COPYs that directory specifically, so a helper one level up would not be in the image. Verified with real cmake: pattern present → exit 0; pattern absent → exit 1, build aborts. Applied to all four source-rewriting patchers; thestring(REPLACE "|" ";")inrust-lib-stage.cmakeis a local list split, not a source patch, so it carries an explicitpatch-assert-exemptmarker — the exemption is on the record rather than a silent gap.Patches.CmakeNoOpGuards.Tests.ps1fails any future unguarded, unmarked replace. This matters most for sentencepiece’s duplicateABSL_FLAG(minloglevel): a silent no-op there ships a link-cleanlitert_lm_main.exethat aborts on every run.58 (DONE)
CUDA_ARCHITECTURESis now pinned at the SOURCE OF TRUTH. The only prior assertion checked the code FALLBACK with the env var cleared — and the very next test proved the env value overrides it, so trimming versions.env kept the whole suite green andsync_versions.py --writewould have propagated the trim into the Dockerfile. Now assertsversions.env == 80;86;89;90and that the Dockerfile ARG default matches.60 (DONE)
Dockerfile.media-merge-builderARG parity. It was opened by no test at all (BuildKit.TwinParityhardcodes the media-BUILDER path; PinParity never reads a Dockerfile) — in exactly the stage where the “~8 versions.env-bump breaks” landed. Now every ARG default that names a versions.env key is compared, with a rot guard (>=8comparable ARGs) so a restructured ARG block cannot make it pass vacuously. Independently cross-checked: 9 ARGs compared, all in sync.82 (DONE) The lint gate crashed intermittently — ~2 in 9 runs, PSSA 1.25.0 throwing
Object reference not set to an instance of an object., never the same file twice, always clean on re-run. An exception is not a finding, so it aborted the gate for a reason unrelated to code quality. Now: retry the file once, and on a second failure report an INFRASTRUCTURE FAILURE andexit 2— distinct fromexit 1(lint failure) so CI can tell a tooling fault from a code problem, and so “LINT OK” is never printed over files that were never analysed. Files are never silently skipped (that would fail open). Caveat: the retry path is UNEXERCISED — four consecutive runs after the change were clean, so the crash branch has not actually fired yet.
#59 NOT closed — owner action. main is not branch-protected
(gh api …/protection → 404) and windows-scripts.yml runs the linter without
-FailOnAnalyzer. Both are repo-settings/policy decisions rather than code, so
they are left for the owner: enable branch protection with both jobs required,
and decide whether analyzer findings should be fatal.
Addendum — closed 2026-08-14 (#48: two host gates that failed OPEN)#
Both were host-side only (WindowsBuildDriver.Common.psm1 is COPY’d into no
image), so they were safe to land while a full chain was mid-flight — the media
scripts and patch dirs are bind-mounted and were deliberately left alone.
Assert-ShimPatchreturned GREEN when it could not find the shim — aWrite-Warningandreturn. The gate exists because a STOCK shim kills heavy RUN layers withExportLayer 0x3after the compile is already paid for, so “could not check” is the one answer that must not read as “fine”. Worse, the hardcoded$env:ProgramFiles\Stevedore\...default missed aD:\Stevedorehost — a layout the SAME driver explicitly supports when resolving buildctl. Now: probe both candidate roots, and throw when neither has one, with-SkipHostChecksas the deliberate override. ($advicehad to move above the branch, since the new throw quotes it.)The per-stage disk gate only ever looked at
C:.[string]$Drive = 'C'and neither caller passed anything, while the LAUNCH gate passes-Drive @($repoRoot)— it learned the lesson the hard way: the build context is the repo checkout, on the reference host a dynamically-expanding VHDX atD:, which “fell to 11.7 GB free while a C:-only gate reported everything fine”. The per-stage gate exists because the launch gate is not enough, and it was watching the wrong disk. Both lanes now derive the drive from$repoRoot(verified:D:\GitHub\…→D). Its silentreturnon an unreadable drive now warns first — in a multi-MB build log, no output is indistinguishable from “plenty of space”.
Addendum — closed 2026-08-14 (Batch A / #71: sccache was NOT broken)#
71 (CLOSED — DISPROVEN, not fixed). The log forensics reported the single most alarming number in the whole audit:
Cache hits= 0 in 94/94 stat blocks,Cache misses=Cache write errors= 189,861 (exactly equal — every write failing), read errors 0. It was ranked the highest-leverage item in the backlog and credited with 18.42 h of repeated ONNX compilation.It was stale evidence. The newest log carrying sccache stats is
bk-run-xnnpack.log, 2026-08-13 19:43. The dufs WebDAV server was migrated to a session-independent SYSTEM ONSTART task that same day — specifically to stop mid-run write failures — and every run afterwards had media-core CACHED. No run has exercised sccache since the fix, so the corpus was structurally incapable of showing the improvement. Aggregating across it produced a confident conclusion about a state that no longer existed.Empirical disproof (probe:
bk-windows-base, the real cache mountid=sccache-winamd64-2, the real WebDAV endpoint, one TU compiled twice withsccache clang-cl):Compile requests 2 | Cache hits 1 | Cache misses 1 | hit rate 50.00 % Cache read errors 0 | Cache write errors 0 | Cache errors 0
Miss → stored → second compile HIT. Supporting checks:
HEAD/GET/PUTall succeed from inside a container (the directionAssert-SccacheEndpointnever tests — it probes from the host, which is why a container-side outage could never have been caught by the gate), and dufs auto-creates nested parent directories on PUT, so sccache’s/6/e/b/<hash>layout is fine. The cache mount itself was found EMPTY, which is also whySCCACHE_ERROR_LOGwas absent from all 102 logs — there was never a log to recover.What this does NOT clear. The probe used clang-cl on a trivial TU. The sccache-CUDA server crash (±2 s deterministic, ~4909-4911 s into ONNX) and the
-j9 → -j2 → -j1silent downgrade ladder it triggers (#75) are untouched by this result, as is the reported nvcc miscompile behind mozilla/sccache#2808. The at-scale hit rate stays unmeasured until the first real media build after 2026-08-13.Method note worth keeping. Two probes in a row were wrong before this one was right: the first mounted
target=C:\sccachein a hand-written Dockerfile with no# escape=directive, so\ate thesand the mount silently did not exist (MOUNT_EXISTS=False); the second used/Fo:C:\probe.obj, and sccache turned that intoC:\:C:\probe.objand failed with the misleading “failed to zip up compiler outputs”. **Use/Fo<path>without a colon, and never hand-write a Windows Dockerfile without# escape=\``.** Both failures looked like product defects and were tooling defects — the same shape as theLoadLibraryW` ANSI-marshaling mistake in the TensorRT entry below.
Addendum — closed 2026-08-14 (Batch C: the TensorRT pin defect)#
53 (DONE)
TENSORRT_VERSIONARG+ENV moved BELOW the CUDA RUN. An ARG in scope keys every following RUN, and nothing up to and includingInstall-Cuda.ps1consumes it — TensorRT arrives viaCOPY --from. With it declared above, bumping the TensorRT pin forced a ~3.8 GB CUDA + cuDNN re-download, which is precisely what made fixing #38 expensive. It now rides the existingGPU_TYPE/CUDA_ROOTENV block, so no extra layer is spent. Landed FIRST, on purpose.38 (DONE) The shipped image had a DEAD TensorRT EP.
versions.envpinned11.2.1.2while the staged archive wasTensorRT-Enterprise-11.1.0.106. Two contradictory resolutions of the same directory existed:Resolve-TensorRtRootglobbedTensorRT-*(pin-INdependent → correct) whileDockerfile.nvidiabuilt the runtime PATH from the PIN → a directory that did not exist. The build stayed green — logs confirm ×24TensorRT detected at C:\tensorrt\TensorRT-11.1.0.106andonnxruntime_USE_TENSORRT=ON, so ONNX compiled the EP against the real 11.1 headers — and only the RUNTIME lookup broke, so ORT dropped the EP with no error. A REGRESSION of the incidentversions.env:238-248documents verbatim (“Bump this WITH the staged zip, never alone”): the pin was bumped alone, because nothing ENFORCED the rule.A Machine-PATH write does NOT fix this (the first attempt, discarded):
Dockerfile.basesetsENV PATH=...explicitly, so the image config wins and a registry PATH written inside a RUN is invisible to later stages. The fix that works with the ENV is a stable directory NAME:NEW
windows/scripts/Set-TensorrtTree.ps1, bind-mounted into thetrt-extractstage: renames the NEWESTTensorRT-<version>tree (by[version]comparison, not a lexical sort — see the correction below) →current, WARNS (never fails) on pin-vs-zip drift so it can no longer be silent, folds a FLAT layout intocurrentas well, and fails closed when neitherbin\norlib\carries runtime DLLs.Dockerfile.nvidiaPATH is now$TENSORRT_ROOT\current\bin;$TENSORRT_ROOT\current\lib—binfirst because that is where TensorRT 10+ puts the runtime DLLs;libkept for the 8.x/9.x layout. Correct for any staged version, forever. The zip-less graceful-skip contract is unchanged (the directories simply do not exist and the entries are inert).Resolve-TensorRtRootpreferscurrent, falling back to the versioned glob so pre-normalization images and host-lane trees keep resolving. Two new tests pin both behaviours (486 total, was 484).
THE BUILD FOUND A SECOND, BIGGER DEFECT — the fail-closed gate earned its keep on its first run. The sdk rebuild failed with
TensorRT lib directory 'C:\tensorrt\current\lib' contains no DLLs. Inspecting the staged 11.1.0.106 Enterprise zip:dir
contents
lib\6 ×
.lib— link-time import libraries onlybin\14 ×
.dll— the runtime DLLsTensorRT 8.x/9.x shipped the runtime DLLs in
lib\; 10+ moved them tobin\, andDockerfile.nvidianever caught up. So the PATH entry was broken in TWO independent ways — wrong VERSION and wrong DIRECTORY — meaning the TensorRT EP could never have loaded at runtime in this image, even with a correctly-pinned zip. The pin mismatch merely hid the second defect behind the first. Neither failed a build, because ONNX resolves its BUILD-time root with a glob and only the RUNTIME lookup was wrong. Final form: PATH getscurrent\bin(runtime) andcurrent\lib(kept for the 8.x/9.x layout), and the normalizer requires DLLs in at least one of them.CORRECTION (independent review, same day). The first version of this script had two defects the review caught: it sorted the versioned trees lexically ascending and took the FIRST, i.e. the OLDEST — directly contradicting the owner’s “always newest” directive one file over; and its flat-layout branch printed “consumers use the root directly” while the ENV PATH pointed at
current\bin/current\lib, which on a flat tree do not exist. Two earlyreturns also bypassed the fail-closed DLL gate. All fixed and re-verified across five synthetic trees: newest-of-two wins (11.10.0.1over11.2.1.2— a lexical sort ranks these backwards), flat layout folds intocurrent, and a pre-existingcurrentwithout DLLs now exits 1 instead of returning early.VERIFIED, end to end. Synthetic trees on the host (normalize + drift warning, tree-without-DLLs → exit 1, tree-without-
lib\→ exit 1, empty root → exit 0 graceful). Then the real sdk build:TensorRT 11.1.0.106 normalized to 'C:\tensorrt\current' (14 runtime DLLs in: bin),[bk] Done in 00:12:00. Stages: sdk (GPU). Then a LOAD test against the produced image — the only proof that actually matters for this defect class:TRT_PATH_ENTRIES=C:\tensorrt\current\bin,C:\tensorrt\current\lib CONTROL LOADED VCRUNTIME140.dll TRTSUMMARY loaded=14 failed=0
Methodology note, worth keeping. The first load probe reported
LoadLibraryWerror 126 for all 14 DLLs and briefly looked like a third defect. It was the PROBE that was wrong: a hand-rolled[DllImport("kernel32")] LoadLibraryW(string)marshalsstringas ANSI by default, so a UTF-16 API received a byte string and answered “module not found”. The repo’s ownAssert-DllLoads(WindowsSmokeTest.Common.psm1:233) has always declared it correctly withCharSet=CharSet.Unicode. Two rules follow: use the existing helper rather than re-declaring P/Invoke, and always run a known-good control (hereVCRUNTIME140.dll) — the control is what exposed the harness, since the MSVC runtime obviously loads in an image built with MSVC. DRIFT RESOLVED THE SAME DAY — and it set a standing rule. The owner staged the newer 11.2.1.2 zip rather than accept a downgrade: “always use the newest tensorrt version”. Never resolve TensorRT pin-vs-zip drift by pinning BACKWARDS — that directive is now recorded at theTENSORRT_VERSIONdefinition in versions.env. Three follow-ons landed with it:TENSORRT_ZIP_SHA256was EMPTY, so ~2 GB of EULA-gated payload entered the image unverified. Now set (9cdb433f…) and verified by the build. Recompute it on every restage — a stale hash fails loudly, as intended.The superseded 11.1.0.106 zip was removed from
windows/downloads/(the owner’s original copy remains in~\Downloads).The extract RUN selected the zip with
Select-Object -First 1, which silently picks the OLDER file when two are staged. It now version-sorts descending via a[version]cast — a plain string sort gets this wrong (11.10.0.1must beat11.2.1.2; verified against four real filenames).
Final state, verified in the produced image:
VERSION_ENV=11.2.1.2 TREE=current CONTROL=LOADED VCRUNTIME140.dll RESULT loaded=14 failed=0
The rebuild took 2:24 vs 12:00 because
Install-Cuda.ps1came back CACHED — #53 paying for itself on its first real use: a TensorRT restage no longer re-downloads ~3.8 GB of CUDA + cuDNN.
Addendum — closed 2026-08-14 (Batch B: driver/log hardening, zero rebuild)#
Eight backlog items landed in one sitting. Selection criterion: none touches a Dockerfile, so nothing invalidated a cache layer and the whole batch was verifiable with lint + unit tests alone — no container build. Result: lint 152/0, tests 484/484 (up from 480; the 4 new ones are #40’s regression guard). All eight came out of the 2026-08-14 deep audit.
41 (DONE) The retry path destroyed the failing attempt’s log.
build-buildkit.ps1teed without-Append, so attempt 2 truncated attempt 1 — a stage that burned its budget kept only the last attempt, and when attempt 1 held the real compile error while 2-3 died on infra flakes the evidence was gone. Now: log cleared once per RUN, appended per ATTEMPT with a===== attempt N/M =====banner. Direct “never swallow logs” fix, inside the path that exists to survive failures.42 (DONE) The failure tail was computed, then thrown away — both lanes.
$tailwas built purely to CLASSIFY the error and then discarded, so the throw carried a bare path (BK) or a bare exit code (classic) and the owner opened a deliberately-unbounded log by hand. Both lanes now print the tail before throwing, and the classic lane’s throw names the log file.43 (DONE) 4 of 5 ninja logs died with the build tree; genai had none. Only ONNX wrote to the persistent
$SCCACHE_DIR\logs; opencv/iree/tvm/litert wrote inside$buildDir, which is discarded with the failed solve (IREE is a 60-120 min build whose only surviving diagnosis was a 50-line tail), andbuild-onnx-genaipassed no-LogFileat all, so not even that existed. Fixed as a SHARED helper, not five copies:Get-PersistentBuildLogPathinWindowsSourceBuild.Common.psm1, with all six call sites converted — including ONNX’s original inline block. Copy-paste is exactly how this drift happened; there is now one implementation to drift from.39 (DONE)
-MediaBranches <subset>silently shipped a STALE image. The merge is skipped on a branch subset, but torch/final still resolvedBASE_IMAGEfrom thewindows-mediatag — the PREVIOUS run’s merge. So “I fixed LiteRT, re-ship” delivered awinamd64without the fix, with a zero exit code. Now throws when the merge is skipped while torch/final are selected, naming both the subset and the missing branches.40 (DONE) The scripted resume never worked (closure scope).
.GetNewClosure()snapshots LOCALS only, but$Docker/$MediaCoreCpus/$MediaMemoryGb/$ResumeStageare script-levelparam()vars → empty inside the module invoker, degrading the run to[] run --isolation hyperv --cpu-count --memory "g"and dying with a PowerShell parser error that pointed nowhere. The identical fix had been on the siblingInvoke-RunCommitStagesince 2026-07 with an explanatory comment; this path never got it. Fixed with four local copies. Note the first draft of this entry overstated it: thedocker container rm -fis NOT data loss — the state is committed to$partialand exit-code-checked first, and the removal is required to reuse the container name. NEW TEST — guards the CLASS, not the instance:tests/Driver.ClosureScope.Tests.ps1walks the AST of both drivers, finds every.GetNewClosure()block inside a function, and fails if it reads a top-levelparam()variable that is not shadowed by a local. It correctly ignores top-level closures (there, params ARE locals) and locally-shadowed names like$isolation; it carries its own negative control (a synthetic re-introduction of the defect must be caught) and a false-positive control (the sibling’s correct pattern must NOT be flagged).62 (DONE)
-ConcurrentAuxdropped six parameters — three guaranteed a failure AFTER media-core was paid for. Children re-run the full preflight with defaults, so-SkipHostChecks,-SkipRdna4Gate,-SkipStepLogGate,-NoSccache,-MinFreeGb,-HostReserveGbnow forward.-ConcurrentAux -NoSccachepreviously could NEVER succeed. Same change adds fail-fast (a child dying at minute 5 was unnoticed until the other finished ~40 min later) and afinallythat stops surviving children — they were spawned outside anytry, so killing the parent orphaned two pwsh+buildctl trees racing the same store.63 (DONE) Every preflight-gate failure orphaned a hidden sampler. It started ~500 lines before the
trythat owns it, so each rejected launch (sccache down, RDNA4 enabled, disk short, dockerd stopped — all common) left an invisible-WindowStyle Hiddenpwsh in awhile ($true)loop forever, one per failed attempt. Moved to immediately before thetry/finally; the preflight costs seconds, so no sample coverage is lost.64 (DONE) The driver prescribed a remedy it could not express. The determinism gate says “the fix is
-NoCacheon this stage alone, NOT a retry”, but-NoCacheapplied to every solve — for a poisonedmedia-core-built-opencvthe only lever was-Stages media -NoCache, which re-does all four media-core sub-stages plus litert plus tvm plus merge. Added-NoCacheStage <label[]>, substring-matched against the same$Labelthe stage logs and disk gate already use (-NoCacheStage opencvworks).
Addendum — closed 2026-08-13 (:winamd64 green end-to-end)#
34 + ELEVATED WINDOW + dufs (DONE 2026-08-13, applied by owner). Owner ran the between-runs elevated bundle: (1) buildkitd service env restored (
BUILDKIT_STEP_LOG_MAX_SIZE/-SPEED=-1) so-SkipStepLogGateis no longer needed; (2) GC budgets deployed (Set-BuildkitdGcpolicy.ps1, buildkitd.toml 400/450GB) — fixes the cross-run snapshot eviction (#34); (3) poisoned probe-build-copy layer chain pruned (Test-BuildCopy.ps1no longer FALSE RED); (4) diagnostic tag cleanup. Also ranInstall-DufsService.ps1→ dufs is now a session-independent SYSTEM ONSTART task (no more mid-run WebDAV-write fail-open). Sanity:buildctl debug workers -vshould show reservedSpace=200GB.Upstream issues (POSTED 2026-08-13): mozilla/sccache#2808 (nvcc deadlock + miscompile) and google-ai-edge/LiteRT-LM#3245 (CMake-lane staleness). opencv/opencv (dnn ORT
char*/wchar_t) draft still unposted.28 (LANDED 2026-08-13) Ninja job-count
-MemGBPerJob 2. Changed4→2at the Build-OnnxFromSource.ps1 (line ~451) and Build-OpencvFromSource.ps1 (line ~295)Invoke-NinjaBuildWithRetrycall sites → ~19 jobs (from ~9) at the measured ~1 GB/process, well under the 39 GB budget. Code landed + lint/tests green; the throughput win verifies on the next full media-core build.27 (DONE + VERIFIED 2026-08-14) Dockerfile.base 1214-char single-line RUN → mounted script. Extracted the pwsh-7 bootstrap blob into
windows/scripts/Initialize-Pwsh.ps1(WPS-5.1-safe, byte-identical logic: 3-attempt backoff + in-loop SHA256 + original-exception rethrow) and rewrote the base RUN toRUN --mount=type=bind,source=windows/scripts/Initialize-Pwsh.ps1,target=C:\Initialize-Pwsh.ps1 & 'C:\Initialize-Pwsh.ps1'. Bind-mount, NOT COPY — no layer, nothing COPY’d this early in base by design; runs under WPS 5.1 (SHELL not yet switched to pwsh). Despite the item’s “never alone / batch with a base bump” caveat, verified standalone with a scoped-Stages basebuild: step#6 … RUN --mount=…Initialize-Pwsh.ps1… DONE 11.1s, build proceeded to VS Build Tools (#9) — the mounted-script bootstrap behaves exactly as the inline blob did. Lint 151/0, parse-clean. NOTE: landing it busts the base-tier cache (base instruction changed) → the next full chain rebuilds downstream of base; that cost is inherent to the change, not the verify build.37 (DONE 2026-08-13) TVM
import tvm→ WinError 127. Root cause was NOT an LLVM ABI skew (the archived suspicion): TVM 0.25 vendors3rdparty/tvm-ffiat an UNRELEASED commit (0.1.13.dev1, not on PyPI), so the PyPIapache-tvm-ffiwheel pip pulled was ABI-skewed vs our source-builttvm_runtime.dll. Fix = build tvm_ffi FROM the vendored source + install the tvm wheel--no-deps(Build-TvmFromSource.ps1). Three sub-fixes gated that source build:Copy-CpythonPyConfigHeader(CMake-4.4 FindPython can’t read in-tree pyconfig.h), installcython(core.pyx transpile → MSB8066), installtyping_extensions(--no-depsstarves tvm_ffi’s only declared dep). See memorytvm-ffi-source-build-winfix.36 (DONE 2026-08-13) litert branch → BAZEL — chain integration complete. The canary recipe (
Build-LitertLmBazel.ps1) was wired into the media-litert branch and the full chain built green; media-litert now produces litert_lm_main.exe via bazel, CMake path frozen as fallback. Included the zlib.net→GitHub-mirror WORKSPACE patch (flaky-download fix).(NEW, not previously numbered) GStreamer merge stage — 8 versions.env-bump regressions that blocked
:winamd64, all fixed 2026-08-13: /LIBPATH-breaks- clang-cl, opencv-5 data-dir + API relocation (xobjdetect/geometry/calib), tflite C-API export, cpp_std c++11→c++17 (MSVC 14.51 STL), plugin-LOAD gate (recursive dumpbin walker), and CUDA-runtime FLATTEN-deploy for opencv’s cudnn64_9.dll (Copy-CudaRuntime.ps1). Full detail in memorygstreamer-merge-winfix. Verified:[bk] Done in 00:41:30→local/kataglyphis:bk-winamd64(all stages, GPU).
Refactor Backlog (Windows container chain)#
Cross-lane / Linux-side items live in docs/refactoring-backlog.md; this section owns the WINDOWS chain exclusively (pointer there exists too).
Owner-requested backlog from the 2026-08-10 systematic code review (8-angle
sweep over windows/). Ordering = suggested attack order: correctness-adjacent
first, then reuse, then cosmetics. Before touching anything, check the
cache-tier map (AGENTS.md / windows-refactor notes): edits to base/toolchain
closure files force a full chain rebuild — batch those, and never remove the
deliberate media-merge version-ARG mirrors.
Contents: P0 architecture (0a-0c) → P1 correctness-adjacent (1-4, 16-19) → P2 reuse (5-9, 20) → P3 hygiene (10-15, 21-25) → second-pass build-definition/ops items (26-32) → pending host/upstream actions → already-fixed protocol. Cross-cutting pairs to do together: #1+#18 (RDNA4 single source), #7+#19 (patch-stanza helper incl. hard-fail rung), #8+#30 (log convention + retention).
Execution guide (effort·impact legend as in docs/refactoring-backlog.md; tier = what a change cache-busts)#
Work the backlog in BATCHES keyed on the cache tier — every media-closure edit costs one ONNX-vertex rebuild, so land them together:
Batch |
Items |
Tier |
Effort |
Impact |
|---|---|---|---|---|
W0 pending actions |
buildkitd env (now ENFORCED by the 0a gate — restore before run 13!), sccache issue, tag cleanup |
host |
S |
★★★ (unblocks log visibility) |
W1 host-only quick wins |
~~2, 5, 6, 8+30, 9, 12, 13, 15, 21, 22, 24, 25, 29~~ ALL DONE |
host scripts/tests only — zero cache impact |
S-M |
★★ |
W2 preflight architecture |
~~0a, 0c, 1+18, 26, 32~~ ALL DONE |
host (drivers, diagnostics, probe assets) |
M |
★★★ |
W3 media-closure batch |
~~3, 4, 7+19, 10, 11, 16+17, 20, 23~~ ALL DONE (2026-08-10 night, landed inside run 12’s already-busted closure window) |
media closure |
M-L |
★★★ |
W4 base-tier batch |
27 (+ anything else touching base closure) |
base — FULL chain rebuild; batch with the next planned base bump |
M |
★ |
W5 process/policy |
0b (CI half DONE — patch-drift job; human bump-protocol half stands), 28 (measurement RUNNING: per-process fleet sampler captured run 12’s ONNX compile → |
repo/CI policy + measurements |
M |
★★★ |
OPEN as of 2026-08-10 night: NEW 34 [M·★★★, P0] — the chain has NO
cross-run caching; MECHANISM IDENTIFIED (2026-08-11 ~08:15): snapshot GC
eviction under an undersized tier-2 budget, NOT export nondeterminism.
Evidence chain: (i) prefix stages rebuild every driver run (73/35 min
instead of seconds, zero manifest-digest overlap between runs 14/15);
(ii) back-to-back canary solves show digests ARE stable on cache-hit
re-export (with AND without SOURCE_DATE_EPOCH) — so the exporter is
deterministic given cached snapshots; (iii) the run-over-run delta is the
hours of vertex churn between runs: tier 2 (buildkitd.toml, keepDuration 720h, maxUsedSpace 150GB) is far below one night’s vertex fleet
(multiple ONNX/OpenCV generations at tens of GB each), so GC evicts the
OLDEST snapshots = the prefix stages; the re-solved layers carry fresh
internal file timestamps → new blobs → new digests → downstream FROMs
miss, cascade. BUILD_DATE/VCS_REF stamps are exonerated (they reach
only torch/final). FIX (elevated window, bundle with the W0 env restore):
raise tier-2 maxUsedSpace 150→350GB and tier-3 240→450GB in
windows/buildkitd.toml (930 GB disk, ~790 free — satisfiable; keep the
2026-08-08 invariants), redeploy via Set-BuildkitdGcpolicy.ps1.
SIDE-FINDING from the fix research: rewrite-timestamp=true on the
Windows image exporter CRASHES mid-finalize and poisons the layer chain —
never use it here (see the probe-chain cleanup pending-action). Item-34 fix research (2026-08-11 ~08:00): rewrite-timestamp=true on the Windows image exporter is DANGEROUS — it crashed mid-finalize (hcsshim::ActivateLayer ... process cannot access the file) and left a POISONED SNAPSHOT in the probe’s layer chain (same snapshot id failed identically on the next two solves; a unique-layer discriminator solve was green, so the damage is chain-local, not a host wedge). ⚠ Until that snapshot is pruned (buildctl prune of the probe refs / worst case reboot), Test-BuildCopy.ps1 will return a FALSE RED on this host — do not trust a probe verdict before the cleanup. Epoch-only canary (no rewrite-timestamp) running separately. NEW 35 [observe·★]: run-15’s ffmpeg stage stalled
for ~120 min between Enter-VsDevCmdEnvironment’s vswhere-fallback line
(15 s) and the awk-replacement line (7216 s) — a section that runs in
seconds normally (run 14: whole prefix 177 s; no scoop-install messages,
so both install branches were skipped). Smells like a stuck TCP/timeout
(VsDevCmd first-run or scoop probe); transient, self-recovered, build
continued green. If it recurs, wrap the section’s candidates in explicit
short timeouts. Also 27 (base-tier window), 28 (analyze the
captured samples → pool split), 31 (owner decision), 0b human half
(bump protocol), 33 (DONE 2026-08-11 morning: unmapped patch dirs now FAIL with
“add it to $repoMap”; current tree 12/12 mapped+OK.) Everything else in this
backlog is closed.
Done-when held throughout: gates green after every sub-batch (lint 141
files 0/0 incl. the new AST-trap pass, 457/457 tests), behavior changes in
AGENTS + this doc + CHANGELOG per repo priority 4.
Pending host/upstream actions (not refactors — do not let these evaporate)#
Restore the buildkitd service env (
BUILDKIT_STEP_LOG_MAX_SIZE=-1,MAX_SPEED=-1): found EMPTY on 2026-08-10 (wiped by the Stevedore/repair work); the default 2 MiB step-log clip hid verdicts all day. ElevatedInstall-NewHost.ps1(idempotent, refuses during builds) or the registry Multi-String +Restart-Service buildkitd— ONLY between chain runs. Since 2026-08-10 night this is ENFORCED:Assert-BuildkitdStepLogEnvrefuses to launch the BK driver until restored (0a).Make dufs session-independent (attribution dossier 2.8, 2026-08-10 night): today it is an ONLOGON scheduled task bound to the RDP session — alive at driver-launch time (so Assert-SccacheEndpoint passes), killable by a mid-run logoff/lock, and every WebDAV write then fails OPEN (multilevel policy
l0) with zero L2 entries as the only symptom. Convert to a Windows service or ONSTART/SYSTEM task + single-instance guard (two dufs.exe were live on 2026-08-10). Evidence:out/sccache-fault-attribution.md.Post the sccache upstream issue:
out/upstream-issue-sccache-nvcc.mdnow carries BOTH failure classes — the deterministic server death on the fused_moe launchers (±2 s across two runs) AND the silent miscompilation of arch-guarded instantiations (runs 10/11 vs bare-nvcc run 5, fresh-cache control) — ready to file against mozilla/sccache. The docker/for-win#14977 comment is already posted.Admin cleanup of 2026-08-10 diagnostic tags (
copyprobe-*,sweep-*,rdna4ab-*,flush-*,size*,pw*,mlchain-probe,verify-cuda-cache,postboot-*,nano-*,gpuab-*, plus the pre-rename stable probe tagsprobe-build-copyandprobe-build-copy-heavy— orphaned by the #29diag-prefix adoption, so thefindstr diag-one-liner does NOT find them): adminnerdctl --namespace buildkit rmiper docs § Store GC (see backlog #29 for the durable convention).
P0 — architecture-level (highest leverage; from the same review’s deep pass)#
0a. (DONE 2026-08-10 night: Assert-BuildkitdStepLogEnv (non-admin registry
read, throws with the elevated remediation, -SkipHostChecks downgrades)
closed the one missing cheap check — disk/shim/daemon/RDNA4/dufs-endpoint
gates already ran in both drivers. NOTE: the gate now REFUSES to launch
until the wiped buildkitd env is restored — do W0 first.)
Host-drift detection as a mandatory driver preflight. Four of the
2026-08-10 blockers were pure host drift (dufs ONLOGON task dead after
reboot, buildkitd service env wiped by the Stevedore repair, Defender
exclusion uncertainty, dGPU state): the code is reproducible, the host
is not. Test-HostSetup.ps1 already exists — carve out its CHEAP
subset (service-env registry read, dufs HEAD request, RDNA4 state,
shim hash) and run it at the top of BOTH drivers. Seconds at launch
instead of minute-80 surprises.
0b. (HALF DONE 2026-08-10 night: patch-drift job added to
windows-scripts.yml — Test-PatchesApplyClean now runs in CI on every
windows/**/versions.env trigger (shallow+sparse clones, ~minutes). The
HUMAN half stands: a versions.env bump still needs one local full-chain
build before trust — CI builds no containers.)
Version bumps must ride the Windows lane. The 2026-08-03 bump
(ONNX 1.28, OpenCV 5.0.0) carried FIVE latent Windows breaks because
[build-win] is opt-in and nobody built the bump. Rule: versions.env
bump commits require [build-win] (or a weekly scheduled canary), and
Test-PatchesApplyClean.ps1 runs as a pre-commit gate whenever
versions.env changes — that alone would have caught the OpenCV patch
drift before any container built.
0c. (DONE 2026-08-10 night: Driver.PreflightParity.Tests.ps1 — shared
contract table + lane allowlists with reasons + a catch-all that fails on
any NEW unlisted Assert-* in either driver; caught its first real case
(Assert-ImageExists) on the first run.)
Lane parity is unowned. The RDNA4 gate initially landed only in the
BK driver; the classic lane got it a day later via review. Either demote
build.ps1 to bootstrap-only, or add a parity test (BuildKit.TwinParity
is the in-repo pattern) asserting both drivers wire the same preflight
set.
P1 — correctness-adjacent (drift that already bites or will)#
(DONE 2026-08-10 night:
Get-Rdna4HazardDevice+Set-Rdna4DeviceStateexported from WindowsBuildDriver.Common are the single source; the gate, toggle (empty-GpuNamedefault = resolve all hazard SKUs,-NoPromptfor automation) and the A/B all consume them. +3 unit tests.) RDNA4 hazard set exists in THREE divergent copies: theAssert-NoActiveRdna4Gpuregex (covers RX 9xxx + AI PRO R9700), the hardcodedFriendlyName -eq 'AMD Radeon RX 9070 XT'inSet-Rdna4Gpu.ps1, and the same literal as-GpuNamedefault inTest-Rdna4LayerLock.ps1. Concrete dead end: on an RX 9060 host the gate refuses and points at a toggle script that cannot find the device. Fix: export ONEGet-Rdna4HazardDevicefrom WindowsBuildDriver.Common and let toggle + A/B resolve through it. (The gate regex additionally gained(TM)-rename tolerance on 2026-08-10 — the other two copies did NOT, widening the drift this item exists to close. Do together with #18.)(DONE 2026-08-10 — candidate lists landed same-day (scope note: the truly single-candidate set was 6); the night batch finished the consolidation: reset-container-stores + verify-cuda-cache now resolve via
Get-PreferredToolPath(candidates → PATH;$null-safe — the oldTest-Path $btthrew when buildctl was absent), and reset-container-stores’ hardcodedD:\GitHubrepo path became$PSScriptRoot-relative. DELIBERATE keepers: probe-build-copy stays inline (first-script-on-a-new-host must be module-free), collect-host-docker-state’s glob is forensics enumeration not tool resolution, deploy-shim-patch/verify-host-setup keep their overridable Program-Files param defaults — the shim deploy target must not silently follow a stale D:\ layout) The Stevedore tool path was hardcoded single-candidate in several files (2026-08-10 evening sweep: probe-build-copy, verify-cuda-cache, test-rdna4-layer-lock, test-layer-rename, test-process-isolation-commit, deploy-shim-patch, reset-container-stores, verify-host-setup, … — only build-buildkit.ps1 and friends carry the candidate list incl.D:\Stevedore\bin). On a D:\ layout the diagnostics throw exactly where they are needed, and the constant now has a dozen copies. Fix:Get-PreferredToolPath(already exported by WindowsScripts.Shared) everywhere; one candidate list, zero copies.(DONE 2026-08-10 night:
Write-SccacheStatsToStderrin WindowsScripts.Shared (name states the sink; the sink-stays-with-caller doctrine holds for other consumers); called end-of-build by ALL SIX source-build scripts — onnx, opencv, genai, tvm, iree, litert.) Consolidate the ONNX stderr stats loop intoWrite-SccacheStats(give the helper a-Sink Stderrswitch and call it) so formatting and the-RequireRemotecontract live in one place and the next CUDA consumer (TVM/OpenCV) inherits the clip-surviving sink for free. (The original finding’s acute half — the missing-RequireRemote, which would have spawned a throwaway server on no-remote builds — was fixed same-day; only the consolidation remains.)(DONE 2026-08-10 night: onnx ninja logs to
$env:SCCACHE_DIR\logs\onnx-ninja.log— the PERSISTENT cache mount, so the stream survives a failed vertex into the next run/debug container; one.prevrotation generation bounds growth.) ONNX ninja runs without-LogFile— the full ninja stream exists only in the (clip-prone) step log;[n/1891]progress is invisible from the host. Violates the never-swallow-logs invariant. Fix: pass a LogFile under the build tree (or out-mounted), always.
P2 — reuse / single-source-of-truth#
(DONE 2026-08-10 night: the A/B now delegates each GPU-state side to
Test-BuildCopy.ps1 -Heavy— digest-pinned base, lane logs and the output-shape lessons live once; the A/B only orchestrates GPU state.)Test-Rdna4LayerLock.ps1re-implements the finalize probe thatTest-BuildCopy.ps1(exit codes +-Heavy+ per-lane Tee logs) was just upgraded to provide. Fix: call the probe (or extract a shared lane-runner) so the load-bearing output-shape/quoting lessons live once. (Its log-swallowing was fixed same-day — the duplication remains.)(DONE 2026-08-10 night: toggle lifted into the module as
Set-Rdna4DeviceState(post-state-verified); toggle script + A/B finally block both consume it, and the toggle gained-NoPrompt+ exit 1 on a failed state change.) GPU toggle logic duplicated betweenSet-Rdna4Gpu.ps1and the A/B script’s finally-block re-enable (the safety-critical path). Fix: parameterize the toggle script (-GpuName,-NoPrompt) and call it, or lift the toggle into the module.(DONE 2026-08-10 night:
Invoke-SourcePatchWithFallbackin WindowsSourceBuild.Patches (fallback scriptblock runs in caller scope,-Fatalthrows on a double miss); all six build-onnx stanzas collapsed; 4 unit tests incl. the Fatal rung. See #19.) Patch-apply stanzas ×6 in Build-OnnxFromSource.ps1 (try → Invoke-SourcePatch → catch → inline fallback → WarnMessage, near-identical each time; 3 added on 2026-08-10 alone). Fix:Invoke-PatchWithFallbackhelper in WindowsSourceBuild.Patches.psm1.(DONE 2026-08-10 night:
Get-DiagnosticLogPath+Limit-DiagnosticLogsin WindowsScripts.Shared own path + retention; verify-cuda-cache consumes them, the A/B’s copy vanished with the #5 delegation, and probe-build-copy keeps its inline block BY DESIGN (module-free first-script rule).) Log-persistence convention has no owner. Pair with #30.(DONE 2026-08-10 night: script-local
Invoke-ProbeLane(exe check, Tee log, tail echo, exit report, attempted/failed bookkeeping) called for all three lanes; args are quoted array elements per the ArgQuoting lesson. NOTE: not yet live-smoked — runTest-BuildCopy.ps1 -Heavyonce after run 12’s media-core finishes, before trusting a verdict.) probe-build-copy’s three lanes are the same 9-line block ×3.
P3 — cosmetics / hygiene#
(DONE 2026-08-10 night: log reset once up front, every invocation appends; flag deleted.)
$invokeNinja’s positional$true/$falseappend flag (WindowsSourceBuild.Common): delete the LogFile once up front and always-Append— removes a silent-log-truncation failure mode and two branches.(DONE 2026-08-10 night: marker is the single channel; the job stream only speaks when a marker WRITE fails — see #17.) Stall-guard verdicts print twice (job stream + marker file re-read). Marker file is the single source of truth (ladder reads it, survives clip) — drop the Write-Output/Receive-Job channel.
(DONE 2026-08-10 W1)
Native.ArgQuoting.Tests.ps1manual case-insensitive loop —-notcontainsalready compares case-insensitively; five lines → one.(DONE 2026-08-10 W1) Fake-ninja ‘fail’ line evaluates its condition twice (SourceBuild.NinjaRetry.Tests) — fold into one guarded block like the FAILONCE line below it.
(DONE 2026-08-10 night: payload lives at
windows/diagnostics/verify-cuda-cache/Test-Cache.ps1(lint scope), copied into the solve context and run asRUN & C:\Test-Cache.ps1.)Test-CudaCache.ps1’s 21-statement concatenated RUN line.(DONE 2026-08-10 night:
git mv verify-defender-exclusions.ps1 Sync-DefenderExclusions.ps1, all references updated — the name now says what it does.)verify-defender-exclusions.ps1naming: it verified AND applied.
P1 addenda from the full sweep#
(DONE 2026-08-10 night: guard v2 — CPU delta demoted to pre-filter, verdict is a timed
sccache --show-statsclient probe (15 s, Start-Process +.Handlequirk); an answering server resets to healthy idle, a hanging probe = kill on first confirmation.) Stall-guard trigger is a CPU proxy — replace with a timed sccache client probe.(DONE 2026-08-10 night: marker truncated inside
$invokeNinjabefore every invocation, ladder classifies on THIS attempt’s kills only and prints lines as it consumes them;Add-Contentis try/catch with a loud job-stream fallback on write failure. +1 regression test (fail-fail-succeed at full-j×2). The former POISONING paragraph is RETRACTED: run 11 failed byte-identically on a FRESH mount — the run-10 link failure was the sccache nvcc MISCOMPILE (see the CUDA-launcher-OFF block in Build-OnnxFromSource.ps1), not truncated cache objects. The mount-id bump tosccache-winamd64-2stays, harmlessly.) Marker-based retry classification is not attempt-scoped.(DONE 2026-08-10 night, pragmatic form: gate-specific
-SkipRdna4Gatein BOTH drivers (message points atTest-BuildCopy.ps1 -Heavyas the evidence to earn it); the full probe-as-verdict altitude change is deliberately NOT built — the probe costs minutes, the gate seconds, and the skip-switch covers the healthy-host-after-driver-fix case.) RDNA4 gate altitude: regex-match should be the cheap trigger, the finalize probe the verdict (block only on a red probe); add a gate-specific-SkipRdna4Gateinstead of the all-or-nothing-SkipHostChecks(which also disarms the disk gates); the day the driver interaction is fixed upstream, healthy RDNA4 hosts stay blocked until module surgery.(DONE 2026-08-10 night: the 006 stanza passes
-FataltoInvoke-SourcePatchWithFallback— a double miss throws at patch time instead of re-arming the sccache crash at re-enable time.) Patch-fallback last rung is soft: when both the.patchAND the inline-regex anchor miss (next ORT bump),Invoke-InlineRegexPatchwarns and returns$falsepiped toOut-Null— for patch 006 that silently re-arms the deterministic sccache crash ~4900 s in. Hard-fail the 006 rung (-Requireor check the return).
P2/P3 addenda#
(DONE 2026-08-10 night:
Start-SccacheStallGuardreturns$nullwithoutTest-SccacheRemoteConfigured, same gate as the launcher wiring.) Guard job spawns even when sccache has no remote configured (baked into the toolchain image, so it exists on PATH in every container): gateStart-SccacheStallGuardonTest-SccacheRemoteConfiguredlike the launcher wiring does.(DONE 2026-08-10 night: detectors moved to
modules/WindowsLint.Common.psm1; Invoke-Lint runs them inside its parse loop (one parse per file,\archive\excluded, violations fail the gate) over a now fully-recursive windows\ walk that also picked upwindows\upstream; the test suite keeps the 6 positive controls.) AST sweep double-parses the tree every gate cycle.(DONE 2026-08-10 W1)
Test-CudaCache.ps1exports a throwaway image nobody consumes — drop--output(solve-only is enough for the hit/write assertions; contrast: the finalize probes NEEDtype=image,unpack=true).(DONE 2026-08-10 night: moved to
C:\sccache\logs\in both media Dockerfiles;Initialize-SourceBuildEnvironmentcreates the dir before the server can spawn — sccache does not create missing parents.)SCCACHE_ERROR_LOGsits at the root of a GC-capped cache mount — eviction under pressure can delete the postmortem exactly when needed; consider a subdirectory exempted by policy or copying the log out in the chain epilogue.(DONE 2026-08-10 night: prepended to all 40 remaining files, each matching its own EOL style.)
#Requires -Version 7.0missing acrosswindows/scripts/tests/.(DONE 2026-08-10 W1)
Test-Rdna4LayerLock.ps1StrictMode fragility:$offTiny/$offHeavyare only-safe-by-control-flow; initialize them up front so a future try/catch edit cannot turn the verdict line into a StrictMode error on the exact host being diagnosed.
Second deep pass (build-definition & operations angles, 2026-08-10 evening)#
The 8-finder review read almost only .ps1/.psm1; this pass covered the
Dockerfiles, resource economics, store hygiene and probe supply-chain.
Checked and deliberately NOT flagged: isolation-probe already parameterizes
its FROM; scrub coverage matches its documented tier map; .dockerignore
guards the context; the ENV/ARG mirrors are the documented deliberate ones.
(DONE 2026-08-10 W1: ARG BASE in both probe Dockerfiles; Test-BuildCopy.ps1 pins it to versions.env WINDOWS_BASE_DIGEST via dependency-free parse on all three lanes, smoke-verified; the A/B script inherits the tag default until #5) Probe Dockerfiles float their base (
FROM ...servercore:ltsc2025without a digest) while the chain pinsWINDOWS_BASE_DIGEST— when MS rolls the tag, the probe certifies a DIFFERENT base than the chain builds on, and pulls a fresh multi-GB image to do it. Fix:ARG BASElike Dockerfile.isolation-probe, defaulted by the probe script from versions.env’s digest.Dockerfile.base carries a 1214-char single-line RUN (the pwsh bootstrap blob) — unreviewable and undiffable. Move to a mounted script like the heavy lanes; BASE-TIER CLOSURE, so batch it with the next planned base rebuild, never alone.
~60-70 % of the CPU is idle during the heaviest stage (26-31 % total at ONNX
-j9, memory-capped by a flat MemGBPerJob=4 that treats a 200 MB CXX TU like a 4 GB flash-attention TU). AGENTS.md priority 1 calls idle cores “the standing wall-clock reserve”: measure real per-TU-class peaks, then split into heavy/light ninja job pools or per-stage MemGBPerJob. Potentially the single largest wall-clock win left in the chain. (MEASURED COMPLETE 2026-08-11: run-13 full window, 7821 samples @15 s (run13-tu-memory-samples.csv) covering toolchain build + the ENTIRE ONNX vertex incl. the early flash-attention region + the OpenCV attempt; corroborated by run-12’s 1453-sample tail window. Peak per-process WorkingSet: cicc 998 MB / clang-cl 989 / cudafe++ 944 / ptxas 830 — NO process reaches 1 GB; peak concurrent fleet total 5.5 GB across 21 processes at-j9. READY TO LAND:-MemGBPerJob 2at the build-onnx/build-opencv call sites → 19 jobs (peak assumption still ~2× measured; extrapolated fleet ≈ 11-12 GB against the 39 GB budget). DELIBERATELY NOT hot-landed mid-run-14: media-closure edit = one more ONNX rebuild, so bundle it with the NEXT closure window per the standing cache-tier rule.)(DONE 2026-08-10 night: the tag-minting diagnostics now share the
diag-prefix (diag-probe-build-copy[-heavy], docker lanelocal/test:diag-probe-build-copy; the A/B mints nothing since the #5 delegation, verify-cuda-cache nothing since #22). Cleanup one-liner: adminnerdctl --namespace buildkit images | findstr diag-→rmi. The pre-convention 2026-08-10 tags — incl. the oldprobe-build-copy[-heavy]names — stay on the pending-cleanup list.) Diagnostic image debris pins store layers.(DONE 2026-08-10 night:
Limit-DiagnosticLogsretention — driver keeps the newest 80 stage logs inout\windows-build-logs, diagnostics the newest 60 inout\build-logsviaGet-DiagnosticLogPath. Console-log convention: the LAUNCHER names one timestamped file per driver invocation — never append across runs.) Build-log growth is unbounded.Green stage images live ONLY in the local containerd store until a manual
-PushRef— a host loss (this host has form: repair-installs, driver surgery) costs every stage. Auto-push green stage tags (or at least export-cache) once a chain goes green; the driver params already exist, they are just never invoked by default.(DONE 2026-08-10 night — answered by reading the workflow: the Windows CI lane is GITHUB-HOSTED
windows-latest, builds NO container images (scripts gate only, stated in windows-scripts.yml’s header) and hosted VMs carry no AMD dGPU → CI is immune to the RDNA4 hazard; the gate/toggle workflow is local-host-only, which is where it lives.) Document the CI runner’s GPU class vs the RDNA4 hazard.
Already fixed during the review session (2026-08-10, for the record)#
The sweep also surfaced correctness bugs in same-day code; these were fixed
immediately rather than backlogged: probe zero-lane false-green (exit 0 with
no lane run), Repair-WindowsComponentstore.ps1 still using the retired
type=local probe shape, the classic lane (build.ps1) missing the RDNA4
gate, Get-SccacheStatsText not re-exported (would have thrown AFTER the
multi-hour ONNX build), Dockerfile.heavy’s trailing-backslash COPY dest
(Dockerfile escape char), the RDNA4 A/B swallowing lane logs and re-enable
failures, the (TM)-rename hole in the hazard regex, the opencv/001 patch
EOL flip, SCCACHE_ERROR_LOG parity for the merge builder, and a stale
module comment describing the abandoned launcher-opt-out design.