Skip to content

Bump HRX: llama.cpp f1a0aca141de, hrx-system 51b1739ae5fd - #13

Merged
bong-water-water-bong merged 1 commit into
mainfrom
bump-hrx/f1a0aca141de-51b1739ae5fd
Sep 23, 2026
Merged

bong-water-water-bong merged 1 commit into
mainfrom
bump-hrx/f1a0aca141de-51b1739ae5fd

Conversation

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator

Moves both submodules to the pair ROCm/ggml-staging-automation now pins.

from to
third_party/llama.cpp (1bit-MONSTER/llama.cpp 1bit/hrx-vulkan) f1a0aca141de f1a0aca141de
third_party/hrx-system (ROCm/hrx-system) fab1624aa925 51b1739ae5fd

CI here builds without HRX. Before merging, on Strix Halo:
cmake -B build -G Ninja -DONEBIT_HRX=ON && cmake --build build --target onebit && tests/hrx_lemonade_e2e.sh build/1bit build/hrx/llama/bin/llama-server

@bong-water-water-bong
bong-water-water-bong merged commit fcdd6d6 into main Sep 23, 2026
1 check passed
@bong-water-water-bong
bong-water-water-bong deleted the bump-hrx/f1a0aca141de-51b1739ae5fd branch September 23, 2026 19:21
bong-water-water-bong pushed a commit that referenced this pull request Sep 23, 2026
- README, PORTING, npu.md, lemonade.md: steps 1-3 landed (3a-3c; the layer
  kernel is still not built from source), the mlx recipe, the XDNA pin; Laya
  (step 4) is next. Drops stale "this PR" rows and "Not yet" items that
  steps 2 and 3 closed.
- hrx.md: re-verified at llama.cpp f1a0aca / hrx-system 51b1739 (#13):
  e2e and ctest pass; fresh llama-bench numbers including BF16; new "Not yet":
  ggml-hrx accepts IQ3_XXS matmuls at scheduling time but cannot run them, so
  sub-4-bit UD files fail on HRX0 with no CPU fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bong-water-water-bong added a commit that referenced this pull request Sep 23, 2026
…#16)

- README, PORTING, npu.md, lemonade.md: steps 1-3 landed (3a-3c; the layer
  kernel is still not built from source), the mlx recipe, the XDNA pin; Laya
  (step 4) is next. Drops stale "this PR" rows and "Not yet" items that
  steps 2 and 3 closed.
- hrx.md: re-verified at llama.cpp f1a0aca / hrx-system 51b1739 (#13):
  e2e and ctest pass; fresh llama-bench numbers including BF16; new "Not yet":
  ggml-hrx accepts IQ3_XXS matmuls at scheduling time but cannot run them, so
  sub-4-bit UD files fail on HRX0 with no CPU fallback.

Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.MONSTER>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
bong-water-water-bong pushed a commit that referenced this pull request Oct 13, 2026
…perturbation level that yields Face A

Two attempts produced only Face B, and the second is informative: attempt 1 got no fingerprint lines at all (defect
#13, the rig's default build does not implement the feature), attempt 2 with the correct build gave 6/6 arms Face B
at req=1-11, and attempt 3 - the same 64-name list plus COPY_PROBE/SENTINEL/LOGITS_FP - reached req=59/66 with 58
OK and ONE Face B fault. That last one matters: the extra environment moved the fault from every arm at req=1-11
back toward the intermittency the objective describes, still Face B.

The remaining difference from the configuration that produced Face A at scale is the selector's SIZE: 315nan read
tail:16 - sixteen tensors per graph - and recorded 16 Face-A faults in 17 arms, while these attempts read 64 named
tensors per graph. So the working hypothesis is a dose-response in instrumentation, with more host-side reads per
graph shifting the fault from Face A toward Face B.

Third attempt: same environment, build and readout, with the selector reduced to about 16 l_out layers sampled
across the model (l_out-0, l_out-3, ..., l_out-45, plus 46 and 47). This keeps the property the sweep depends on -
l_out-<layer> is the last node of its layer's chunk, hence faithfully readable - while matching the perturbation
level that produced Face A. Readout unchanged, with the added check that Face B arms again mean the sweep is
mis-targeted rather than every layer clean. A 16-layer sample brackets the origin layer rather than pinpointing it,
which is the intended resolution here.

Declares this the last selector attempt: if it also yields Face B, the honest conclusion is that the l_out selector
and the Face-A fault are not co-observable at any perturbation level tried, recorded as a finding about the
instrument rather than as a negative result about layers.
bong-water-water-bong pushed a commit that referenced this pull request Oct 13, 2026
Chasing defect #15 turned up a second operability problem. The frozen rig gates every arm on load1 < 4
(315-disc.sh:91), and against the current tenancy that threshold is unreachable: loadavg sits at 4.72 with tctl at
44.5C while our own side-processes are verified at zero (evictonly=0, CPU workers=0) and GTT is at 26GiB, i.e. the
box is as quiet as we can make it and the gate still refuses. The load is other agents' workloads - clickhouse,
redis, dockerd, node.

Two consequences. First, a run can stall indefinitely without failing: a swap script of mine sat in exactly this
loop with every one of our preconditions satisfied, and only a self-imposed iteration cap let it proceed, while the
rig's own gate has no such cap - and an arm that never starts is indistinguishable from outside from an arm that
ran and produced nothing, the same ambiguity this campaign has hit twice before in defect #13's inert EXTRA_ENV and
#14's NANONLY sweep that could not distinguish clean from not-run. Second, the gate is a property of the original
tenancy: load1 < 4 and tctl < 80 were calibrated for a box this campaign had to itself, so with other agents
running servers and CPU work the gate measures THEIR load and silently changes what in-regime means for our arms -
not the GTT regime itself, since arms carry their own gtt_start, but the ambient condition the campaign has treated
as constant, which is the baseline against which section 39's inducing effect and the whole ambient-vs-forced
comparison are drawn.

Not resolved here: the honest statement is that this campaign's ambient baseline and its arm-starts are now
conditional on a box it no longer exclusively owns, and no arm in this record was tagged with the foreign load
present when it ran. The rig's newer 'resident_inventory (foreign, not ours)' line is a step toward recording that
and should be read as required context for any arm from this session onward.
bong-water-water-bong pushed a commit that referenced this pull request Oct 14, 2026
To run three probes back to back I wrote three scripts each shaped as 'while ps | grep <predecessor>; do sleep; done;
clean; launch the next one'. Three disc sessions then appeared at once, including two copies of 315lout4, and
315chain-run.log was empty - stage 1 never started - while stage 2 launched anyway, because the guard is 'wait WHILE
the predecessor is running', which is satisfied immediately when the predecessor does not exist at all. The guard
answers 'is it running now?' rather than 'did it ever run and finish?'. Two sessions then composed the regime
simultaneously, so neither arm's cell means what its label says and every arm in that window is unusable.

Why this is the same defect one layer up: it is defect #14 with the sign flipped. There, absence of output was read
as a clean result; here, absence of a process is read as completion. Both are a predicate on a proxy standing in for
the event of interest, and both silently proceed. The campaign now has four instances of this shape - #13, where an
EXTRA_ENV named a feature the build does not implement and absence of effect was read as absence of an effect; #14;
#16; and the pkill-on-name traps of #11/#12 where killing the wrapper was read as stopping the run.

Records the fix and what I did instead: the correct guard records evidence of the predecessor's completion via a
sentinel line written after its last arm, and additionally requires that it started, but chaining is not worth that
machinery here, so I abandoned it and ran the stages directly one at a time, verifying each launch by its own log
header before starting the next - slower, but it cannot silently skip a stage, which is the failure mode that cost
two composed regimes and about twenty minutes of box time this session is already over budget on. Cost: two
simultaneous compositions whose arms are discarded, the section-40 chain probe never ran and must be re-issued, and
one duplicate 315lout4 session, with no conclusions drawn from any arm in that window.
bong-water-water-bong pushed a commit that referenced this pull request Oct 14, 2026
…NT and the run was aimed at the wrong one

Caught while preparing the run; it would have made the campaign UNINTERPRETABLE rather than wrong, which
is the worse failure because it looks like a null.

THE DEFECT: instrumentation is split across two source trees that do not overlap. llama-315copy carries the
FINGERPRINT (hrx-tensor-fp, hrx-finite-fp; built by 315fp-build, 315fp2-build, 315fbar-build); llama-315probe
carries the PRODUCER PROBE (hrx-producer, GGML_HRX_PRODUCER_PROBE/DEVICE; built by 315probe-build). Checked
in the artefacts, not inferred: 315probe-build's libggml-hrx.so.0.18.0 has 7 hrx-producer strings and 0
hrx-tensor-fp strings, and llama-315copy's graph-executor.cpp has 0 occurrences of
kProbeSentinel|producer_probe_target|hrx-producer.

WHAT IT WOULD HAVE DONE: the campaign set GGML_HRX_TENSOR_FP=<15-name list> on a 315probe-build binary
where that variable is INERT - so the 15-name list, which is the fault-yield enabler, would not have been
active. Both conditions would have degenerated to 'probe, with and without a coherence bit' at an unknown
(probably ambient ~5%) fault rate with 4 eviction arms each - landing in the pre-registration's own
INVALID/under-powered row, while a reader saw two arms with no faults and no fingerprint lines.

THE AMENDMENT IS A TARGET CHANGE, NOT A REDESIGN: A'/B' needs three things from its binary - the
fingerprint (yield enabler + onset readout), the coherence toggle (the intervention) and the writeback
instrument (the warmth check). Two of three live in llama-315copy, so the fix is to patch THAT tree - the
toggle's anchor is unique there because the only other params block is DEVICE_LOCAL - and build 315fp-build.
Verified after patching: fingerprint, GGML_HRX_STAGING_COHERENT, and GGML_HRX_WRITEBACK_FINGERPRINT (2
occurrences in command-program-executor.cpp).

THE PRODUCER PROBE IS DROPPED FROM THIS CAMPAIGN, deliberately: not needed for A'/B', not in this tree, and
leaving GGML_HRX_PRODUCER_PROBE=1 in the environment of a binary without it would have been a second inert
variable - so those two variables are REMOVED rather than left in and ignored. The device-probe question
keeps its own pre-registration and its own tree.

THE GENERALISABLE TRAP, recorded because it will recur: an environment variable whose instrument is not
compiled into the binary is SILENTLY INERT and nothing in the run's output says so. The only defence is to
check the ARTEFACT (strings <lib> | grep <env name>) rather than the source tree you believe you built.
Same class as the record's defect #13 ('the rig's default BIN build does not implement GGML_HRX_TENSOR_FP at
all, so an EXTRA_ENV-driven sweep was silently inert') - the same trap a second time, which is why it is
written down rather than just fixed.
bong-water-water-bong pushed a commit that referenced this pull request Oct 20, 2026
…s 449a809e (#13: v_f16 ABI + f16-V read fixes)

Fixes this PR's first hw-gate run (ops 618/649, Coder-30B HTTP 500).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bong-water-water-bong added a commit that referenced this pull request Oct 20, 2026
…ily (#480)

* serve: the placement report covers every graph, not just the warmup

--placement-report passed GGML_HRX_REPORT=1, and the backend's 1 is the
first graph only, so serve printed a clean report for a model that leaves
nodes on the CPU in later graphs: the 20 Oct census found LFM2 --parallel 4
(20 nodes, 5 splits) and ZAYA1-8B (1-3 nodes) reading "all nodes on HRX".

Ask for every graph (2), keep the worst one instead of the last, and print
serve's line again whenever a graph is worse than every graph before it,
with the graph count. --strict-device reads the same worst graph. Without
--placement-report serve keeps 1, so no log volume is added by default.

tests/hrx_placement_test.cpp covers a clean warmup followed by a par4 graph
and a later clean graph.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* serve: --strict-device reads the report it needs

--strict-device only passed GGML_HRX_STRICT=1 to the backend. It did not pass GGML_HRX_REPORT=2 and it
did not add the -lv 4 that lets llama-server's log level carry the placement report through, so the graph
that would have been refused was never reported and serve fell through to "the backend printed no
placement line" while starting normally. Both flags are now treated the same way: GGML_HRX_REPORT=2 and
-lv 4 whenever either is set, so the refusal reads the same worst graph that --placement-report prints.

Found on device: `1bit serve ... --strict-device --parallel 4` (LFM2-1.2B) answered requests instead of
refusing, with that "no placement line" message in its log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* serve: --parallel on qwen35 / qwen35moe / qwen3next

These architectures were refused with "--parallel on --device hrx does not run <arch> yet (no
multi-sequence gated delta-net on HRX)". That was true when the HRX gated-delta-net matchers held
kMaximumSequences 3; they hold 8 now (llama.cpp 1bit/hrx-gdn-multi-sequence), and a four-sequence run keeps
every node on the device.

Measured on Qwen3.8-27B UD-Q4_K_XL, `--parallel 4`, four concurrent chats: 4 of 4 answered, placement "all
3655 nodes on HRX, 1 graph splits", zero error lines. The forced `-np 1` for these architectures when
--parallel is not given stays: llama-server's own default opens several slots, and that is a different
question from the explicit flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Pin llama.cpp cefbfc07 (fork #117, G9) and gpu-kernels 421d7a4e (G7 #11, G8 #12); --parallel on qwen35 family

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* registry: regenerated at llama.cpp cefbfc07

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Pin llama.cpp dcf8c1ec (fork #118: narrower GDN claim) and gpu-kernels 449a809e (#13: v_f16 ABI + f16-V read fixes)

Fixes this PR's first hw-gate run (ops 618/649, Coder-30B HTTP 500).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* registry: regenerated at llama.cpp dcf8c1ec

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: bcloud <bcloud@localhost>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: bcloud <bcloud@1bit.local>
Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg>
bong-water-water-bong pushed a commit that referenced this pull request Oct 22, 2026
Moves the NPU-kernels pin to 1bit-MONSTER/npu-kernels npu/ship-sealed-kernels HEAD
(neutral sealed metadata). The pin moves to the merge commit when PR #13 lands.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
bong-water-water-bong pushed a commit that referenced this pull request Oct 22, 2026
…e npu gate passes)

The release side of shipping the NPU kernels closed, compiled and encrypted only:

- scripts/weekly.sh build: with WEEKLY_NPU_KERNELS=1, fetch config/npu-kernels.config and
  call the private checkout's one entry point (addons/release-kernels.sh <out> <key dir>),
  which installs the kernel key for the runtime build and writes the sealed sets to
  $BUILD/npu/kernels; build with ONEBIT_NPU_PRIVATE and ONEBIT_NPU_RELEASE=ON, so the
  packed 1bit loads sealed kernels only. The policy lives in the binary: the package has no
  launcher wrapper (Lemonade execs 1bit directly), so an environment variable could be unset.
  Default off until the hardware gate's npu phase passes on Strix Halo.
- scripts/package-linux.sh: packs $BUILD/npu/kernels beside 1bit (npu/kernels), where the
  route looks for it.
- package_checks (npu): every file under npu/kernels but layout.json is sealed, never a
  plaintext ELF; every ELF in the tarball is for the host (x86-64); the packed 1bit has no
  symbol table and its strings name no private source file and no build-machine home.
  Private-source file names now include the NPU-kernels checkout.
- config/npu-kernels.config: pin the private branch head that has the entry point; neutral
  require= list. The pin moves to the merge commit when npu-kernels #13 lands.
- docs/releases.md: the switch, the checks, the key directory (ONEBIT_NPU_KEY_DIR).

Checked on ryzen: bash -n; package_checks on a synthetic good package passes all four new
checks, and on a bad one fails each (plaintext kernel ELF, an EM 264 ELF, an unstripped 1bit
with 25 symbols, a private source name, a /home/ path). Not run on Strix Halo yet
(maintenance freeze): no weekly build with the switch on has been made.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
bong-water-water-bong pushed a commit that referenced this pull request Oct 22, 2026
… gate needs no llama.cpp

- Pin 1bit-MONSTER/npu-kernels at dfe511236d03, the npu-dx merge of #13 (sealed kernel
  loading, release entry point, sealed-only release switch). fetch-private.sh fetches it and
  finds every require= file.
- scripts/hw-gate.sh: the llama.cpp binary check applies to the HRX phases only, so
  --phases npu runs on a box with no HRX build. Dry run on ryzen (no NPU): npu SKIP, exit 0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
bong-water-water-bong added a commit that referenced this pull request Oct 22, 2026
* npu: a hardware-gate NPU phase, closed+encrypted kernel delivery, docs

Make the NPU engine shippable with the runtime and kernels closed, as compiled
binaries only:

- scripts/hw-gate.sh: a neutral `npu` phase (not in the default phases; add with
  --phases npu) that auto-skips with no NPU (/dev/accel/accel0) or no checker, and
  otherwise runs a private checker ($HW_GATE_NPU_CHECK) inside the gate's GPU claim
  and under ~/npu.lock, reads its neutral result lines (oracle vs an fp64 reference,
  greedy64, prefill, reproducibility) and applies a tok/s floor (HW_GATE_NPU_FLOOR).
  The checker and kernels are private; the gate carries no method.
- config/npu-kernels.config: the private NPU-kernels pin the release fetches
  (ONEBIT_NPU_PRIVATE), same shape as config/gpu-kernels.config.
- docs/npu.md, docs/releases.md: the NPU kernels ship as compiled, encrypted
  artifacts that `1bit` verifies and decrypts in memory at load (fails clean on a
  wrong key, no network callback); no source or method is public.

Proven on Strix Halo (private npu-kernels npu/ship-sealed-kernels): the sealed dx
kernel set decodes BYTE-IDENTICAL logits to the plain set (Qwen3-0.6B, 24/24 vs
fp64, md5 9a405cf6...), 64/64 greedy at ~90 tok/s, a foreign-key set refused cleanly,
a plain ELF refused under REQUIRE_SEALED, 0 amdxdna/IOMMU faults. The on-device gate
`npu` phase run and wiring the kernels into the weekly package are the remaining
steps (strixhalo was under a maintenance freeze).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* config/npu-kernels.config: pin the neutral-metadata commit

Moves the NPU-kernels pin to 1bit-MONSTER/npu-kernels npu/ship-sealed-kernels HEAD
(neutral sealed metadata). The pin moves to the merge commit when PR #13 lands.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* weekly: pack the sealed NPU kernels (WEEKLY_NPU_KERNELS, off until the npu gate passes)

The release side of shipping the NPU kernels closed, compiled and encrypted only:

- scripts/weekly.sh build: with WEEKLY_NPU_KERNELS=1, fetch config/npu-kernels.config and
  call the private checkout's one entry point (addons/release-kernels.sh <out> <key dir>),
  which installs the kernel key for the runtime build and writes the sealed sets to
  $BUILD/npu/kernels; build with ONEBIT_NPU_PRIVATE and ONEBIT_NPU_RELEASE=ON, so the
  packed 1bit loads sealed kernels only. The policy lives in the binary: the package has no
  launcher wrapper (Lemonade execs 1bit directly), so an environment variable could be unset.
  Default off until the hardware gate's npu phase passes on Strix Halo.
- scripts/package-linux.sh: packs $BUILD/npu/kernels beside 1bit (npu/kernels), where the
  route looks for it.
- package_checks (npu): every file under npu/kernels but layout.json is sealed, never a
  plaintext ELF; every ELF in the tarball is for the host (x86-64); the packed 1bit has no
  symbol table and its strings name no private source file and no build-machine home.
  Private-source file names now include the NPU-kernels checkout.
- config/npu-kernels.config: pin the private branch head that has the entry point; neutral
  require= list. The pin moves to the merge commit when npu-kernels #13 lands.
- docs/releases.md: the switch, the checks, the key directory (ONEBIT_NPU_KEY_DIR).

Checked on ryzen: bash -n; package_checks on a synthetic good package passes all four new
checks, and on a bad one fails each (plaintext kernel ELF, an EM 264 ELF, an unstripped 1bit
with 25 symbols, a private source name, a /home/ path). Not run on Strix Halo yet
(maintenance freeze): no weekly build with the switch on has been made.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* config/npu-kernels.config: pin the npu-kernels merge commit; npu-only gate needs no llama.cpp

- Pin 1bit-MONSTER/npu-kernels at dfe511236d03, the npu-dx merge of #13 (sealed kernel
  loading, release entry point, sealed-only release switch). fetch-private.sh fetches it and
  finds every require= file.
- scripts/hw-gate.sh: the llama.cpp binary check applies to the HRX phases only, so
  --phases npu runs on a box with no HRX build. Dry run on ryzen (no NPU): npu SKIP, exit 0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* docs/npu.md: how to run the NPU engine; package README line when it carries the kernels

Neutral: "the 1bit NPU engine runs the model on the XDNA 2 NPU", the serve command for a Qwen3
NPU model directory (0.6B, 1.7B, 4B), Lemonade's onebit npu backend, and that the kernels ship
inside the package. README.txt gains the NPU serve line only when the package has npu/kernels.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* hw-gate npu: no tok/s reported is a failure, not a skipped floor

The first on-device run of the npu phase passed with an empty tok_s (a checker bug,
npu-kernels #14): the floor check only ran when a number was present. Require a number;
unit-checked on three checker outputs (90.50 PASS, empty FAIL, 41.2 below a 60 floor FAIL).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* npu-kernels pin dfe51123 -> 6eee7607: npu-check reports tok/s

npu-kernels #14 fixes the awk printf redirection that left tok_s empty, so the gate npu phase speed floor now has a number to check (11.05 ms/step -> 90.50 tok/s on both gawk and mawk).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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