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
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ jobs:
- name: Offline tests
run: cargo test --locked

java:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
java: ["21", "25"]
defaults:
run:
working-directory: java
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: ${{ matrix.java }}
cache: maven
cache-dependency-path: java/pom.xml
- name: Offline tests
run: mvn -B -ntp verify

bootstrap:
runs-on: ubuntu-latest
strategy:
Expand Down Expand Up @@ -137,3 +157,14 @@ jobs:
working-directory: rust
env:
JACQUARD_REQUIRE_LIVE: "1"
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: maven
cache-dependency-path: java/pom.xml
- name: Run independent Java adapter against Core
run: mvn -B -ntp verify
working-directory: java
env:
JACQUARD_REQUIRE_LIVE: "1"
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ invent messages that Core has not specified.
- Keep the first carrier serial, bounded, versioned, and fail-closed.
- Preserve transport independence: process framing is one carrier, not the
semantic definition of the boundary.
- The Python, TypeScript, Go, and Rust adapters each implement the pinned
fixtures independently. Keep pin constants and kit copies generated by
`scripts/core_pin.py`.
- The Python, TypeScript, Go, Rust, and Java adapters each implement the
pinned fixtures independently. Keep pin constants and kit copies generated
by `scripts/core_pin.py`.
- Add tests with behavior. Use the standard library until a reviewed need
justifies a dependency.
- Work on branches and merge through pull requests. The empty repository seed
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@
handler reports completion unknown. As a consequence `HandlerError` cannot
implement `std::error::Error`, and a downstream `From` impl for a type that
implements `Error` conflicts with it.
- Java adapter: an independent Maven project in `java/`
(`org.jacquardlang:jacquard-host`, Java 21+) with no third-party runtime
dependencies (on Unix it runs the system `mkfifo`).
It provides strict codecs, the session state machine, a bounded process
carrier for `jacquard host worker`, and a `Host` with a closed operation
registry. It carries the pinned kit as class-path resources and replays all
21 recordings. It is protocol-level only, with no SDK layer. Java cannot
start the worker in its own process group or interrupt a pipe read, so the
carrier never blocks on a read, reads the worker's output through FIFOs it
creates with `mkfifo` on Unix (so the JDK's exit-time pipe drain cannot hold
the caller), kills the worker's process tree from a `ProcessHandle`
snapshot, and documents what that misses in `docs/LIMITS.md`. `scripts/core_pin.py` now generates
`java/src/main/java/org/jacquardlang/host/Compat.java` and keeps the Java kit
copy in sync, and CI runs the offline tests on Java 21 and 25 and the live
tests against the pinned Core.

## 0.2.0 — 2026-10-25

Expand Down
35 changes: 30 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ Contributions are licensed under [Apache 2.0](LICENSE), matching this repository

`core-pin.json` names the one Core release all adapters target. Do not edit
`src/jacquard_host/compat.py`, `typescript/src/compat.ts`, `go/protocol/compat.go`,
`rust/src/compat.rs`, the Go and Rust kit copies under `go/kit/data/` and
`rust/kit/`, or the generated block
`rust/src/compat.rs`, `java/src/main/java/org/jacquardlang/host/Compat.java`,
the Go, Rust, and Java kit copies under `go/kit/data/`, `rust/kit/`, and
`java/src/main/resources/org/jacquardlang/host/kit/`, or the generated block
in `docs/COMPATIBILITY.md` by hand: change the pin with
`python3 scripts/core_pin.py update --tag ...`, which also vendors the kit, and
`python3 scripts/core_pin.py check` (run in CI) reports any drift.
Expand Down Expand Up @@ -111,14 +112,38 @@ kit. `scripts/core_pin.py` maintains both; do not edit them by hand. The
`jacquard-examples` Cargo example reads the rules and inputs from `examples/`
directly, so there is no copy to keep in sync.

## Java

The independent Java adapter lives in `java/` as Maven artifact
`org.jacquardlang:jacquard-host`. It has no third-party runtime dependencies
and does not call Python, Node.js, Go, or Rust; on Unix it runs the system
`mkfifo`. JUnit 5 is its only test dependency. Java 21+ and Maven 3.9+ are
required.

```sh
cd java
mvn -B verify
# With the pinned Core configured (eval "$(python3 ../scripts/core_pin.py install)"):
JACQUARD_REQUIRE_LIVE=1 mvn -B verify
```

CI runs the offline tests on Java 21 and 25, and the live tests on Java 21 in
the shared pinned-Core job. The compiler runs with `-Xlint:all -Werror`.
`java/src/main/java/org/jacquardlang/host/Compat.java` is generated and the
kit under `java/src/main/resources/` is a byte copy of the pinned kit.
`scripts/core_pin.py` maintains both; do not edit them by hand. The `StandIn`
main class in the test sources is a fixture for the offline tests. Copy the
repository `NOTICE` to `java/NOTICE` when it changes (a test fails if they
differ).

## Releasing

A release is one commit on `main` with green CI. To cut one:

1. Open a pull request that dates the CHANGELOG entry and updates any version
references in the docs. Keep the Python (`src/jacquard_host/__init__.py`),
npm (`typescript/package.json`, `typescript/src/version.ts`), Rust
(`rust/Cargo.toml`), and release versions equal.
(`rust/Cargo.toml`), Java (`java/pom.xml`), and release versions equal.
2. After it merges, tag the merge commit twice, with annotated tags
(`git tag -a`):
`jacquard-host-X.Y.Z` for the repository and its assets, and `go/vX.Y.Z`
Expand All @@ -131,8 +156,8 @@ A release is one commit on `main` with green CI. To cut one:
4. Publish a GitHub release for `jacquard-host-X.Y.Z` with the CHANGELOG
entry as its notes and the assets attached.

Nothing is published to PyPI, npm, or crates.io. The Rust crate is used from
the repository tag.
Nothing is published to PyPI, npm, crates.io, or Maven Central. The Rust
crate is used from the repository tag, and the Java artifact is built from it.

## TypeScript

Expand Down
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ recursive-include go *.go *.md *.json *.jac
include rust/Cargo.toml rust/Cargo.lock rust/rustfmt.toml rust/LICENSE rust/NOTICE
recursive-include rust *.rs *.md *.json *.jac
prune rust/target
include java/pom.xml java/LICENSE java/NOTICE
recursive-include java *.java *.md *.json *.jac
prune java/target
7 changes: 4 additions & 3 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ Copyright 2026 Jacquard Host contributors
This product includes conformance artifacts from Jacquard Core,
https://github.com/jbwinters/jacquard-lang, licensed under Apache License 2.0.
The artifacts under src/jacquard_host/data/conformance/host-protocol-v0/,
and their byte-identical copies under go/kit/data/host-protocol-v0/ and
rust/kit/host-protocol-v0/, are copied verbatim from the commits recorded in
docs/COMPATIBILITY.md.
and their byte-identical copies under go/kit/data/host-protocol-v0/,
rust/kit/host-protocol-v0/, and
java/src/main/resources/org/jacquardlang/host/kit/host-protocol-v0/, are
copied verbatim from the commits recorded in docs/COMPATIBILITY.md.

Upstream notice:
Jacquard
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ third-party runtime dependencies. The [TypeScript SDK](typescript/README.md),
the [Go SDK](go/README.md), and the [Rust SDK](rust/README.md) implement the
pinned protocol independently. The TypeScript SDK supports async service
methods, the Go SDK maps native Go types and context cancellation, and the Rust
SDK maps native Rust types through `record!` and `variants!` declarations.
SDK maps native Rust types through `record!` and `variants!` declarations. A
protocol-level [Java adapter](java/README.md) (Java 21+) also implements the
pinned protocol independently. It has a closed operation registry and kit
replay, but no SDK layer yet.

**Experimental:** the SDK targets Core's pinned `jacquard-host-v0` protocol.
Core is installed separately. Each invocation runs one fresh, serial worker;
Expand Down Expand Up @@ -113,8 +116,8 @@ participant collection require separate application work.

See [CONTRIBUTING.md](CONTRIBUTING.md) for offline tests, installed-distribution
checks, and live runs. CI tests Python 3.11–3.13, Node.js 22/24, Go 1.24 and
stable, and Rust 1.88 and stable. It separately installs the pinned Core release
for every adapter's live suite and the public examples.
stable, Rust 1.88 and stable, and Java 21 and 25. It separately installs the
pinned Core release for every adapter's live suite and the public examples.

[Evidence](docs/EVIDENCE.md) records the checks and platform claims;
[development experiments](docs/development/README.md) preserve the usability
Expand Down
19 changes: 11 additions & 8 deletions docs/COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ Every adapter in this repository is pinned to one published Jacquard Core
release, recorded once in [`core-pin.json`](../core-pin.json). The Python
constants (`src/jacquard_host/compat.py`), the TypeScript constants
(`typescript/src/compat.ts`), the Go constants (`go/protocol/compat.go`), the
Rust constants (`rust/src/compat.rs`), and the block below are generated from
that file by `scripts/core_pin.py sync`. `scripts/core_pin.py check` fails CI
when any of them drifts from the pin. It also fails when any vendored kit copy
drifts: the Python package data, Go's embedded `go/kit/data/`, or the Rust
crate's embedded `rust/kit/`. Adapters verify the kit's four
Rust constants (`rust/src/compat.rs`), the Java constants
(`java/src/main/java/org/jacquardlang/host/Compat.java`), and the block below
are generated from that file by `scripts/core_pin.py sync`.
`scripts/core_pin.py check` fails CI when any of them drifts from the pin. It
also fails when any vendored kit copy drifts: the Python package data, Go's
embedded `go/kit/data/`, the Rust crate's embedded `rust/kit/`, or the Java
class-path copy under `java/src/main/resources/`. Adapters verify the kit's four
digests independently at load time, and the SDKs refuse a Core whose
`--version` differs from the pinned version.

Expand Down Expand Up @@ -41,7 +43,7 @@ Release assets verified by `scripts/core_pin.py install`:
| macos-x86_64 | `jacquard-macos-x86_64.tar.gz` | `8efc54bcf7573cb7cfd35fa3e77a584680ce68de872bdb212ed8369a974ff967` |
<!-- core-pin:end -->

Python, TypeScript, Go, and Rust replay the same 21 recordings against the pinned
Python, TypeScript, Go, Rust, and Java replay the same 21 recordings against the pinned
worker, including Core's recorded `noncanonical-target-hash` divergence: the
HB.1 vector expects E1603 while the shipped preflight classifies an uppercase
target hash as a malformed scalar (E1601). The transcript is recorded as
Expand All @@ -52,8 +54,8 @@ independent v0 evidence; it does not change the protocol version or declare v1.
The adapters decode boundary descriptors in Core's order: the kind, then the
exact fields, then one node of `max_value_nodes`, then any identity, then the
list count. Malformed input therefore gets the same error code from every
adapter and from Core. For recording comparisons, Python, Go, and Rust sort object keys
by code point, while TypeScript sorts them by UTF-16 code unit. The two orders
adapter and from Core. For recording comparisons, Python, Go, Rust, and Java sort object
keys by code point, while TypeScript sorts them by UTF-16 code unit. The two orders
differ only for keys outside the Basic Multilingual Plane. Every protocol key is
ASCII, so the comparisons agree.

Expand Down Expand Up @@ -114,6 +116,7 @@ python3 -m pip install . && python3 scripts/check_examples.py
(cd typescript && npm ci && npm test && npm run test:live && npm run check:package)
(cd go && go test -race ./... && go test -count=1 ./...)
(cd rust && cargo test)
(cd java && JACQUARD_REQUIRE_LIVE=1 mvn -B verify)
```

`update` resolves the tag to its commit, copies the kit files from
Expand Down
Loading
Loading