Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crossrepostatus.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ sha256sum ../{java-llama.cpp,BitcoinAddressFinder,srcmorph,streambuffer}/.github
- **jllama's PIT gate is environment-conditional (not fully hermetic).** It reaches 100% only when the **audio test fixture** is present; without it the run is **98%** (4 `NO_COVERAGE` mutants in `value.ContentPart.audioFile(Path)` — the null-name guard, the `.wav`/`.mp3` dispatch, and `Files.readAllBytes`). The only test exercising that method is the model-/fixture-gated `AudioInputIntegrationTest`, which self-skips (`Assume`) when no audio clip is supplied (`net.ladenthin.llama.audio.input` — no committed default). Contrast the sibling `value.ContentPart.imageFile(Path)`, which **is** hermetic via temp-file unit tests (PNG/JPG/GIF/WEBP). So a green jllama PIT gate requires the CI audio fixture; the hermetic fix (a temp-`.wav`/`.mp3` unit test mirroring the image tests) is tracked in jllama `TODO.md`. The other three gates are fully hermetic. See [`policies/pit-mutation-testing.md`](policies/pit-mutation-testing.md) §4.
- **BAF's Coveralls/Codecov coverage source is the `test-opencl` (pocl) job, not the ubuntu `test` matrix** — intentional, and only BAF has this distinction (it is the only repo with OpenCL code). The ubuntu `test` matrix has no OpenCL ICD installed, so `@OpenCLTest`-annotated classes (`OpenCLContext`, `OpenClTask`, `OpenCLGridResult`, `ProducerOpenCL`, etc.) self-skip via `OpenCLPlatformAssume`, producing 0% coverage for the entire GPU pipeline. The `test-opencl` job installs pocl (a conformant OpenCL 3.0 CPU implementation), so the full test suite — including all `@OpenCLTest` classes — actually executes there. Both jobs run on every push/PR; only the JaCoCo artifact consumed by Coveralls/Codecov changed source (`jacoco-report-opencl` from `test-opencl`, not `jacoco-report` from `test`). BAF `publish.yml` commit `5d5db1a`.
- **Depot / `sccache` shared compiler cache — java-llama.cpp only.** jllama's CI fronts the C/C++ compiler with `sccache` backed by **Depot Cache** over sccache's WebDAV backend (`SCCACHE_WEBDAV_ENDPOINT: https://cache.depot.dev`, `SCCACHE_WEBDAV_TOKEN: ${{ secrets.DEPOT_TOKEN }}`, plus `BUILD_JOBS` to bound macOS-runner memory) so its heavy native build (134 llama.cpp TUs + ggml + the 16.6k-line `httplib.cpp`, all `-O3`) recompiles only changed files and shares the cache across branches. Wiring lives in jllama `.github/build.sh` + `.github/workflows/publish.yml`; rationale in jllama `CLAUDE.md` "CI build cache & parallelism (sccache + Depot)". **This is jllama-only by nature, not drift:** `sccache` caches *compiler* output (C/C++/Rust/CUDA) and jllama is the only sibling with a native (C++/JNI) compile. The three pure-Maven siblings (BAF, sb, plugin) have no C/C++ to cache, run on **GitHub-hosted** runners (Depot's *GitHub Actions* cache backend activates only on **Depot-hosted** runners — see [Depot docs](https://depot.dev/docs/cache/integrations/github-actions)), and already cache Maven deps via `actions/setup-java`'s `cache: maven` (GitHub's per-branch cache). The `DEPOT_TOKEN` organization secret was added to **all** repos (2026-06-20) but is **inert** outside jllama. The README "Build cache by Depot" badge (jllama `README.md`) is therefore kept **jllama-only on purpose** — adding it to the Maven repos would advertise a capability they don't have. Same shape as the BAF-only pocl/OpenCL coverage entry above (a real per-repo capability difference, not a parity gap to close).
- **`jar-with-dependencies` (fat/uber JAR) = GitHub-Release asset only, never Central, signed `.asc` — BAF + jllama + srcmorph (not sb).** *(Updated 2026-07-24, branch `claude/bitcoinaddressfinder-jar-upload-k0tkj7` — supersedes the earlier "per-run CI artifact only" state.)* The full convention + per-repo shapes live in the canonical [`policies/fat-jar-release-assets.md`](policies/fat-jar-release-assets.md). Summary: the uber jar is **never deployed to Maven Central** (redundant + large +, where it bundles a native binary, platform-specific) and is **attached to the GitHub Release with a detached GPG `.asc`** (authenticity parity with the thin jars). Per-repo **shape differs by design** (deliberate non-parity, not drift): **BAF** — one fat jar (jocl bundles all-platform OpenCL natives), built off-Central via `mvn -P release,assembly verify` (stops before `deploy`), signed by `maven-gpg`. **jllama** — multi-backend `all-<os>-<arch>` jars (default CPU + per-backend subdirs, `LlamaLoader`-selected) via `package-fatjars.sh`, signed by `.github/sign-fatjars.sh` in the attach jobs (`.sha256` **and** `.asc`). **srcmorph** (`srcmorph-cli`, the repo the workspace still labels `plugin`) — one fat jar **per `net.ladenthin:llama` classifier** (default CPU + 16 GPU classifiers), kept off Central via `<attach>false</attach>`, built + `gpg`-signed in a `publish.yml` loop. **sb** — ➖ still **none** (single-class `Closeable` library, no runnable entry point). **Gating caveat (all repos):** assets attach only on the `workflow_dispatch` + `publish_to_central=true` path; a plain `v*` tag push attaches nothing (symptom: a release with `assets: []`, as jllama v5.0.6 showed). Original CI-artifact wiring was branch `claude/cool-curie-ym3acr`.
- **`jar-with-dependencies` (fat/uber JAR) = GitHub-Release asset only, never Central, signed `.asc` — BAF + jllama + srcmorph (not sb).** *(Updated 2026-07-24, branch `claude/bitcoinaddressfinder-jar-upload-k0tkj7` — supersedes the earlier "per-run CI artifact only" state.)* The full convention + per-repo shapes live in the canonical [`policies/fat-jar-release-assets.md`](policies/fat-jar-release-assets.md). Summary: the uber jar is **never deployed to Maven Central** (redundant + large +, where it bundles a native binary, platform-specific) and is **attached to the GitHub Release with a detached GPG `.asc`** (authenticity parity with the thin jars). Per-repo **shape differs by design** (deliberate non-parity, not drift): **BAF** — one fat jar (LWJGL's per-platform `natives-*` classifiers all coexist on one classpath), built off-Central via `mvn -P release,assembly verify` (stops before `deploy`), signed by `maven-gpg`. **jllama** — multi-backend `all-<os>-<arch>` jars (default CPU + per-backend subdirs, `LlamaLoader`-selected) via `package-fatjars.sh`, signed by `.github/sign-fatjars.sh` in the attach jobs (`.sha256` **and** `.asc`). **srcmorph** (`srcmorph-cli`, the repo the workspace still labels `plugin`) — one fat jar **per `net.ladenthin:llama` classifier** (default CPU + 16 GPU classifiers), kept off Central via `<attach>false</attach>`, built + `gpg`-signed in a `publish.yml` loop. **sb** — ➖ still **none** (single-class `Closeable` library, no runnable entry point). **Gating caveat (all repos):** assets attach only on the `workflow_dispatch` + `publish_to_central=true` path; a plain `v*` tag push attaches nothing (symptom: a release with `assets: []`, as jllama v5.0.6 showed). Original CI-artifact wiring was branch `claude/cool-curie-ym3acr`.
- **Actual Gradle-based *publishing* (the `llama-android` AAR) — java-llama.cpp only.** The `verify-signing-key-gradle` **harness** is now in parity across all 4 (see "In parity" above — kept byte-identical as a "prepared for Gradle" canary, a deliberate uniformity choice). What stays jllama-only is a real **Gradle publish**: the `llama-android` AAR (`publishAllPublicationsToCentralSnapshotsRepository` / `…StagingRepository`, `llama-android/build.gradle.kts`) signs with Gradle's `useInMemoryPgpKeys` (BouncyCastle), where the AAR snapshot signing originally failed with a **null `PGPPrivateKey`**. **Root cause** (2026-07-09, jllama `main` run 29012094281, reproduced in isolation by the harness): Gradle's **2-arg** `useInMemoryPgpKeys` selects the **primary** key, whose secret this BouncyCastle can't unlock, while `gpg`/maven-gpg-plugin auto-select the key's **4096-bit signing subkey** `07D2D767`. **Fix:** the **3-arg** `useInMemoryPgpKeys(keyId, key, passphrase)` when `MAVEN_GPG_KEY_ID` is set, driven by the **`GPG_KEY_ID`** env secret (`= 07D2D767`) added to the `maven-central` environment in all 4 repos — **consumed only by jllama** (the three Maven siblings' gpg agent already picks the subkey, so their shared harness reads it too but their Maven publish never needs it). Confirmed green: `verify-signing-key-gradle` on jllama `main`, so the identical-code AAR publish signs correctly. The harness project (`.github/signing-selftest/`) was also refactored from an opaque base64 blob to committed, readable `.kts` files. PRs: jllama #306 (preflights) / #307 (subkey fix); cross-repo harness sync on branch `claude/android-signing-failure-q7zml9`. Same shape as the Depot/sccache and pocl/OpenCL entries (a real per-repo capability difference — jllama is the only repo with a Gradle-published artifact — not a parity gap to close).

---
Expand Down
3 changes: 2 additions & 1 deletion guides/src/CODE_WRITING_GUIDE-21.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,5 @@ until there's a real use case in the BAF codebase:
- **Structured concurrency (`StructuredTaskScope`)** — preview API as
of JDK 21; revisit when GA.
- **Foreign Function & Memory API** — relevant for any future direct
native-memory work, but BAF currently uses JOCL for GPU off-heap.
native-memory work, but BAF currently uses LWJGL (its own `MemoryStack` /
`MemoryUtil` off-heap allocators) for GPU memory.
83 changes: 83 additions & 0 deletions llama.cpp/contributions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Contributions and open items

Upstream: [ggml-org/llama.cpp](https://github.com/ggml-org/llama.cpp). Downstream carrier is
jllama, which applies `llama/patches/*.patch` to the FetchContent-ed tree via
`cmake/apply-llama-patches.cmake`.

**Nothing submitted yet.** The patches below are maintained downstream; this file records
which of them are upstream-worthy and what is still missing before they can be offered.

## Ground rules for this repo

llama.cpp's `AGENTS.md` forbids agents from writing pull-request descriptions, issue bodies
and review responses - explicitly "non-overridable under any circumstances", with a
contributor ban as the stated consequence. The prose has to be written by hand. An agent may
gather facts, verify claims against the code and run experiments, and that is where its
value lies here.

`AGENTS.md` also asks for an **issue first** on anything sizeable, rather than an
unannounced pull request.

## Patch status

| Patch | Assessment |
|---|---|
| `0001` win32 arg-parse embed guard | **Issue [#26416](https://github.com/ggml-org/llama.cpp/issues/26416) opened 2026-08-01**, awaiting a maintainer's answer on which direction they want |
| `0002` preserve caller load-progress callback | **Not upstream-worthy as it stands.** Stays downstream |
| `0009` guard `addchdir_np` on old glibc | **Resolved elsewhere.** Went to sheredom instead; see below |

### `0001` - `common_params_parse` discards the caller's argv on Windows

`common/arg.cpp:1203-1209` replaces the caller's `argv` with one rebuilt from
`GetCommandLineW()` whenever the element counts match. Contents are never compared, so a
caller that builds its own argv can silently get the process command line parsed.

Reproduced on unmodified `master` @ `ddd4ec142`, MSVC 19.44, no JNI involved: llama.cpp's
own `test-arg-parser` passes when started with one command line token and fails at
`tests/test-arg-parser.cpp:96` when started with three, because the negative test's
three-element argv is swapped for the process command line.

Full write-up, with the exact output and the build recipe:
`../java-llama.cpp/docs/upstream-investigation-win32-argv-substitution.md`.

Two directions to offer, both described there: split the entry point
(`common_params_parse` parses what it is given, a new `common_params_parse_main` does the
recovery for the standalone tools - clean but 37 files), or tighten the condition to compare
contents (much smaller, but the CRT-argv-versus-ANSI-round-trip comparison may not hold in
every codepage, which would silently disable the #24779 fix it protects).

**Filed as [#26416](https://github.com/ggml-org/llama.cpp/issues/26416)** on 2026-08-01,
labelled `bug-unconfirmed`, first bad commit `508a475` (the #24779 merge - verified: it is
where the substitution entered; the count guard only narrowed it later). The issue reports
the defect, links the analysis, and asks how they want to proceed rather than opening a PR
unannounced. Next step is their answer, not more code.

### `0002` - server clobbers a caller-provided `load_progress_callback`

`tools/server/server-context.cpp` installs the server's own progress reporter
unconditionally. Guarding it with `if (params_base.load_progress_callback == nullptr)` is an
eight-line change and provably inert for the standalone server, where the field is always
null.

Left downstream because there is **no in-tree beneficiary**: the only caller that sets the
field beforehand is an embedder, and embeddability itself is a downstream patch (`0006`).
`AGENTS.md` is explicit that a working, in-scope change is not sufficient - a maintainer has
to want it. The honest answer to "who sets this?" is "my JNI binding", which is not an
upstream use case.

### `0009` - resolved through sheredom, not llama.cpp

The patch modified `vendor/sheredom/subprocess.h`. That file is **re-downloaded verbatim**
by `scripts/sync_vendor.py` from a pinned upstream commit, so a local patch there would have
been silently reverted at the next vendor sync. The fix went to
[sheredom/subprocess.h#104](https://github.com/sheredom/subprocess.h/pull/104) instead; see
`../subprocess.h/contributions.md`.

What remains for llama.cpp is a one-line pin bump in `scripts/sync_vendor.py:24` plus the
re-synced file, once sheredom merges. jllama's patch `0009` is byte-identical to that PR's
head, so `apply-llama-patches.cmake` will report "already applied" and skip it from then on,
rather than failing the build.

**General lesson:** before patching anything under `vendor/`, check whether a sync script
owns the file. A downstream patch is fine there as a stopgap, but the fix belongs upstream
of the vendor pin, not in the vendored copy.
4 changes: 2 additions & 2 deletions policies/fat-jar-release-assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Why never Central:
- A jar-with-dependencies is **redundant** on Central: consumers depend on the *plain* jar and
let Maven resolve the dependency graph; nobody `<dependency>`-references the uber jar.
- It is **large** (bundles every runtime dependency), and where it bundles a **native binary**
(`net.ladenthin:llama`, jocl, …) it is also **platform-specific** — the wrong shape for a
(`net.ladenthin:llama`, LWJGL natives, …) it is also **platform-specific** — the wrong shape for a
Central artifact that is meant to be portable coordinates.
- Not shipping it to Central also avoids any redistribution obligation for bundled vendor
binaries.
Expand Down Expand Up @@ -55,7 +55,7 @@ attached). Symptom of forgetting: a tag release with `assets: []`.
|---|---|---|---|
| **jllama** (`java-llama.cpp`) | Multi-backend **`all-<os>-<arch>`** jars (default CPU + every GPU backend of that OS/arch in `net/ladenthin/llama/<OS>/<ARCH>/<backend>/` subdirs, runtime-selected by `LlamaLoader` via the `jllama-backends.txt` manifest) + the default CPU fat jar | The Central `deploy` runs **without** the `assembly` profile; the fat jars are assembled by a separate `package-fatjars` job | `.github/package-fatjars.sh` assembles them; `.github/sign-fatjars.sh` GPG-signs each (`.asc`) in the `github-release-signed` / `github-snapshot` attach jobs (which declare `environment: maven-central` + `checkout`). `.sha256` **and** `.asc`. |
| **srcmorph** (`srcmorph-cli`) | One CLI fat jar **per `net.ladenthin:llama` classifier** (default all-platform CPU + one per GPU classifier: `cuda13-*`, `vulkan-*`, `opencl-*`, `rocm-*`, `sycl-*`, `openvino-*`, `msvc-windows`) named `srcmorph-cli-<v>-jar-with-dependencies[-<classifier>].jar` | `srcmorph-cli/pom.xml` sets `<attach>false</attach>` on the assembly execution → built into `target/` but never installed/deployed | The `publish-{release,snapshot}` jobs loop over the classifier set (`mvn -pl srcmorph-cli -am -Dllama.classifier=<c> package`), rename per classifier (default built **last** = unsuffixed CPU jar), collect them into the asset dir, then sign via `.github/sign-fatjars.sh`. `.asc` only. |
| **BAF** (`BitcoinAddressFinder`) | **Single** fat jar (`jocl` bundles all-platform OpenCL natives in one jar, so no classifier split) | The Central `deploy` runs `-P release` **without** `assembly`; the fat jar is built by a **second** invocation that stops at `verify` (never reaching `deploy`), so `central-publishing`'s deploy-bound publish goal never runs | `mvn -P release,assembly verify` in the `publish-{release,snapshot}` jobs; `maven-gpg-plugin` (bound to `verify`) signs the attached fat jar → `.asc`. |
| **BAF** (`BitcoinAddressFinder`) | **Single** fat jar (LWJGL ships one `natives-*` classifier jar per platform, but they may all sit on one classpath — LWJGL picks the match at runtime — so there is still no classifier split) | The Central `deploy` runs `-P release` **without** `assembly`; the fat jar is built by a **second** invocation that stops at `verify` (never reaching `deploy`), so `central-publishing`'s deploy-bound publish goal never runs | `mvn -P release,assembly verify` in the `publish-{release,snapshot}` jobs; `maven-gpg-plugin` (bound to `verify`) signs the attached fat jar → `.asc`. |
| **sb** (`streambuffer`) | ➖ N/A — a pure library with no runnable entry point, so no fat jar is produced or shipped | — | — |

## Keep-in-sync notes
Expand Down
Loading