ci: gate the packaged jar on the Java 8 class-file floor - #154
Conversation
`maven.compiler.release` governs only the code we compile. A dependency built
for a newer Java lands in the jar untouched and nothing in a normal build
objects; the failure surfaces at a consumer's JVM as
UnsupportedClassVersionError, which is the worst possible place to find it.
It has already happened twice in the sibling repos (checker-qual 4.x, and
logback-classic 1.4.0+ whose LogbackServiceProvider SLF4J's ServiceLoader
loads at startup).
Adds the cross-repo shared `.github/verify-bytecode-version.sh` and runs it in
the `smoke-jar` job. The script is kept byte-identical in java-llama.cpp,
BitcoinAddressFinder, streambuffer and srcmorph; the checksum lives in
workspace/crossrepostatus.md. `--max-major` is passed from the workflow so the
ceiling sits next to the release it belongs to (52 here) rather than being
duplicated inside the script per repo.
This repo is the least exposed of the four — no logger, and the deliverable is
the plain library jar rather than a fat jar — so the step is a regression guard
rather than a fix. It runs before the smoke test so an unloadable class is
reported as such instead of as a mysterious smoke failure.
Notes on the script's shape:
* `module-info.class` and `META-INF/versions/**` are skipped unconditionally.
A classpath JVM never loads either, so a high version there is not a defect
and waiving them per-repo would only invite blanket exceptions.
* exit 2 on an empty scan. A run that found no jars must never read as a pass.
* paths may be jars or directories, so one invocation covers a whole artifact.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnNYn8W1xuVxVJtyL34GyH
Review SummaryThis PR adds excellent infrastructure for preventing Java version incompatibilities in packaged artifacts. The implementation is solid, well-documented, and security-conscious. Strengths✅ Clear motivation: The PR documentation explains the real-world failure modes (checker-qual, logback) that this guards against, making the maintenance burden transparent for future reviewers. ✅ Robust error handling:
✅ Smart design choices:
✅ Security: No shell injection risks (proper quoting), no path traversal issues, minimal dependencies (python3). ✅ Documentation: Excellent inline comments, comprehensive README in script header, well-integrated CLAUDE.md section. ✅ Cross-repo consistency: The byte-identical synchronization requirement is clearly documented with checksum tracking. Minor Observations
No bugs or security issues found. The placement in the workflow (before smoke test) is correct. |
|



Summary
maven.compiler.releasegoverns only the code we compile. A dependency built for a newer Java lands in the jar untouched and nothing in a normal build objects; the failure surfaces at a consumer's JVM asUnsupportedClassVersionError, which is the worst possible place to find it. It has already happened twice in the sibling repos — checker-qual 4.x (@Retention(RUNTIME), so any reflection over an annotated element loads it) and logback-classic 1.4.0+, whoseLogbackServiceProviderSLF4J'sServiceLoaderloads at startup..github/verify-bytecode-version.shand runs it in thesmoke-jarjob. Byte-identical in java-llama.cpp / BitcoinAddressFinder / streambuffer / srcmorph; the checksum lives inworkspace/crossrepostatus.md.--max-majoris passed from the workflow so the ceiling sits next to the release it belongs to (52 here) rather than being duplicated inside the script per repo.Script shape worth knowing:
module-info.classandMETA-INF/versions/**are skipped unconditionally. A classpath JVM never loads either, so a high version there is not a defect (and it is what keeps this repo'srelease 9module-infoout of scope); waiving them per-repo would only invite blanket exceptions.Test plan
mvn package: 5 classes across 2 jars, 0 over major 52Java 8 bytecode floorsection inCLAUDE.mdNo source, test or dependency change; this PR is a CI step plus the shared script and its documentation.
Related issues / PRs
Companion PRs add the same gate to java-llama.cpp, BitcoinAddressFinder and srcmorph, and record it in the workspace checksum table.
Checklist
CONTRIBUTING.mdandCODE_OF_CONDUCT.md🤖 Generated with Claude Code
https://claude.ai/code/session_01AnNYn8W1xuVxVJtyL34GyH
Generated by Claude Code