Skip to content

Pin the full model to TensorFold v1.1.9 with no patches - #33

Merged
plotarmordev merged 5 commits into
mainfrom
feat/tensorfold-1.1.9-rebased
Oct 30, 2026
Merged

plotarmordev merged 5 commits into
mainfrom
feat/tensorfold-1.1.9-rebased

Conversation

@plotarmordev

@plotarmordev plotarmordev commented Oct 30, 2026 •

Copy link
Copy Markdown
Owner

Description and motivation

I move the full-model engine pin from TensorFold d1018b31 to v1.1.9 (465e48b6). The full-model patch series is now empty. v1.1.9 already includes every patch I carried:

Old patches In TensorFold since Upstream
0001–0011 (prefill rows, replay fix, frame budget, controls allowlist, voice catalogs, silence guard and redraws) v1.1.4 #1119, #1120, #1134, #1135, #1152, #1157–#1162
0012 reference-prefill reuse v1.1.5 a06a4dff, #1237
0013/0014 request sampling controls and JSON boundaries v1.1.6 #1277 (e19b8073, 90082556)

v1.1.9 also includes the slot-release fix (7e43ebeab, #1438), which shipped in v1.1.8. So this bump needs no local patch for it.

Patch check against v1.1.9: 0013 and 0014 no longer apply with git am, because the files they add (docs/speech-sampling.md, zig/src/server/speech_sampling*.zig) already exist there. I applied 0001–0014 to d1018b31 and compared the result with v1.1.9:

  • docs/speech-sampling.md is identical.
  • speech_sampling.zig and its test differ only by upstream's later fix 4a556244, which sends a temperature of -0/-1e-400 to the sampler as +0.
  • v1.1.9's zig/src/server/root.zig registers both test files.

The same is true for the dialogue-speaker patch 0015 that #28 added: v1.1.9 already ships it (#1278), so this branch removes it.

What changes:

  • engine/UPSTREAM now pins v1.1.9. The 14 full-model patches are removed. engine/patches/SHA256SUMS stays as an empty file, which declares the empty series.
  • scripts/build-engine.sh accepts an empty series only for --weights full, and only when the manifest is present and empty. An empty NVFP4 manifest, a missing manifest and a manifest that lists a patch that is not there all still fail before checkout. A model-free build test covers these cases.
  • recipe/pilot.py passes TF_DRAMA_PREFILL_ROWS=128 for full and custom checkpoints on the Linux native backend. Upstream defaults to single-row prefill, and old patch 0001 turned batched prefill on. NVFP4 and the sglang backend are unchanged.
  • README, engine/patches/README.md, CONTRIBUTING, NOTICE, the macOS and sampling docs and CHANGELOG now describe the new pin. They also name its two behaviour differences:
    • With the mid-silence rule on, X-Silence-Mid-Trips now counts only the returned take. This has been true since v1.1.4 and is unchanged through v1.1.9.
    • The -0 temperature sign fix above.

The NVFP4 pins (CUDA and Metal) and their patch series are untouched.

This replaces #31 (same change on the old base) and the earlier 1.1.4 bump branch, neither of which I will merge.

Rebased onto main after #28 (f68738ea):


Testing

CPU only. I built and tested on a GB10 host, without using its GPU. The engine builds below ran on #31's head cb958306; the rebase adds only docs, the result note and the removal of 0015, so the B build input (465e48b6 + 0 patches) is unchanged.

  • Engine builds, ZIG=zig-0.17.0 NVCC=/usr/local/cuda/bin/nvcc JOBS=4 scripts/build-engine.sh --weights full <dir>:
    • A, on main db6ba7da: d1018b31 + 14 patches = e0f55c97. Exit 0 in 3:46. tensorfold-native sha256 93fc4ca1…d249, reports version 1.1.1.
    • B, on this branch cb958306: 465e48b6 + 0 patches = 465e48b6. Exit 0 in 4:32. tensorfold-native sha256 ca64be09…9c89b, drama3-generate sha256 32bbb744…6027, reports version 1.1.9.
    • The B binary's serve --help lists the guard flags the recipe uses. --voices, --allowed-controls and --max-frames don't appear in the help text on A or B; I found them in v1.1.9's zig/src/server/cli.zig.
  • python3 -m unittest discover -s recipe -p 'test_*.py' on this head: 50 tests OK, 15 skipped (the explicit macOS subprocess smoke tests).
  • sha256sum -c SHA256SUMS on this head: CUDA NVFP4 4/4 OK, Metal NVFP4 6/6 OK; the full-model manifest is empty with no patch files.
  • The new build test fails against main's scripts/build-engine.sh (1 failure) and passes with this change.
  • python3 bench/stream_check.py --self-test on this head: passed.
  • bash -n scripts/build-engine.sh: OK.
  • python3 gpu-checks/runner.py --patch-selftest and --diag-selftest on this head: PASS (B full runs no checksum step, a changed NVFP4 patch or build script aborts the identity check, a build from another pin is not reused, a prep abort writes an INCONCLUSIVE summary).
  • zig build test -Dnvcc=/usr/local/cuda/bin/nvcc in the v1.1.9 engine tree: exit 0 in 9:23. The test output includes expected-failure lines from negative cases. The build host exposed no CUDA device, so this covers host-side tests only.

GPU A/B pins (gpu-checks/runner.py): A = f68738ea (main: d1018b31 + full-model patches 0001–0015 and the CUDA NVFP4 series). B = 3f44de62 (this branch's v1.1.9 tree; a commit cannot name its own SHA. Its engine/, scripts/, recipe/ and bench/ equal this head's; the runner itself runs from the synced gpu-checks/). I compare against main because this pull request claims v1.1.9 matches the current 0001–0015 series; an older A would count 0013–0015 as v1.1.9 differences. Both trees take the same requests: seeds and speaker tags on A too, and the same tagged catalog. Each full build must reach its one deterministic HEAD (A 3e1721df, B 465e48b6); a build from any other pin is never reused. A and B pin the same NVFP4 engine: the runner checks that from the git tree of engine/nvfp4 and the two reviewed build-engine.sh blobs before any build, builds no NVFP4 engine and runs no NVFP4 A/B check. gpu-checks/plan-output.txt and diag-plan-output.txt are regenerated from --plan / --diag --plan.

Not run yet: GPU A/B. I will run gpu-checks/run-all.sh on the device when its GPU is free. On both trees with the full model it runs: G1, the streaming check, two corpus capture passes and the reference-cache transitions, then compare_gate.py on the captures, whose byte-identity true/false is recorded as a result; G2, request sampling (seed repeatability, temperature, top_k, top_p, and a 400 for top_k 65); G3, the tagged and untagged dialogue line with the builtin and the tagged catalog voice. run-diag.sh adds D1, the issue #32 frame-cap count for that dialogue at seeds 1–5 on both trees, and D2, Whisper word error rates for D1's replies. I will add the results here. Until then this pull request has no audio-identity or qualification evidence, and I expect no byte identity with A: upstream changed the engine between d1018b31 and v1.1.9.


Performance or quality claim

None.


Checklist

  • One change per patch, new patches at the end of the series, SHA256SUMS and engine/patches/README.md updated (series emptied; manifest kept empty)
  • scripts/build-engine.sh applies the whole series and builds from a clean checkout
  • Every behaviour change has a deterministic test that fails without it
  • No dead code, debug output or leftovers
  • No personal voices, recordings, private names, host names or private paths in code, fixtures, docs, evidence or commit messages
  • Where audio should not change, compare_gate.py reports "identical": true and stream_check.py passes; where it changes on purpose, the qualification gates are reported before and after (pending the GPU A/B)

TensorFold v1.1.9 (465e48b6) carries every full-model patch I shipped:
0001-0011 since v1.1.4, the reference-prefill reuse (0012, a06a4dff)
since v1.1.5, the request sampling controls (0013/0014, #1277) since
v1.1.6 and the speaker tags (0015, #1278, landed as 715a074dd). It also
has the slot-release fix (7e43ebeab, #1438) since v1.1.8. 0013 and 0014
no longer apply to v1.1.9 because their files are already there; the
patched speech_sampling sources differ from v1.1.9 only by upstream's
+0 temperature fix (4a556244).

- engine/UPSTREAM moves to v1.1.9; engine/patches keeps an empty
  SHA256SUMS that declares the empty series. Patch 0015 and its
  manifest line go; its README row moves into the v1.1.9 table.
- scripts/build-engine.sh accepts an empty series only through an
  empty manifest; a missing manifest or a listed-but-absent patch still
  fails before checkout. A new build test covers both.
- The Linux pilot sets TF_DRAMA_PREFILL_ROWS=128 for full and custom
  checkpoints, because upstream defaults to single-row prefill and the
  old patch 0001 turned batched prefill on.
- README, patch README, CONTRIBUTING, NOTICE, macOS and sampling docs
  and CHANGELOG describe the new pin and its two behaviour differences.
- recipe/README-dialogue.md states that the frame-cap stopping result
  was measured on the previous pin plus patches and that v1.1.9 is
  untested (#32); README and CHANGELOG point to that section.
- results/dialogue-stopping-20261030.json records the NVFP4 build's
  source tree (1ff01f58) beside its commit; no measured value changes.
- scripts/build-engine.sh accepts an empty SHA256SUMS only for `--weights full`;
  an empty NVFP4 manifest still fails the build. The existing empty/missing
  manifest test now also proves an empty NVFP4 series is refused.
- gpu-checks/runner.py skips `sha256sum -c` when the full-model manifest is
  empty with no patches (same rule as build-engine.sh), so the pending GPU A/B
  can verify the v1.1.9 tree. Its patch selftest covers the skip and an empty
  NVFP4 manifest still failing.
- README.md and CHANGELOG.md mark the v1.1.9 behaviour match as per upstream
  source with the GPU A/B pending, the CHANGELOG frame-cap note as measured on
  the previous pin, and recipe/README-macos.md says the Mac full-model build
  at v1.1.9 has not been run yet.
- runner.py pins B to 3f44de6 (this branch's v1.1.9 tree; a commit cannot
  name its own SHA, and 3f44de6 already carries the matching runner and
  build rules). A stays a7752b4.
- B's full model is unpatched by contract (empty v1.1.9 series), so the
  runner runs no sha256sum step for it; B's NVFP4 series is still
  checksum-verified. The patch selftest covers both.
- sync-to-device.sh bundles the new B commit.
- plan-output.txt and diag-plan-output.txt are regenerated with --plan and
  --diag --plan (CPU only).
- runner.py pins A to main f68738e (d1018b31 + full patches 0001-0015 and
  the CUDA NVFP4 series); B stays 3f44de6. A's full and NVFP4 series and
  B's NVFP4 series are checksum-verified; B's full model is unpatched.
- A and B carry the same NVFP4 engine, so I build both NVFP4 engines only to
  prove their patched source trees identical, say so in the plan and
  summary, and drop every NVFP4 check (old G1/G2/G5 NVFP4, G3, G4, D1, D2
  and their CPU probes).
- The run compares the full model like for like: corpus/stream/reference
  cache (G1), request sampling on both trees (G2), tagged and untagged
  dialogue on both trees (G3). A loads the tagged catalog; the untagged-only
  baseline workaround is gone.
- The diagnostic round is D1 (issue #32 frame cap: both trees, tagged and
  untagged dialogue, seeds 1-5) and D2 (Whisper WER on D1's replies). A's
  unseeded, untagged-only D3 group is gone.
- sync-to-device.sh bundles f68738e instead of a7752b4 and no longer copies
  the corpus (each tree carries its own; the corpus preflight fed only the
  old D1). GPU_CHECK_NVFP4_CHECKPOINT is no longer required.
- plan-output.txt and diag-plan-output.txt are regenerated with --plan and
  --diag --plan; README describes the new pins and checks.
- G1 records compare_gate.py's identical true/false as a measured result
  (g1_gate in the summary) and runs it after both trees' reference-cache
  step; only a missing or inconsistent gate report fails G1.
- Builds are tied to the pins: each full build has one deterministic HEAD
  (A 3e1721df = d1018b31 + 0001-0015, B 465e48b6 = v1.1.9), a build at any
  other HEAD is never reused, and a rebuild must reach the pinned HEAD. The
  diag selftest covers a stale build being refused.
- NVFP4 identity is checked from sources before any build: the same
  engine/nvfp4 tree in A and B and the two reviewed build-engine.sh blobs.
  No NVFP4 engine is built; the patch selftest covers a changed NVFP4 patch
  or build script aborting.
- Any prep-time abort writes an INCONCLUSIVE summary with its reason; main
  runs now also record builds and write root/build-manifest.json.
- selftest-output.txt is deleted (stale; selftest.sh must run on the device
  host). README says what to do with an existing root/.
- plan-output.txt and diag-plan-output.txt are regenerated.
@plotarmordev

Copy link
Copy Markdown
Owner Author

GPU A/B on DGX Spark (CUDA), head 68c6308, A = main f68738ea, B = 3f44de62 (TensorFold v1.1.9, no full-model patches). Both full builds reached their pinned HEADs.

Check Result
G1 corpus captures, byte comparison A vs B PASS, byte-identical
G2 request sampling (seeds, temperature 0, top-k 1) PASS
G3 tagged and untagged dialogue PASS

Status: complete (wall time about 40 min including both builds). I haven't listened to the audio yet. The issue #32 frame-cap diagnostic (D1/D2) on both trees is running now; I'll post it here when it finishes, and I'm holding the merge until then.

@plotarmordev

Copy link
Copy Markdown
Owner Author

Issue #32 frame-cap diagnostic (D1/D2), same pins, CUDA full model, seeds 1–5:

Tree Tagged dialogue capped Untagged capped
A main (previous pin + 0001–0015) 3/5 0/5
B TensorFold v1.1.9 3/5 0/5

Per-reply bytes, durations and RMS are identical between A and B, so v1.1.9 behaves exactly like the previous pin here: the known stopping limit is unchanged, not fixed. D2 (Whisper) completed. Status: complete.

Exact-head local checks on 68c6308: 50 unit tests OK (15 skipped), stream_check self-test, patch and diag self-tests, NVFP4 checksums all pass. No hosted CI runs on this repo. Merging now; I'll follow up with a small docs PR so README-dialogue states the v1.1.9 measurement instead of "untested".

@plotarmordev
plotarmordev merged commit 71cedf3 into main Oct 30, 2026
plotarmordev added a commit that referenced this pull request Oct 31, 2026
The full-model paragraph named only request sampling as flag-free. Speaker tags 0 to 15 are too, and CUDA NVFP4 0003 and Metal NVFP4 0006 carry them. I keep the 0003 subject fix from my earlier commit; its old README hunk targeted the patch-series paragraph that #33 replaced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant