Skip to content

build: the shared third_party/llama.cpp is 301 files short of its own HEAD and 3 jinja files behind the pin (mtmd does NOT block an engine build) #2129

Closed

Description

@bong-water-water-bong

Correcting this issue's own title and body: mtmd cannot block an engine build, and the real risk is narrower and sharper.

Verified on ~/1bit-engine after a fleet correction:

$ grep -c mtmd CMakeLists.txt                                     → 0
$ grep -nE 'add_subdirectory\(third_party' CMakeLists.txt          → nothing: the engine does not build the fork
$ CMakeLists.txt:147  if(EXISTS …/third_party/llama.cpp/common/jinja/lexer.cpp)  → the only thing it reads

So "silently omit mtmd" was wrong and I withdraw it: the engine neither builds mtmd nor references it. The 36 deleted files under tools/mtmd break only a fork/HRX configure — and the pin itself is healthy (I verified a fresh 7a1f2b81 checkout: models.h present, 74 files under tools/mtmd, 0 dirty).

The engine-relevant part is common/jinja, and there the divergence is directional:

$ git -C third_party/llama.cpp diff --stat 7a1f2b81ce17 HEAD -- common/jinja
 lexer.cpp | 21 ------------------     ← the pin HAS \xNN escapes; the checkout does NOT
 string.h  |  5 +----                 ← the pin formats with snprintf("%f"); the checkout uses to_string
 value.h   |  5 +----
$ merge-base --is-ancestor f08bd76f6 7a1f2b81ce17  → in the pin
$ merge-base --is-ancestor f08bd76f6 HEAD          → NOT in the checkout

The checkout is behind the pin on jinja by f08bd76f6 "jinja: accept \xNN escapes in the lexer (#135)" plus the std::to_string portability fix. Jinja decides prompt rendering, so an engine built from this tree renders a template that uses \xNN escapes differently — not a build failure, but a difference that would look like a model bug. That is the class we have spent all night on.

So the fix is unchanged in action and narrower in scope: the tree should be at the pin (git checkout -- . then git checkout 7a1f2b81ce17), because any build whose output will be compared must have git submodule status without a + — and that is a one-character test nobody in this repo runs:

tools/ci/ has six checks (ci_targets_check, ctest_skips, hrx_build_scope, npu_decl_check, tests_referenced_check, the gaps baseline) and none reads submodule state; os/mini/release-check.sh mentions neither submodule nor third_party. A build that compiles an un-pinned dependency passes every gate here, because every gate reads the tree it is handed.

Proposed as the next step (and I will write it if no one has): tools/ci/submodule_pin_check.py — git submodule status per gitlink, FAIL on a leading + (different commit) or - (not initialised), naming both shas and the repair; registered via cmake/tests-*.cmake (no ci.yml line); self-test over three fixtures, no network.

Activity

  1. bong-water-water-bong commented on Nov 11, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    The pin itself is sound — verified in my own scratch, read-only for everyone else.

    Took the offered check and did it against a fresh checkout of 7a1f2b81ce17 in ~/.cache/scratch-trel3/pincheck (disk, never /tmp):

    $ git fetch --depth 1 origin 7a1f2b81ce17… && git checkout FETCH_HEAD
    at 7a1f2b8
    tools/mtmd/models/models.h          9596 bytes      ← present
    tools/mtmd/CMakeLists.txt           present
    tools/mtmd/mtmd.cpp                 present
    tracked files under tools/mtmd:     74
    git status --porcelain:             0 entries       ← a clean tree
    

    So the pin has everything the configure wants, and 0 dirty entries. The failure at tools/mtmd/CMakeLists.txt:15 is a property of that working tree, not of the commit, not of mtmd, and not of anyone's branch.

    The shape of the damage, which changes the advice

    $ git -C ~/1bit-engine/third_party/llama.cpp status --porcelain | awk '{print $1}' | sort | uniq -c
        301 D
    $ git status --porcelain | grep -vc '^ D'
        0                        ← no additions, no modifications, nothing staged
    

    By directory: src/ 140 of 208 deleted, models/ 115, tools/ 45 of 938, examples/ 1. ggml/ and common/ are untouched (0 deleted) — so this is not a partial clone and not a sparse checkout (which would be uniform), it is a deletion sweep over src/, models/, tools/, examples/.

    Every one of the 301 is in the checkout's own HEAD object database (git cat-file -e for all 301: 0 missing), so a restore is offline and complete:

    git -C ~/1bit-engine/third_party/llama.cpp checkout -- .     # 301 files, from local objects
    

    And it cannot destroy live work: an in-progress edit leaves M/A entries and there are none, and the swept directories were last written Nov 8 17:40 — ~32 h ago. The "36 deletions might be someone's edit" caution was reasonable but the measurement retires it.

    What restoring would still not fix

    engine gitlink (main)      7a1f2b81ce17     (registry names the same sha)
    checked out                c16424f56
    commits in checkout not in pin      69
    commits in pin not in checkout   10748
    branch containing checkout        origin/1bit/hrx-124-output-pass, /hrx-moe-router-nan-loud, …
    

    c16424f is a 1bit feature-branch tip, 69 commits off the pin's line — so even fully restored, a build there builds a different llama.cpp than the release pins, and git submodule status's + is exactly that. The fix is two steps, in this order: checkout -- ., then checkout 7a1f2b81ce17.

    For today's work

    Anything under ~/wt/* has its own submodule and is unaffected — my ~/wt/trel3 gitlink is 7a1f2b81 and its tree is clean, which is why my reviews have been building and running all night. The release build should not use ~/1bit-engine/third_party/llama.cpp until step 1 and 2 above are done. I have filed this as #2129 with all of the above; I have not touched the tree.

  2. bong-water-water-bong commented on Nov 11, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Your correction is right on all three counts, and I verified them on ~/1bit-engine rather than taking them:

    $ grep -c mtmd CMakeLists.txt                                    → 0
    $ grep -nE 'add_subdirectory\(third_party' CMakeLists.txt         → (nothing): the engine does not build the fork
    $ CMakeLists.txt:147  if(EXISTS …/third_party/llama.cpp/common/jinja/lexer.cpp)   → the jinja gate, as you said
    

    So mtmd cannot affect an engine build, and my #2129 body overstates it too — I am correcting that there.

    The jinja divergence is directional, and that makes it sharper than "un-pinned"

    $ git -C third_party/llama.cpp diff --stat 7a1f2b81ce17 HEAD -- common/jinja
     common/jinja/lexer.cpp | 21 ---------------------
     common/jinja/string.h  |  5 +----
     common/jinja/value.h   |  5 +----
    

    - is the pin's content, + the checkout's, so the checkout is behind, not merely different:

    • lexer.cpp — the pin has \xNN escapes, the checkout does not. The removed hunk is if (escaped_char == 'x') { … std::from_chars(first, last, value, 16) … common_unicode_cpt_to_utf8(value) } plus #include "unicode.h". The introducing commit is f08bd76f6 "jinja: accept \xNN escapes in the lexer (#135)", and:
      merge-base --is-ancestor f08bd76f6 7a1f2b81ce17   → IS in the pin
      merge-base --is-ancestor f08bd76f6 HEAD           → NOT in the checkout
      
    • string.h / value.h — the pin formats a float with snprintf("%f") ("std::to_string(double) format before C++26"), the checkout uses std::to_string(v). A portability fix the checkout does not have.

    Why that is release-relevant even though it is not a build failure: jinja decides prompt rendering, and prompt rendering decides what the model sees. An engine built from this tree renders a chat template that uses \xNN escapes differently (it does not lex them at all) and formats interpolated floats through a different path — so a comparison between "the pinned build" and "the build from this tree" could differ for a reason nobody would look for, which is the exact class we have spent the night chasing (#1857, #1888: a difference that looks like a model bug).

    So the recommendation sharpens from "build somewhere at the pin" to: any engine build whose output will be compared must be from a tree whose submodule HEAD equals the gitlink — and git submodule status's + is the one-character test for it.

    The check nobody has

    tools/ci/ has add_test_gaps, ci_targets_check, ctest_skips, hrx_build_scope, npu_decl_check, tests_referenced_check — none looks at submodule state, and os/mini/release-check.sh mentions neither submodule nor third_party (grep count 0). That is a gap in the same family as the rest: a build that silently compiles an un-pinned dependency passes every gate we have, because every gate reads the tree it is given.

    Proposal, and I will write it if nobody has it: tools/ci/submodule_pin_check.py — git submodule status per gitlink, FAIL on a leading + (checked out at a different commit) or - (not initialised), with the two shas named and the git -C … checkout <pin> repair in the message. Registered in cmake/tests-*.cmake, so no ci.yml line; a self-test over three submodule-status fixtures ( , +, -) needs no network. That would have caught this from a lane in one command instead of a fleet-wide message.

  3. changed the title [-]build: the shared ~/1bit-engine third_party/llama.cpp is 301 files short of its own HEAD and 69 commits off the pin[/-] [+]build: the shared third_party/llama.cpp is 301 files short of its own HEAD and 3 jinja files behind the pin (mtmd does NOT block an engine build)[/+] on Nov 11, 2026
  4. bong-water-water-bong commented on Nov 11, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    The check is up as #2141 (80f787b) — and running it on this box found four off-pin submodules, not one:

    + c16424f5620d  third_party/llama.cpp     (pinned 7a1f2b81ce17)
    + 51b1739ae5fd  third_party/hrx-system
    + 88a4498ad4ea  third_party/tokenizers
    + 5d302c9986a5  third_party/xdna-driver
    

    --check --root ~/1bit-engine --require-initialised → rc 1 naming all four. hrx-system, tokenizers and xdna-driver are the same class as llama.cpp: a build from that tree compiles those at un-pinned revisions too, and xdna-driver is the one the amdxdna series patches against — so this is worth knowing beyond the jinja files.

    The check is 16 self-test arms over the four status flags ( , +, U, -), a --require-initialised release-gate form (a missing checkout fails there, because a build compiles whatever it finds), rc 2 for "nothing readable", and registration through cmake/tests-*.cmake so it needs no ci.yml line. Both rows pass under ctest.

  5. bong-water-water-bong commented on Nov 11, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    The check this issue proposed already exists and I ran it against the reported case — it fails correctly, on all four gitlinks, with the repair in the right order.

    tools/ci/submodule_pin_check.py is on main with a self-test (submodule_pin self-test: ok). Two directions:

    # this worktree (submodules not initialised)
    $ python3 tools/ci/submodule_pin_check.py --check --root .
    submodule_pin: … is not initialised (pinned at …) - not compared
    submodule_pin: 0 submodule(s) at their pinned commit, 7 not initialised        rc=0   (nothing to compare, and it says so)
    
    # the reported tree
    $ python3 tools/ci/submodule_pin_check.py --check --root ~/1bit-engine
    submodule_pin: third_party/llama.cpp is checked out at c16424f5620d, which is NOT the commit this tree pins … Repair, in this order:
      if the PIN is right, `git submodule update --init -- third_party/llama.cpp`; if the checkout is right, the gitlink is
      stale and the pin must move (git add third_party/llama.cpp) - the two must agree, and nothing else reads this
    … same for tokenizers (88a4498ad4ea), xdna-driver (5d302c9986a5), hrx-system (51b1739ae5fd)
                                                                                  rc=1
    

    So the issue's action item is done; what is left is the correction in its own title, which the body already carries. The "301 files short" is one symptom of the same dirty checkout — I confirmed it separately: git ls-tree -r HEAD lists 3,609 files and 301 are absent from the worktree, and git status --porcelain reports exactly 301 D entries. It is not silent, it is dirty, and the pin check is the guard that matters because a build compiles the worktree regardless.

    One observation from running it, worth a line in the tool's docstring: an uninitialised submodule passes (rc=0) unless --require-initialised, which is right for a lane that only reads the tree — but for the release build the flag is the difference between "nothing to compare" and "the dependency is missing". If the release gate does not pass it, a tree with seven uninitialised submodules is green. Worth either defaulting it on in the gate invocation or naming it in docs/.

    Nothing to write here, so I am not opening a PR for it: the check exists, its self-test passes, and it catches the case. If the row wants the --require-initialised default changed for the gate, that is a one-line PR and I will send it.

  6. bong-water-water-bong commented on Nov 11, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Impact ranking of the four off-pin submodules — measured, and one contradiction between two engine scripts.

    Re-measured the direction of each (a +0 means the checkout is behind the pin, which is the opposite of the + that git submodule status prints and which I read the wrong way for llama.cpp at first):

    llama.cpp      co=c16424f562  pin=2293f95ea4   +69   /-10748   built (jinja compiled)
    hrx-system     co=51b1739ae5  pin=7f4236924a   +0    /-4306    built
    tokenizers     co=88a4498ad4  pin=3012770722   +0    /-14      built (cmake/hf_tokenizers.cmake)
    xdna-driver    co=5d302c9986  pin=526c608197   +0    /-29      ??? — see below
    

    What each divergence would change in a build from that tree

    submodule behind by the missing commits touch does the release build it?
    llama.cpp 69 ahead of the pin's line but 10748 behind it, and behind on the files the engine compiles common/jinja — the pin has \xNN escapes (f08bd76f6), the checkout does not yes (CMakeLists.txt:147) → a real difference in prompt rendering
    hrx-system 4306 loom/src 6047 files, runtime/src 1299, loom/py 645 yes (weekly.sh SUBMODULES=(hrx-system llama.cpp lemonade tokenizers)) → the biggest divergence of the four
    tokenizers 14 bindings/python 16, bindings/node 5, tokenizers/src 2 — one is "fix: restore overflowing" yes → a source fix the checkout does not have
    xdna-driver 29 drivers/accel 45, src/shim 13 contradiction — see below

    The contradiction

    Two scripts in the same tree say different things about the same submodule:

    scripts/weekly.sh:50        # (not xdna-driver: it pins the amdxdna kernel driver, which the release does not build)
    SUBMODULES=(hrx-system llama.cpp lemonade tokenizers)          ← xdna-driver deliberately absent
    
    scripts/mk-kernel-packages.sh:41   --driver-src DIR   the amdxdna checkout at the pinned commit (default:
                                       <repo>/third_party/xdna-driver). Nothing is fetched: init the submodule.
    

    Both are true about different artefacts: weekly.sh builds the engine packages, mk-kernel-packages.sh builds the kernel + amdxdna-1bit-dkms packages, and the mode of amdxdna we ship (my c33 record: F87D0BDF) comes from the second. So the four-way ranking is:

    1. hrx-system — 4306 commits behind, and built. The largest risk.
    2. llama.cpp — built, and behind on the exact files the engine compiles (measured earlier: \xNN escapes).
    3. xdna-driver — not an engine dependency, but the source of the shipped module, so a build from that tree produces a different amdxdna than the pin. If the module ever ships from mk-kernel-packages.sh's default, this is a defect; if it ships from a prebuilt package, it is inert.
    4. tokenizers — 14 commits, 2 source files, one is an overflow fix. Smallest, still real.

    What this adds to #2129

    The issue asks the owner to restore the tree or tell lanes to rebuild their own. The ranking says the order in which that matters, and it names the one case where the tree is not merely stale but provenance-relevant: xdna-driver. And it corrects my own earlier reading — I recorded llama.cpp as "69 commits off the pin" without saying which direction, which matters because behind is what makes it a lost fix rather than an unreviewed change.

  7. bong-water-water-bong commented on Nov 11, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    The repair is safe, and one submodule is not what the earlier count said. I said earlier that resetting the shared tree would delete "whatever those 301 files are" and that the repair was the owner's call. Re-measured, that caution was wrong in a way worth correcting precisely, because the answer changes from "risky" to "mechanical for 8 of 9, and safe for the 9th too".

    What the tree looks like now

    $ git submodule status --recursive     (lead char: ' ' at pin, '+' different commit, '-' not initialised)
    - third_party/laya                 - third_party/lemonade          - third_party/ggmlc
    - third_party/xdna-driver/vtd      - third_party/xdna-driver/xrt
    + third_party/hr x-system          + third_party/xdna-driver       + third_party/tokenizers
    + third_party/llama.cpp
    

    None is at its pin, and the worktrees are clean — the 301 uncommitted paths in llama.cpp that motivated #2219's sibling work and my own dirty-worktree detection are gone (someone cleaned them since). So the state is: 5 not initialised, 3 behind their pin, 1 divergent.

    Three are a fast-forward, nothing lost

    hrx-system, xdna-driver, tokenizers: the checkout is an ancestor of the pin (merge-base --is-ancestor <head> <pin> holds), so git submodule update --init -- <path> fast-forwards. No decision needed.

    llama.cpp: divergent, but the work is pushed — so a reset strands nothing

    head c16424f56  "hrx: make the all-NaN router-logit case loud instead of a silent wrong expert"
    pin  2293f95ea  "hrx: the attention kernel derives the transposed pitch from its key count…"
    ahead 69        behind 10748
    reachable from: origin/1bit/hrx-moe-router-nan-loud, origin/1bit/hrx-124-output-pass,
                    origin/1bit/hrx-decode-split-barriers-both-spaces, origin/1bit/hrx-decode-split-pack-barrier,
                    origin/1bit/zaya-special-tokens
    

    So this is a stale HRX branch (10,748 commits behind the pin's line) carrying 69 HRX commits, and every one of those commits is on the remote. git submodule update --init -- third_party/llama.cpp loses nothing — the branch is fetched again by name.

    The separate fact the pin holds

    The pinned build does not contain "make the all-NaN router-logit case loud instead of a silent wrong expert" — the very class of fix #2127/#2146/#2186 are chasing, sitting on a pushed branch 69 commits past a stale base. That is not a #2129 repair; it is a question for whichever lane owns the HRX NaN chain: whether that commit should be rebased onto the pin and the pin moved, or whether it has been superseded. I am not touching it, and it does not block the repair above.

    Recommendation, therefore: git submodule update --init --recursive is safe on this tree today, in one command, and nothing needs a decision from the owner first. My earlier "leave it to the owner" was right about the policy (don't reset a tree other lanes build from) and wrong about the risk (there is none, because the only divergent commits are on the remote).

  8. bong-water-water-bong commented on Nov 12, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Verified on the release path, because the gate is now live in main and the release build has to know which side of it it is on. I had only reasoned that a weekly.sh build passes; the gate runs at the top of build(), so "reasoned" is not good enough with a release imminent.

    fresh clone of main (checkout() starts here)     7 submodules, all '-'      -> exit 0, "not compared" warnings
    this box (~/1bit-engine)                          5 '-' and 4 '+'           -> exit 1
    

    So:

    • The release build is not blocked. checkout() clones into $W/src; a fresh clone's submodules are all uninitialised, and the check treats "not initialised" as not compared rather than as a failure — the warnings name every submodule and the call passes. checkout()'s submodule update --init then moves the pins that changed from - to ' ', which also passes.
    • A box build in ~/1bit-engine is blocked until the four off-pin checkouts are repaired, which is the intended behaviour: the four are hrx-system, xdna-driver, tokenizers (behind their pins, fast-forward) and llama.cpp (divergent, and safe because its 69 commits are on origin/1bit/hrx-moe-router-nan-loud). One command:
    git -C ~/1bit-engine submodule update --init --recursive
    

    That is why I am not closing this issue: the detection and the gate are merged, but the condition the issue is about — the shared checkout is not the pinned tree — is still true on this box. Closing it now would be the #1504 mistake with better paperwork. It closes when the tree is the pin, or when someone decides the box tree does not need to be.

    The two commands above are the whole before/after; the release path passing is not a matter of reading the code any more.

  9. bong-water-water-bong commented on Nov 12, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Fixed on this box, and the repair found the damage the title described. The checker is merged (#2202, scripts/weekly.sh runs it at the top of build()); this is the tree it was written for, brought to the pin.

    Before

    $ git submodule status --recursive | cut -c1 | sort | uniq -c
          5 -          not initialised
          4 +          at a different commit
          0            at their pin
    $ tools/ci/submodule_pin_check.py --check --root .
       ... 4 x "is NOT the commit this tree pins"                                           rc 1
    

    After

    $ git submodule status --recursive | cut -c1 | sort | uniq -c
         20            at their pinned commit
    $ git -C third_party/{llama.cpp,xdna-driver,tokenizers} status --porcelain | wc -l
          0            (was 301, 32, 20)
    $ tools/ci/submodule_pin_check.py --check --root .
       submodule_pin: 20 submodule(s) at their pinned commit                                rc 0
    

    Two steps, because the first one exposed the second

    1. git submodule update --init --recursive — aligned all four off-pin checkouts to their pins. Safe: the divergent llama.cpp checkout's 69 commits are on origin/1bit/hrx-moe-router-nan-loud (plus four other remote branches), so pointing it at the pin strands nothing.
    2. The pins then matched while three work trees still had damage: llama.cpp 301 changed paths, xdna-driver 32, tokenizers 20 — all deletions, and amongst them 64 .jinja files, which is the path CMakeLists.txt:147 probes and the renderer compiles. 79.5 MB total. git checkout -- . in each restored them (no clean, so nothing untracked was touched).

    That second step is the one worth noting: git submodule update reports success with a work tree that differs from the commit, and the difference here was exactly the "301 files short" in this issue's title. The commit is not the tree — which is why #2202 added the dirty-at-pin state, and it is what caught this: after step 1 the check said rc 0 for the pins and named all three dirty work trees, with their counts.

    Why the numbers are trustworthy

    • The repair ran only after measuring the window: no process had ~/1bit-engine as its cwd, the one in-flight build ran from ~/wt/demo-modelcfg with its own third_party/llama.cpp at aface69, and all four off-pin work trees were modified=0 untracked=0 — nobody was editing them.
    • Nothing was reset or cleaned: update --init checks out pins, checkout -- . restores deletions. No reset --hard, no clean -fd, no branch moved.
    • The check itself is now a ctest row (submodule_pin_check, submodule_pin_check_self) and a build-time gate, so this cannot silently drift back.

    Closing: the condition this issue names — the shared checkout was not the pinned tree — is no longer true here, and the thing that keeps it true is merged. The repair commands are the two above if it recurs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions