>>FIRST MISSION//LOGS//llama-cpp//llama-cpp-1-0-wrote-down-what-breaks.MD
[ + ] TARGET_LOCKED200 OK
NOV 15, 2026timer 3 MIN READSYS_TAG: llama-cpp STATUS: VERIFIED_WORKING

llama.cpp Hit 1.0 and Wrote Down What Breaks

llama.cpp and ggml both shipped v1.0.0 on November 13 with a published semver table, and the first major version was spent deleting 35 deprecated functions. The promise covers libllama and libggml, not llama-server, and that distinction is the whole story.

ENGINE: KERNEL // STABLE
BASE_ARCH: x86_64
HOST: VASTORIGINS.COM
GPG: OKSIG_ID: 0x4EB27DB0

I check the llama.cpp releases page the way I check a weather forecast before a long run, mostly out of habit and occasionally because the answer changes my plans. This morning the top of the list was not another b-prefixed nightly. It was v1.0.0.

llama.cpp v1.0.0 and ggml v1.0.0 were both tagged on November 13, 2026, which ends a versioning argument that had been sitting open in a GitHub discussion since August. The interesting part is not the number. It is that the maintainers sat down first, defined what each digit means, and then spent the major version on deletion.

📌 What 1.0 Actually Commits To

The release post on the Hugging Face blog states the rules plainly. A major bump is a breaking change to the public C API in ./include. A minor bump is a backward-compatible feature, backend update, model support, or API addition. A patch is a bug fix with no API change. API and ABI incompatibilities both count, which matters here because ggml backends compile as dynamic libraries and can be loaded at runtime.

Two libraries, two headers: libllama from llama.cpp/include/, libggml from ggml/include/.

That reads like boilerplate until you see what it replaces. The project has spent three and a half years, by the post’s own count, shipping bNNNNN tags off master with no compatibility signal in the number at all. Downstream projects could not pin against anything meaningful, and every integrator was effectively testing their build against whatever master happened to be that week. The August discussion exists because that stopped being tolerable once the project had real downstreams.

🪓 The Break Was Paid Up Front

1.0.0 is itself the breaking change. PR #30565, merged November 12, deletes llama_set_warmup, all 35 functions marked DEPRECATED in llama.h, the deprecated llama_context_params::defrag_thold field, and the -dt, --defrag-thold command line option. On the ggml side, PR #29801 prunes the deprecated API and removes the legacy DIAG_MASK_INF and DIAG_MASK_ZERO ops.

That is the honest way to spend a major version. If the first digit is going to mean “breaking changes live here”, the first one should be the messy release where you finally delete the leftovers, so that 1.1 and 1.7 can stay boring.

The other half of the same pull request is the part that will get buried under backend bullet points. It promotes the NextN and speculative decoding API out of llama-ext.h and into llama.h: 18 functions covering NextN embeddings, layer inputs, embedding and state rows, and draft model queries, with llama_set_embd_state_src renamed to llama_set_ctx_state_src.

Why that matters is spelled out in the discussion. Gerganov’s answer to whether llama-ext.h is covered by the versioning rules was that the header exists specifically so the team can experiment without touching the official API or its version numbers. It is not public, and it can change without a bump. At 1.0.0, eighteen functions crossed from the unversioned side to the promised side. That is a real expansion of what you can safely build on, and it happened in the same tag that deleted thirty-five others.

🔗 Why the Tag Is Enforceable

A compatibility policy in a blog post is a wish. What makes this one credible is a rule buried in the packaging document from the August thread: release tags are only cut when llama.cpp’s internal copy of ggml is identical to the released ggml. That guarantees a downstream building from a release tag and linking against a system-wide ggml gets a compatible pair. Nightlies keep the b[NUM] numbering and build with -DLLAMA_BUILD_IS_DEV=ON. Official releases use vX.Y.Z and -DLLAMA_BUILD_IS_DEV=OFF.

The wire got a version gate too. ggml 1.0.0 bumps the RPC protocol to v9, which rejects incompatible peers and now fails gracefully on unreachable endpoints or failed handshakes. If you split a model across machines with rpc-server, mixing versions across nodes stops being a silent corruption risk and becomes a refusal to start. That is inconvenient during a rolling upgrade and correct the other 364 days.

The clearest statement of the actual stake came from the Debian packager in that thread. Semantic versioning, he wrote, makes it possible to maintain a SOVER, and a SOVER is what lets Debian ship llama.cpp as a library in public search paths instead of bundling it. A distribution can only put a .so in /usr/lib if upstream promises what breaks the ABI. Before this release, that promise did not exist in a form anyone could read from a version string.

🕳️ Where the Promise Stops

The published table covers ./include and nothing else. Everything else in the repository, including the HTTP server that a large share of real applications actually talk to, sits outside it.

The August thread has the working detail. As one collaborator proposed it, only breaking changes to inference endpoints (completions, embeddings) count as a major bump. Router API, tools, and CORS proxy breaking changes were penciled in as patches, and changes to llama-cli, llama-ui, and llama-quantize as minor. Adding a new enum value counts as breaking even when no function signature moves.

Those are planning comments, not a published policy, so read them as intent rather than contract. But they name the boundary precisely, and the boundary is exactly where a lot of code lives. An app that only speaks /v1/chat/completions is covered. An app that depends on the router API, the tools runtime, or the CORS proxy is not.

Distribution has the same shape of gap. The same document notes that two channels, the llama.app installer and the Winget manifest, publish nightly builds rather than official releases, with a TODO to switch. Homebrew and Debian link against the system-wide ggml package, while the installer and Winget pack the internal copy. So “pin to 1.0.0” is a per-channel exercise, and the installer on macOS may hand you a b build that behaves like a 1.0 without being one. Both of those facts carry an August timestamp and the release post points packaging questions at that same discussion, so check your channel before you trust the number.

🧭 What I Take From It

Three practical things, no drama.

Pin the tag, not the nightly. That is the entire benefit of 1.0.0 shipping as a tag and it costs nothing to take. Nightlies still exist for when you need model support that landed yesterday, but a production container should contain v1.0.0, not b12359.

Treat the C header as the contract and the server as best effort. If your integration is C or C++ against llama.h, you can now read the first digit and plan the upgrade. If your integration is HTTP, the OpenAI-compatible endpoints are the stable part and the router and tools surface is the moving part. Those are different risk profiles and they are now formally different, which is an improvement over everything being equally unstable.

Expect the churn to stay high anyway. The plan discussed was roughly one release per week, mostly minor, because model support alone justifies cutting a release. A minor bump every week is a lot of library updates for a distro to carry, and it means the 1.x band is wide. The major digit tells you when you have to do work. It does not tell you the surface stopped changing.

🧠 Final Thoughts

What makes this release worth writing about is not version 1.0. It is the order of operations. The project defined what breaks before it needed the definition, then paid for the definition by deleting thirty-five functions and closing down an entire experimental header boundary in the same tag. Most projects I depend on reach 1.0 first and learn their compatibility policy afterward, one bug report at a time.

The caveat I would give anyone quoting the release notes: the promise is about libllama and libggml. It is not a promise about llama-server. Know which of the two you actually integrated against, because only one of them just got a contract.

Thanks for reading.

[ SIGNATURE VERIFIED // GPG 0x4EB27DB0 // PROVENANCE SECURE ]
➔ RETURN TO LOGS