This file lists every engine-level change LocalRouter carries against the engines it runs, with each one's upstream pull request. It counts patch files, scripted edits of upstream files, flags or workarounds that exist only because of an upstream bug or a missing option, and vendored upstream code. Each entry gives where it lives here, what it changes and why, whether upstream has it, and what happens next. CONTRIBUTING.md requires an entry and an upstream pull request for every new one.
Audited 2026-10-31 against the latest upstream default branches:
- ashhart/TensorFold
mainatacea3b52(after v1.2.0); - plotarmordev/drama-tensorfold
mainat4d9cfb2; - plotarmordev/TensorFold
drama-nvfp4atb1f4b9b4.
| # | Change | Upstream | Upstream PR | Our side |
|---|---|---|---|---|
| 1 | Drama 3 voice prefix cache, CUDA full model | ashhart/TensorFold | #1745 | drop patches/engine/ at the first full-model pin that includes it |
| 2 | Drama 3 voice prefix cache, CUDA NVFP4 | plotarmordev/TensorFold drama-nvfp4 |
already proposed: plotarmordev/TensorFold#4 (not ours) | drop patches/engine-nvfp4/ once #4 merges and drama-tensorfold repins NVFP4 |
| 3 | Launchers: --external-admission (+ Linux --reserve-gib) |
plotarmordev/drama-tensorfold | #35 | replace both launcher patches with flags |
| 4 | Launchers: --parent-pid (macOS; Linux for callers without PR_SET_PDEATHSIG) |
plotarmordev/drama-tensorfold | #36 | as 3 |
| 5 | Launchers start under python3 -I |
plotarmordev/drama-tensorfold | #37 | as 3 |
| 6 | Streamed reasoning_content keeps a trailing newline |
ashhart/TensorFold | #1743 | drop the qualification exception once the chat pin includes it |
| 7 | graph.endCapture leaves the capture scope open on failure |
ashhart/TensorFold | #1744 | drop the two captureEnd calls once the runtime pin includes it |
| 8 | Tokenizer has no Lowercase normalizer (CLIP) |
ashhart/TensorFold | not opened: no upstream model needs it | keep clip_tokenizer.zig's own pass |
| 9 | Chat pinned to 1.1.1 on GB10 (1.1.4 resumes only at 4,096-row chunks) | ashhart/TensorFold | none: a pin choice, no code carried | re-measure on each new release |
| 10 | cuBLASLt with a recorded algorithm; driver identity check | ashhart/TensorFold | not upstreamable: LocalRouter's attestation policy | keep |
| 11 | NVFP4 kernels copied from TensorFold v0.6.1 | ashhart/TensorFold v0.6.x | not upstreamable: unmodified copies of a frozen line | keep |
| 12 | Idol pipeline built with local, ungated encoders (no from_pretrained option for them) |
speridlabs/idol-sdk | #3 | drop the hand-built IdolPipeline once the SDK takes encoder paths |
Not ours, and not listed above:
- The series pinned by hash in
tools/speech/drama3/pins.json(59 patches,engine/patches/at drama-tensorfold1a53b8ae) andpins-macos.json(5 patches,engine/nvfp4/macos/patches/atdb6ba7da) are drama-tensorfold's own: every patch'sFrom:line and commit is plotarmordev's, and every pinned sha256 equals that commit's file, checked on 2026-10-31. All 59 are in TensorFold v1.1.9, which the full model now pins with an empty series. apps/mobile's react-native patch.
- Here:
tools/speech/drama3/patches/engine/0001-drama-a-voice-s-reference-rows-are-prefilled-once-an.patch, applied bybuild.shafter upstream's series. Added incd45432(#25). - Upstream file: TensorFold
zig/src/native/drama_host.zig,zig/src/families/drama/{backbone,tower}.zig. Our patch targets drama-tensorfold's old engine base (TensorFoldc7137bb3+ 59 patches); the full model now pins TensorFold v1.1.9 with no patches. - What and why: a voice's reference rows (280–431 frames plus their transcript) were prefilled again on every request. The patch snapshots backbone and tower state after them and restores it for a later prompt with the same rows. On DGX-01, streamed first audio p50 went from 0.67–1.16 s to 0.127–0.134 s, with replies byte-identical with the cache on and off (DRAMA3.md).
- Upstream today: main has the Metal counterpart (
a06a4dff, from #1237, "CUDA stays uncached") and no CUDA cache. - General? Yes. The upstream port cuts on a prefill chunk boundary, as Metal does, so a cached reply is the same bytes as an uncached one. Ours cuts at the system message, which changes chunk cuts for referenced prompts.
- PR: #1745. Host tests run over a fake lane (cached cuts and state equal uncached). The Linux CUDA host build and the macOS Metal build both compile.
- Review: the maintainer asked for PCM sha256 with
TF_DRAMA_REFERENCE_CACHE=0against the default, on a voice → default → voice sequence with a repeat, atTF_DRAMA_PREFILL_ROWS1 and 128, with 2 concurrent lanes on one voice, and the hit's prompt time both ways. The PR now carriestools/zig/drama_reference_cache_check.py, which runs that matrix against a CUDA build and fails on any PCM difference, a hit with the cache off, or no hit with it on. - Next: run it on a GB10 and post the numbers. Not yet run: this Mac has no CUDA and the Spark wasn't reachable from here.
- Here:
tools/speech/drama3/patches/engine-nvfp4/0001-…patch, the same cache ported to plotarmordev'sdrama-nvfp4branch (b1f4b9b4). Added in67eb7ed(#77). - Upstream today: an equivalent pull request by another contributor, plotarmordev/TensorFold#4, is open. It is chunk-aligned and byte-identical, with GB10 receipts.
- PR: none of ours. That would duplicate #4.
-
Here:
tools/speech/drama3/patches/pilot-external-admission.patch(Linuxrecipe/pilot.py,68ca3bd, #13) and part ofpilot-macos-external-admission.patch(recipe/pilot_macos.py,4bf4b70, #136).fetch.shandsetup-macos.shapply them withgit applyto a copy underROOT/launcher/. -
What and why: the launchers enforce their own admission and abort thresholds: 88 GiB
MemAvailableon Linux, and weights + 30 GiB free+inactive on macOS, each with a 34 GiB abort. On Linux the engine also has a fixed 34 GiBTENSORFOLD_MEMORY_RESERVE_GIB. LocalRouter admits each load from its own budget, so these refused loads it had admitted. -
General? Yes: a flag for any supervisor that budgets memory itself. Upstream has no equivalent (macOS's
--min-available-gibcannot go below 34 GiB). -
PR: drama-tensorfold#35 adds
--external-admissionto both launchers and--reserve-gibto the Linux one. Tested:- unit tests;
- a macOS smoke test;
- the real NVFP4 Metal engine on this Mac Studio: at 47.7 GiB free+inactive, main refused with "Need 50.76 GiB"; the branch was ready in 5.6 s and served a request.
The Linux launcher was not run end to end (no systemd/CUDA here). Our patch has run on the GB10.
- Here: part of
pilot-macos-external-admission.patch(4bf4b70, #136). - Why: macOS has no parent-death signal. When the worker is killed, the launcher and server stay up, holding the lock and the memory.
- Linux: our Linux worker arms
PR_SET_PDEATHSIGon the launcher, so it has no gap here. A caller that cannot (a shell, another supervisor) had the same one, so #36 adds the flag torecipe/pilot.pytoo: once the parent is gone it stops the systemd unit and recordsparent_exited. - PR: drama-tensorfold#36, both launchers. Tested on
macOS with smoke tests using a real orphaning parent and with the real Metal engine: the supervisor exited, then
stop_signalwas 15, the group settled and the server was gone. On Linux, unit tests (they fail on main) mock systemd; not run on a Spark.
- Here: part of
pilot-macos-external-admission.patch(4bf4b70, #136). Both launchers now importweight_selection, which-Icannot find. - PR: drama-tensorfold#37. Tested: a new test fails on
main and passes on the branch, and the real engine served a request under
-I.
- Here: no code change. It is a named exception in the chat qualification
(
tools/chat/qwen38-27b/qualify.py,STREAM_REASONING_TRAILING_WS,685f517, #14), also used bybench_macos.py. The bug report draft istools/chat/qwen38-27b/upstream-issue-stream-reasoning-newline.md. - Upstream file:
zig/src/server/chat.zig. The whole replypyStrips the reasoning; the stream sends it as decoded. The bug is still on main. - PR: #1743. Tested on Metal (Qwen3.8-27B, this Mac): the stream went from 599 to 598 bytes on main's repro, equal to the whole reply; tokens and content unchanged. CI runs the zig suites. The maintainer approved it and rebased it onto main; it lands with their next batch.
- Here:
src/engines/qwen_image/dit.zigandsrc/engines/minimax_h3/dit.zigcallcuda.copy_source.captureEndthemselves whenendCapturefails (37755e0, #92, the 1.1.4 runtime pin). - Why: since 1.1.x,
endCapturecloses copy-source's capture scope only on success. After an invalidated capture, every later capture andDeviceBuffer.upload/fromHostin the process is refused. This is still on main. - PR: #1744. A no-GPU fake-driver test fails on main; it was compiled on Linux and CI runs it. No CUDA run. CUDA only: Metal has no capture scope. No review yet.
- Here:
src/engines/kandinsky6/text/clip_tokenizer.zigremoves theLowercasestep fromtokenizer.jsonbefore TensorFold parses it and lowercases the text itself. TensorFold's tokenizer has noLowercasenormalizer, and main still lacks one. - Not opened: no TensorFold model uses a lowercasing tokenizer. Upstream's rules count code with no in-tree user as dead code. Revisit if TensorFold adds a CLIP or BERT-style encoder. Kandinsky-6 is GB10 only.
- Here:
tools/chat/qwen38-27b/pins.json(251503f, #97); the Mac uses 1.1.4. 1.1.4's prompt cache resumes only at 4,096-row prompt chunks, so a short conversation's next turn is prefilled again (first token 1.46 s, against 0.1–0.3 s on 1.1.1; CHAT.md). - Not a patch: we carry no code. Before the pin moves,
chat_bench.py turnmust match 1.1.1. It has not been measured on v1.2.0.
- Here:
src/engine/vendor/cublaslt.zigandsrc/engine/vendor/driver.zig. They add cuBLASLt plans with a recorded algorithm from a pinned library, and a check of the libcuda identity. TensorFold is not changed. - Not upstreamable: these implement LocalRouter's attested-library policy, not a TensorFold gap.
- Here:
kernels/cuda/nvfp4/*, written bytools/kernels/sync.py. They are whole files, with only the torch includes and host wrappers cut. - Not upstreamable: the kernels are unmodified, and the v0.6.x Python line takes no changes.
- Here:
tools/asset3d/idol/worker.py(IdolEngine.load,dinov3_from_timm). The worker buildsIdolPipelinewithobject.__new__and fills in what its__init__would: Idol's own weights from the pinned local copy, DINOv3 ViT-H+/16 from the ungated timm checkpoint remapped in memory into Transformers' DINOv3 graph, and the FLUX.2 autoencoder from FLUX.2-klein-4B'svae/withlocal_files_only. idol-sdk is pinned at4702a7f0. - What and why: Idol's
config.jsonnames its image encoders by Hub repo (image_encoders: the gatedfacebook/dinov3-vith16plus-pretrain-lvd1689mandblack-forest-labs/FLUX.2-dev), andImageEncoderloads them withAutoModel.from_pretrained/AutoencoderKLFlux2.from_pretrainedafterrequire_encoder_accesschecks the gate. So the SDK needs a Hugging Face token and accepted DINOv3 terms, and it cannot take the ungated timm layout. The shipping path takes no token and never fetches a gated repo. The remapped DINOv3 parameters are byte-identical to the gated checkpoint and its features bit-identical; the kleinvae/gives the same latents (worker README). - Upstream today: no option to pass encoder paths or modules, at the pinned commit and on
main. - General? Yes: anyone running offline or without the gated repos needs it.
- PR: #3:
image_encodersonIdolPipeline/from_pretrainedtakes each encoder from a Hub repo id, a local folder or a loaded model, and checks only repo ids for gated access. Checked on MPS offline with no token: the timm-remapped DINOv3 and klein'svae/give the avocado byte-identical to the stock gated pipeline (sha256b6e814f5…). A loaded model is not cast: casting it to bf16 also cast DINOv3's fp32 RoPEinv_freqand changed the PLY. No review yet. - Next: once #3 merges, repin idol-sdk and replace the hand-built pipeline with a
from_pretrainedcall (image_encoderswith the remapped DINOv3 and the local klein folder);test_worker.pycovers the loaded graph.