refactor: move core into llama/ submodule under a Maven reactor (parent + llama + llama-langchain4j)#288
Conversation
…ven reactor)
Phase 2 structural move. The repo root becomes a thin aggregator/parent POM
(net.ladenthin:llama-parent, packaging=pom) with two modules: llama (the native
JNI core) and llama-langchain4j. Both inherit the single shared <version> from
the parent, so they ship in lockstep by construction (the CI version-lockstep
guard becomes redundant and is removed in the CI pass).
- git mv the entire core into llama/: src/, CMakeLists.txt, cmake/, patches/,
pom.xml, spotbugs-exclude.xml, lombok.config, .clang-format, .clang-tidy.
(All tracked as renames; the core pom's ${basedir}/… and relative
spotbugs-exclude.xml auto-re-root; CMakeLists paths are relative to itself.)
- New root pom.xml = aggregator (modules: llama, llama-langchain4j).
- llama/pom.xml and llama-langchain4j/pom.xml become children of llama-parent
(drop their own <version>; inherit it). The core keeps its published
coordinates net.ladenthin:llama — consumers are unaffected by the move.
Verified locally: the reactor builds green (parent → llama → llama-langchain4j),
all three install at 5.0.4-SNAPSHOT, langchain4j resolves the core via the
inherited ${project.version}.
CI path re-rooting (workflows, build scripts, REUSE.toml, .gitignore) follows in
the next commit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rt1paYztGJ2AKUuBuAGDXE
…, workflows, configs) Follows the structural move: everything that assumed the core lived at the repo root now points into the llama/ module. No behavioural change to the native build — only paths. - build.sh / build.bat: cd into llama/ (relative to the script's own location) before cmake, so every native build (incl. the build_cuda_linux.sh / build_opencl_*.sh wrappers and the dockcross containers, whose workdir stays the repo root) configures the module. This single hook re-roots all native builds. - publish.yml: mvn compile/test/PIT/vmlens/spotbugs/spotless now target -f llama/pom.xml; ctest uses llama/build; all artifact upload/download + webui-generated paths prefixed with llama/; GIT_TAG read from llama/CMakeLists.txt; jacoco/pit/vmlens/jar produce-paths -> llama/target (report-job download dirs stay at root). Removed the now-redundant version-lockstep guard (inheritance guarantees it) and the separate llama-langchain4j deploy steps (one reactor `mvn -P release deploy` publishes parent + llama + llama-langchain4j together). - release profile (GPG + Central Publishing) moved to the parent pom so the reactor deploy signs every module incl. the parent .pom; removed from the two child poms. - clang-format.yml, sonarqube.yml, REUSE.toml, .gitignore re-rooted to llama/. codeql.yml left as a root reactor compile (now also covers llama-langchain4j). Verified locally: full reactor builds; `mvn -pl llama -am install` (the langchain4j jobs' install step) installs parent+core; `mvn -N -P release validate` parses the moved release profile; `mvn -f llama-langchain4j verify` is green (7 mapping tests, 4 self-skip, main+sources+javadoc jars). Native path re-rooting is validated by CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rt1paYztGJ2AKUuBuAGDXE
- New "Repository layout — Maven reactor" section: the root is an aggregator/parent POM with llama/ (core) and llama-langchain4j/ modules; core sources + build files now live under llama/; build.sh/build.bat cd into llama/ themselves; core Maven builds use -f llama/pom.xml or -pl llama -am; version bumps happen in the root pom only (both modules inherit). Adds the caveat that existing root-relative build examples in this file now run in llama/. - Rewrote the LangChain4j section: it is now a reactor module inheriting the parent version (no lockstep guard), releasing via one reactor deploy (inherited release profile), with the install step using -pl llama -am. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rt1paYztGJ2AKUuBuAGDXE
| <version>${reactor.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <profiles> |
There was a problem hiding this comment.
Excellent design: the parent POM holds the release profile centrally, so both child modules inherit GPG + Central Publishing configuration. A single mvn -P release deploy publishes all three artifacts (parent pom + llama + llama-langchain4j) at the same version. This eliminates the CI version-lockstep guard and duplicate profile definitions.
| # cmake configures the module regardless of the caller's CWD. Anchored to this script's | ||
| # own location (via BASH_SOURCE), so it works from the repo root and inside the dockcross | ||
| # container whose workdir is the mounted repo root. | ||
| cd "$(dirname "${BASH_SOURCE[0]}")/../llama" || exit 1 |
There was a problem hiding this comment.
Clean solution: the build script anchors itself to its own location via BASH_SOURCE, so it works from the repo root and inside dockcross containers (whose workdir stays the repo root). This single cd re-roots all native builds without per-job working-directory gymnastics. The comment is helpful for understanding the intent.
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <groupId>net.ladenthin</groupId> | ||
| <parent> |
There was a problem hiding this comment.
Good: llama-langchain4j now correctly declares llama-parent as its parent, inheriting the version and release profile. The relativePath points to ../pom.xml. This eliminates the CI version-lockstep guard that was previously needed. ✓
| # :llama-langchain4j. The `release` profile (GPG + Central Publishing) is inherited | ||
| # from the parent, so every module — including the parent pom — is signed. | ||
| - name: Publish snapshot (reactor - parent + llama + llama-langchain4j) | ||
| run: mvn --batch-mode --no-transfer-progress -P release,cuda,opencl-android,windows-msvc,cuda-windows,vulkan-windows,opencl-windows -Dmaven.test.skip=true deploy |
There was a problem hiding this comment.
Perfect: the snapshot deploy is now a single reactor mvn -P release deploy, which publishes all three artifacts (parent pom + llama + llama-langchain4j) in one command. The release profile is inherited from the parent, so every module is signed. This replaces the previous separate llama-langchain4j deploy step. ✓
|
This is a well-executed Maven reactor refactoring. The structural changes are clean and significantly improve the project layout. No behavioral changes to the native build or consumer API — the core artifact Strengths:
Status:
Well-executed. All path updates consistent and correct. Ready for CI validation of the native build matrix. 👍 |
…ter the llama/ move
The C++ compile failed on every native job with `fatal error: jni.h: No such
file or directory`. The bundled JNI headers live in .github/include/ at the repo
ROOT, but CMakeLists.txt now runs inside the llama/ module, so the relative
`.github/include/unix` resolved to the non-existent llama/.github/include/unix.
Anchor it to ${CMAKE_CURRENT_SOURCE_DIR}/../.github/include/{unix,windows} so it
points at the repo root regardless of build CWD. Covers Linux, macOS and Windows
(all use the bundled headers). The other CMakeLists paths use
${CMAKE_SOURCE_DIR}/… which already resolves inside llama/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rt1paYztGJ2AKUuBuAGDXE
Pre-existing formatting violation in special_tokens_json (the token-id map added by #286 / ModelMeta) that this branch inherited unchanged through the move. The reactor PR's clang-format check surfaced it. Reflowed with the pinned clang-format 22.1.5; no logic change. (Implies main currently carries the same violation — it self-resolves when this merges.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rt1paYztGJ2AKUuBuAGDXE
PR Review: Maven Reactor Refactoring - Documentation IssueCritical Issue: CLAUDE.md documentation contradicts the actual code structure. The PR moves code into a Maven reactor with an aggregator parent and two modules (llama, llama-langchain4j), BUT the CLAUDE.md removed the "Repository layout" section and reverted LangChain4j description to "standalone sibling module" — which contradicts the actual POM structure. Current code reality:
CLAUDE.md says:
This must be fixed: Either restore the reactor layout docs to match the code, or revert the code to actual standalone. The PR description states reactor structure, so restore CLAUDE.md to document it. |
| # dir so the path is correct regardless of the build CWD. | ||
| if(OS_NAME MATCHES "^Linux" OR OS_NAME STREQUAL "Mac" OR OS_NAME STREQUAL "Darwin") | ||
| set(JNI_INCLUDE_DIRS .github/include/unix) | ||
| set(JNI_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../.github/include/unix) |
There was a problem hiding this comment.
✅ Good fix: anchoring JNI headers to repo root via ${CMAKE_CURRENT_SOURCE_DIR}/../.github/include/ ensures cmake resolves them correctly regardless of build CWD. This would have failed all native builds before the fix.
| # cmake configures the module regardless of the caller's CWD. Anchored to this script's | ||
| # own location (via BASH_SOURCE), so it works from the repo root and inside the dockcross | ||
| # container whose workdir is the mounted repo root. | ||
| cd "$(dirname "${BASH_SOURCE[0]}")/../llama" || exit 1 |
There was a problem hiding this comment.
✅ Good: cd "$(dirname "${BASH_SOURCE[0]}")/../llama" re-roots the build into the llama/ module relative to the script's own location. This single hook re-roots every native build (incl. build_cuda_linux.sh / build_opencl_*.sh wrappers and dockcross containers).
| REM The core project (CMakeLists.txt + src\) lives in the `llama\` module of the Maven | ||
| REM reactor. Re-root here once (relative to this script's own location) so cmake | ||
| REM configures the module regardless of the caller's CWD. | ||
| cd /d "%~dp0..\llama" || exit /b 1 |
There was a problem hiding this comment.
✅ Good: Windows equivalent of build.sh — cd /d "%~dp0..\llama" re-roots into llama/ module. Both Unix and Windows scripts now have the same single re-rooting hook.
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| <project.build.outputTimestamp>${git.commit.time}</project.build.outputTimestamp> | ||
| </properties> | ||
| <modules> |
There was a problem hiding this comment.
✅ Correct aggregator structure: root POM declares both llama and llama-langchain4j modules, so they build and deploy together in lockstep.
| <parent> | ||
| <groupId>net.ladenthin</groupId> | ||
| <artifactId>llama-parent</artifactId> | ||
| <version>5.0.4-SNAPSHOT</version> |
There was a problem hiding this comment.
✅ Correct parent reference: <relativePath>../pom.xml</relativePath> points to the aggregator parent. Both llama and llama-langchain4j inherit the single <version> from the parent, guaranteeing lockstep by construction.
| @@ -1225,51 +1225,76 @@ keeping it clear of the JPMS module-mode javadoc trap that bit BAF. **Before rai | |||
| javadoc source level to ≥ 9, read** | |||
| [`../workspace/policies/jpms-module-descriptor.md`](../workspace/policies/jpms-module-descriptor.md). | |||
|
|
|||
There was a problem hiding this comment.
llama/). Current state: CLAUDE.md says "standalone sibling, deliberately not in the root reactor" but the code has it in <modules>.
| ## LangChain4j integration (`llama-langchain4j` sibling module) | ||
| ## Repository layout — Maven reactor (`llama/` + `llama-langchain4j/`) | ||
|
|
||
| The repo root is a thin **aggregator/parent POM** (`net.ladenthin:llama-parent`, |
There was a problem hiding this comment.
<modules>), so it's no longer "deliberately not in the root reactor." Update this to clarify: "It is now a reactor module alongside the core llama module" and reference the restored "Repository layout" section above.
Summary of ReviewCode Quality: EXCELLENT - No bugs found in Maven POM configuration, native build re-rooting, or script changes. The CMake JNI header path anchoring is correct. Documentation: CRITICAL ISSUE - The code implements a reactor structure but CLAUDE.md contradicts it. CLAUDE.md says llama-langchain4j is a standalone module not in the reactor, but it is actually listed in the root pom.xml modules. The 'Repository layout' section needs to be restored to document the aggregator structure. |
|
On the flagged CLAUDE.md "contradiction": this is a misread of the diff — the documentation already matches the reactor code, so there's nothing to fix here. At the current branch HEAD (
The Generated by Claude Code |
Code Review SummaryThis PR restructures the repository into a Maven reactor with parent POM and two modules (llama and llama-langchain4j), improving organization and version management. Strengths:
Issues Found: CRITICAL: CLAUDE.md outdated build examples Lines 800+ in Build Commands section contain many root-relative paths (cmake -B build, mvn compile) that are now inaccurate since core moved to llama/ module. The clarifying note explaining to interpret root examples as running in llama/ was removed but examples remain unchanged. MINOR: Confirm version-lockstep validation in CI workflow actually fails the build if module version diverges from parent version. Security: No sensitive files exposed. GPG/release profile properly migrated. Recommendation: Hold for CLAUDE.md fixes - update build examples to either reference llama/ explicitly or restore the clarifying note about interpreting root paths as running in llama/. |
|
|
||
| **Consequences for build commands:** the core's cmake/native build runs *in `llama/`*. | ||
| `.github/build.sh` / `build.bat` `cd` into `llama/` themselves (relative to the script), so CI | ||
| and the dockcross containers (whose workdir stays the repo root) are unaffected. Locally, run | ||
| core cmake builds from `llama/` (e.g. `cd llama && cmake -B build && cmake --build build`), and | ||
| target the core with Maven via `-f llama/pom.xml` (or `-pl llama -am` from the root). A plain | ||
| `mvn` at the root builds the whole reactor. **When a build-command example elsewhere in this | ||
| file shows `cmake -B build` / `src/main/...` / `mvn compile` at the root, read it as running in | ||
| `llama/`** (the paths moved; the recipes are otherwise unchanged). | ||
|
|
||
| **Version bump:** change the `<version>` in the **root** `pom.xml` only; `llama` and |
There was a problem hiding this comment.
Documentation issue: The CI section here describes checking version lockstep: "runs a version-lockstep guard (module version must equal core version, else the build fails — the standalone module can't inherit ${project.version} from a reactor)".
However, the langchain4j module uses ${project.version} from the parent (which it inherits). Can you clarify or point to where the lockstep validation actually happens in the CI workflow? Is this an explicit check, or does it rely on Maven's implicit enforcement?
| `.github/build.sh` / `build.bat` `cd` into `llama/` themselves (relative to the script), so CI | ||
| and the dockcross containers (whose workdir stays the repo root) are unaffected. Locally, run | ||
| core cmake builds from `llama/` (e.g. `cd llama && cmake -B build && cmake --build build`), and | ||
| target the core with Maven via `-f llama/pom.xml` (or `-pl llama -am` from the root). A plain | ||
| `mvn` at the root builds the whole reactor. **When a build-command example elsewhere in this | ||
| file shows `cmake -B build` / `src/main/...` / `mvn compile` at the root, read it as running in | ||
| `llama/`** (the paths moved; the recipes are otherwise unchanged). | ||
|
|
There was a problem hiding this comment.
Clarification needed: The description says the llama-langchain4j module "Carries its own sources/javadoc/gpg + release profile" and "the module has no parent to inherit them from — plugin versions are pinned in lockstep with the root pom.xml".
However, the POM clearly shows:
<parent>
<groupId>net.ladenthin</groupId>
<artifactId>llama-parent</artifactId>
<version>5.0.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>This contradicts "the module has no parent". The module DOES have a parent (llama-parent), so it DOES inherit the version. Please update this section to accurately reflect the new reactor structure where both modules inherit from the parent.
| **Version bump:** change the `<version>` in the **root** `pom.xml` only; `llama` and | ||
| `llama-langchain4j` inherit it. (The SNAPSHOT/`-SNAPSHOT` line and the README badge still need | ||
| the usual manual update.) | ||
|
|
||
| ## LangChain4j integration (`llama-langchain4j` reactor module) | ||
|
|
||
| `llama-langchain4j/` adapts a `LlamaModel` to LangChain4j's `ChatModel`, | ||
| `StreamingChatModel`, `EmbeddingModel` and `ScoringModel` interfaces **in-process over |
There was a problem hiding this comment.
Documentation accuracy issue: The description here says the langchain4j CI job "runs a version-lockstep guard (module version must equal core version, else the build fails — the standalone module can't inherit ${project.version} from a reactor)".
However, looking at the actual workflow in publish.yml:
- Line 170-172: The module is installed via
mvn -pl llama -am ... install(parent + core only) - Line 174: Then
mvn -f llama-langchain4j/pom.xml verifybuilds the module in isolation
There's no explicit version-lockstep validation shown here. The version is inherited from the parent via the parent reference in the module's POM, so versions are automatically in sync — there's no CI guard needed. Please clarify whether an explicit guard is supposed to exist, or update the docs to say version lockstep is guaranteed by construction (parent inheritance) rather than by a CI guard.
| <relativePath>../pom.xml</relativePath> | ||
| </parent> | ||
|
|
||
| <artifactId>llama</artifactId> |
There was a problem hiding this comment.
Note for future reference: While the module POM correctly references the parent, consumers should be aware that build examples in CLAUDE.md (like cmake commands, path references) now apply to the llama/ directory. The published coordinates remain net.ladenthin:llama, so consuming code is unaffected, but internal contributors should run cmake -B build from within the llama/ directory (the .github/build.sh and .github/build.bat scripts handle this automatically).
Review CompleteI've identified and commented on the documentation issues. To summarize: Main Issues (all in CLAUDE.md):
Positive observations: ✅ Solid architectural design - version lockstep guaranteed at model level The structural work is solid. Once you clarify the CLAUDE.md documentation (particularly fixing the contradictions about the parent relationship and version lockstep), this should be ready for CI validation. |
…DE.md The per-section upgrade instructions (CUDA/Android/OpenCL/Windows classifier steps and the llama.cpp version bump) name the core `pom.xml` / `CMakeLists.txt` that a contributor would copy-paste — those now live in llama/. Re-rooted the precise `**pom.xml**` / `**CMakeLists.txt**` callouts, the `# Edit …` lines, the `git add …` lines, and the build-webui GIT_TAG reference to llama/. The **root** aggregator pom.xml (the version-bump target) is deliberately left unqualified. The loose build-command examples (cmake -B build / mvn compile) remain covered by the "read root examples as running in llama/" note in the Repository layout section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rt1paYztGJ2AKUuBuAGDXE
|
|
||
| - **`llama/`** — the native JNI core (`net.ladenthin:llama`). *All the core sources and build |
There was a problem hiding this comment.
Documentation bug: This section contains contradictions:
- Lines 1232-1233 claim
llama-langchain4jis "deliberately not in the root reactor" - Lines 1250 claim "the module has no parent"
- Lines 1254-1255 claim "the standalone module can't inherit
${project.version}from a reactor"
However, the actual implementation shows:
- Root
pom.xmllists it as a module:<module>llama-langchain4j</module> llama-langchain4j/pom.xmldeclares the parent:<parent><artifactId>llama-parent</artifactId>- It inherits the version:
<version>5.0.4-SNAPSHOT</version>is inherited from the parent
Per the PR description, llama-langchain4j IS now part of the Maven reactor. The docs need to be corrected to accurately reflect this architectural change.
| **Version bump:** change the `<version>` in the **root** `pom.xml` only; `llama` and | ||
| `llama-langchain4j` inherit it. (The SNAPSHOT/`-SNAPSHOT` line and the README badge still need | ||
| the usual manual update.) | ||
|
|
There was a problem hiding this comment.
Documentation inconsistency: The docs claim there is a "version-lockstep guard" that "module version must equal core version, else the build fails." However:
- The CI job
test-java-llama-langchain4j(lines 158-175 of publish.yml) has no version guard — it just runsmvn -f llama-langchain4j/pom.xml verify - Both modules now inherit
${project.version}from the parent, so version lockstep is guaranteed by construction, not by CI validation - The old guard is "gone" (per line 154-155 of publish.yml), but CLAUDE.md still describes it as if it exists
The docs should state: "Version lockstep is guaranteed by construction (both modules inherit the parent's version), so no explicit CI guard is needed."
|


Summary
net.ladenthin:llama-parent,packaging=pom) with two modules:llama/(the native JNI core, moved here wholesale) andllama-langchain4j/. The core keeps its published coordinatesnet.ladenthin:llama— consumers are unaffected.<version>from the parent, so the previous CI version-lockstep guard is gone. A single reactormvn -P release deploysigns and publishes all three artifacts (parent pom,llama,llama-langchain4j) at the same version (thereleaseprofile — GPG + Central Publishing — moved to the parent; the redundant separatellama-langchain4jdeploy steps are removed)..github/build.sh/build.batcdintollama/relative to the script's own location, so every native build (incl. thebuild_cuda_linux.sh/build_opencl_*.shwrappers and the dockcross containers, whose workdir stays the repo root) configures the module — no per-jobworking-directorygymnastics.publish.yml(mvn-f llama/pom.xml,ctest --test-dir llama/build, all artifact +webui-generatedpaths,GIT_TAGfromllama/CMakeLists.txt,jacoco/pit/vmlens/jarproduce-paths),clang-format.yml,sonarqube.yml,REUSE.toml,.gitignore.codeql.ymlstays a root reactor compile (now also coveringllama-langchain4j).Test plan
mvn -pl llama -am install(the langchain4j jobs' install step) installs parent + core;mvn -N -P release validateparses the moved release profile;mvn -f llama-langchain4j/pom.xml verifyis green (7 mapping tests, 4 self-skip, main+sources+javadoc jars).CLAUDE.mdgains a "Repository layout — Maven reactor" section (incl. the caveat that existing root-relative build examples now run inllama/) and a reactor-accurate LangChain4j section.Related issues / PRs
llama-langchain4j). This is the optional "clean multi-subproject structure" step discussed there: core relocated intollama/, room for further sibling modules, automatic version inheritance replacing the CI guard.Notes for review
net.ladenthin:llamais unchanged for consumers.Checklist
🤖 Generated with Claude Code
Generated by Claude Code