Skip to content

Commit 9d5cd0d

Browse files
nficanoclaude
andcommitted
refactor SDK structure
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a50e887 commit 9d5cd0d

303 files changed

Lines changed: 10845 additions & 6543 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,53 @@ All notable changes to this project are documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [0.1.0] - 2026-05-10
8+
## [1.0.0]
99

10-
### Added
10+
Initial release of the ARCP Java SDK.
1111

12-
- Initial reference SDK release aligned with ARCP protocol v1.0 (see README status).
12+
### Modules
1313

14+
- `arcp-core`: wire types, envelope, capability negotiation, sealed message and
15+
event taxonomies, ULID-based ids, lease + constraints, in-memory transport.
16+
- `arcp-client`: `ArcpClient`, `JobHandle`, `ResultStream`, `WebSocketTransport`
17+
(JDK `HttpClient.WebSocket`), replaying event publisher.
18+
- `arcp-runtime`: `ArcpRuntime`, session FSM, job FSM, `LeaseGuard`,
19+
`BudgetCounters`, `IdempotencyStore`, `AgentRegistry`, heartbeat tracker,
20+
resume buffer, expiry watchdog.
21+
- `arcp`: umbrella artifact re-exporting client + runtime.
22+
- `arcp-runtime-jetty`: embedded Jetty 12 WebSocket server transport.
23+
- `arcp-otel`: OpenTelemetry adapter (transport-wrapping `Tracer`), W3C
24+
traceparent injection/extraction via the `extensions` payload field.
25+
- `arcp-middleware-spring-boot`: Spring Boot 3.x auto-configuration registers
26+
an `ArcpWebSocketHandler` at the configured path whenever an `ArcpRuntime`
27+
bean is declared.
28+
- `arcp-tck`: reusable JUnit 5 `@TestFactory` conformance suite parameterised
29+
by a `TckProvider` SPI, so downstream JVM ARCP implementations can ride the
30+
same checks.
31+
32+
### Examples
33+
34+
Ten runnable example subprojects: submit-and-stream, cancel, heartbeat,
35+
cost-budget, result-chunk, agent-versions, list-jobs, lease-expires-at,
36+
idempotent-retry, custom-auth. Each prints `OK <name>` on success and asserts
37+
under `-ea`.
38+
39+
### Diagrams
40+
41+
Six Graphviz diagrams (light + dark variants, 12 SVGs total) under
42+
`docs/diagrams/`: module graph, session lifecycle, job lifecycle, capability
43+
negotiation, heartbeat + ack, result-chunk reassembly. Render with
44+
`make -C docs/diagrams`.
45+
46+
### Tests
47+
48+
32 tests across 12 suites cover the wire round-trip, capability intersection,
49+
agent version resolution, budget arithmetic on `BigDecimal`, lease expiry,
50+
glob matching, idempotency reuse and conflict, subscribe with history replay,
51+
result-chunk reassembly, span emission, the Jetty WebSocket end-to-end, the
52+
Spring Boot end-to-end, and seven conformance dynamic tests.
53+
54+
### Build
55+
56+
JDK 21 LTS floor; toolchain JDK 21; `--release 21`. No `--enable-preview`
57+
required of consumers. Virtual threads drive every per-job worker.

CONFORMANCE.md

Lines changed: 152 additions & 50 deletions
Large diffs are not rendered by default.

PLAN.md

Lines changed: 0 additions & 392 deletions
This file was deleted.

README.md

Lines changed: 163 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,184 @@
1-
# `arcp`Java reference implementation of ARCP v1.0
1+
# ARCP Java SDK
22

3-
A clean, idiomatic, tested Java reference implementation of the
4-
**Agent Runtime Control Protocol (ARCP)** v1.0 as specified in
5-
[RFC-0001-v2.md](./RFC-0001-v2.md).
3+
Java SDK for the **Agent Runtime Control Protocol (ARCP)**. Targets JDK 21
4+
LTS; tested on 21. Depends on Jackson and SLF4J only at the `api` level —
5+
no logging binding shipped.
66

7-
> **Status:** Phase 0 (skeleton + plan). The Gradle multi-project build
8-
> compiles cleanly and the four gate commands pass; no protocol surface is
9-
> implemented yet. Track progress in [CONFORMANCE.md](./CONFORMANCE.md).
7+
## Install
108

11-
## Requirements
9+
### Gradle (Kotlin DSL)
1210

13-
- **JDK 25** (LTS). Available via Homebrew as `openjdk` or by direct download
14-
from [adoptium.net](https://adoptium.net/) / [openjdk.org](https://openjdk.org/).
15-
- **Gradle wrapper.** No system Gradle required; the wrapper bootstraps
16-
Gradle 9.0.0 on first run.
11+
```kotlin
12+
dependencies {
13+
implementation("dev.arcp:arcp:1.0.0") // umbrella
14+
// or, granular:
15+
implementation("dev.arcp:arcp-client:1.0.0") // client only
16+
implementation("dev.arcp:arcp-runtime:1.0.0") // runtime only
17+
implementation("dev.arcp:arcp-runtime-jetty:1.0.0") // WebSocket server
18+
implementation("dev.arcp:arcp-otel:1.0.0") // OpenTelemetry tracing
19+
}
20+
```
1721

18-
## Layout
22+
### Maven
1923

24+
```xml
25+
<dependency>
26+
<groupId>dev.arcp</groupId>
27+
<artifactId>arcp</artifactId>
28+
<version>1.0.0</version>
29+
</dependency>
2030
```
21-
java-sdk/
22-
├── settings.gradle.kts # multi-project: :lib, :cli, :examples
23-
├── build.gradle.kts # root config
24-
├── gradle/libs.versions.toml # version catalog
25-
├── lib/ # arcp library (Maven Central artifact)
26-
├── cli/ # `arcp` CLI binary (picocli, application plugin)
27-
├── examples/ # runnable example programs
28-
├── PLAN.md # engineering plan
29-
├── CONFORMANCE.md # per-RFC-section status
30-
└── RFC-0001-v2.md # canonical protocol spec
31+
32+
## Quickstart
33+
34+
```java
35+
import dev.arcp.client.ArcpClient;
36+
import dev.arcp.client.JobHandle;
37+
import dev.arcp.core.transport.MemoryTransport;
38+
import dev.arcp.runtime.ArcpRuntime;
39+
import dev.arcp.runtime.agent.JobOutcome;
40+
41+
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
42+
43+
class Quickstart {
44+
public static void main(String[] args) throws Exception {
45+
MemoryTransport[] pair = MemoryTransport.pair();
46+
ArcpRuntime runtime = ArcpRuntime.builder()
47+
.agent("echo", "1.0.0",
48+
(input, ctx) -> JobOutcome.Success.inline(input.payload()))
49+
.build();
50+
runtime.accept(pair[0]);
51+
52+
try (ArcpClient client = ArcpClient.builder(pair[1]).build()) {
53+
client.connect(java.time.Duration.ofSeconds(5));
54+
JobHandle handle = client.submit(ArcpClient.jobSubmit(
55+
"echo@1.0.0", JsonNodeFactory.instance.objectNode().put("hi", 1)));
56+
System.out.println(handle.result().get().result());
57+
}
58+
runtime.close();
59+
}
60+
}
3161
```
3262

33-
## Build
63+
For a WebSocket-backed runtime, swap `MemoryTransport` for
64+
`dev.arcp.runtime.jetty.ArcpJettyServer` on the runtime side and
65+
`dev.arcp.client.WebSocketTransport.connect(uri)` on the client side.
3466

35-
```bash
36-
export JAVA_HOME=/path/to/jdk-25 # e.g. /opt/homebrew/opt/openjdk
37-
./gradlew check # compile + test + spotless + jacoco
38-
./gradlew javadoc # publish-quality javadoc
39-
./gradlew :lib:publishToMavenLocal # local Maven artifact (Phase 7)
40-
```
67+
## Packaging
4168

42-
## Architecture
43-
44-
```mermaid
45-
flowchart TB
46-
app[Application code]
47-
client[ARCPClient]
48-
runtime[ARCPRuntime]
49-
transport[Transport<br/>WebSocket | stdio | InMemory]
50-
store[(SQLite event log)]
51-
app --> client
52-
client --> transport
53-
transport --> runtime
54-
runtime --> store
55-
```
69+
| Artifact | What's in it | Depends on |
70+
| ------------------------------ | -------------------------------------------------- | ------------------------------- |
71+
| `arcp-core` | Wire types, errors, capability, ids, lease, transport SPI | none |
72+
| `arcp-client` | `ArcpClient`, `JobHandle`, `ResultStream`, JDK WebSocket transport | `arcp-core` |
73+
| `arcp-runtime` | `ArcpRuntime`, session FSM, job FSM, lease enforcement, budget counters | `arcp-core` |
74+
| `arcp` | Umbrella; re-exports client + runtime | `arcp-client`, `arcp-runtime` |
75+
| `arcp-runtime-jetty` | Embedded Jetty 12 WebSocket server transport | `arcp-runtime` |
76+
| `arcp-middleware-spring-boot` | Spring Boot 3.x auto-config + WebSocket handler | `arcp-runtime` |
77+
| `arcp-otel` | OpenTelemetry adapter (transport-wrapping `Tracer`)| `arcp-core`, `opentelemetry-api`|
78+
| `arcp-tck` | Reusable JUnit 5 `@TestFactory` conformance suite | `arcp-client`, `arcp-runtime` |
5679

57-
- The **library** (`:lib`) is pure protocol: envelope serialisation, runtime,
58-
client, transports, event log.
59-
- The **CLI** (`:cli`) is a thin picocli wrapper: `arcp serve|tail|send|replay`.
60-
- The **examples** (`:examples`) are runnable demo programs: minimal session,
61-
tool invocation with progress, human input, permission challenge, observer
62-
subscription, agent relay.
80+
## Layout
6381

64-
See [PLAN.md](./PLAN.md) for the design rationale, message-type to record map,
65-
state diagrams, open questions, and per-phase deliverables.
82+
```
83+
java-sdk/
84+
├── settings.gradle.kts
85+
├── build.gradle.kts
86+
├── gradle/libs.versions.toml
87+
├── arcp-core/
88+
├── arcp-client/
89+
├── arcp-runtime/
90+
├── arcp/ # umbrella
91+
├── arcp-runtime-jetty/
92+
├── arcp-otel/
93+
├── arcp-middleware-spring-boot/
94+
├── arcp-tck/
95+
├── docs/diagrams/ # 6 Graphviz diagrams (light + dark SVGs)
96+
└── examples/
97+
├── submit-and-stream/
98+
├── cancel/
99+
├── heartbeat/
100+
├── cost-budget/
101+
├── result-chunk/
102+
├── agent-versions/
103+
├── list-jobs/
104+
├── lease-expires-at/
105+
├── idempotent-retry/
106+
└── custom-auth/
107+
```
66108

67-
## Quickstart (Phase 0)
109+
## Build
68110

69111
```bash
70-
git clone <repo>
71-
cd arpc/java-sdk
72-
export JAVA_HOME=$(/usr/libexec/java_home -v 25)
73-
./gradlew check # green
74-
./gradlew :cli:run --args="" # prints arcp-java 0.1.0-SNAPSHOT
112+
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
113+
./gradlew build # compile + test all modules
114+
./gradlew :examples:submit-and-stream:run
115+
./gradlew :arcp-runtime-jetty:test
75116
```
76117

77-
End-to-end examples (`:examples:run01``:run06`) ship in Phase 7.
118+
## Features
119+
120+
- §5.1 envelope with `arcp: "1"` and `FAIL_ON_UNKNOWN_PROPERTIES=false`
121+
- §6.1 bearer auth via `BearerVerifier` SPI; `acceptAny` and `staticToken` helpers
122+
- §6.2 capability intersection with rich `agents` shape (name + versions + default)
123+
- §6.3 resume buffer (in-memory ring) and rotating `resume_token`
124+
- §6.4 heartbeats: scheduler-driven ping; client and runtime treat two missed
125+
intervals as `HEARTBEAT_LOST`
126+
- §6.5 `session.ack` with auto-emit rate limit on the client side
127+
- §6.6 `session.list_jobs` scoped to the session's principal
128+
- §7.1 `job.submit` with `lease_request`, `lease_constraints`, `idempotency_key`
129+
- §7.2 idempotency: identical `(principal, key, payload)` reuses the prior `job_id`;
130+
conflicting payload yields `DUPLICATE_KEY`
131+
- §7.4 cooperative cancellation via `JobContext.cancelled()` + `Thread.interrupt`
132+
- §7.5 agent versioning: `name@version` grammar; bare names resolve to advertised
133+
default; unknown versions surface `AGENT_VERSION_NOT_AVAILABLE`
134+
- §7.6 subscribe / unsubscribe with optional history replay; subscribers do not
135+
carry cancel authority
136+
- §8.2 ten event kinds via sealed `EventBody`, including `progress` (current ≥ 0)
137+
- §8.4 `result_chunk` reassembly via `ResultStream` (in-memory or `OutputStream` sink)
138+
- §9 lease grammar + subset check (`Lease.contains`); `LeaseGuard` enforces glob
139+
patterns with `*` and `**` semantics
140+
- §9.5 lease expiration: strict UTC-`Z` parsing; scheduled watchdog terminates
141+
jobs whose lease expires while running
142+
- §9.6 `cost.budget` via per-currency `AtomicReference<BigDecimal>` counters
143+
with `USE_BIG_DECIMAL_FOR_FLOATS` on the wire mapper
144+
- §11 OpenTelemetry trace propagation via `ArcpOtel.withTracing(transport, tracer)`;
145+
`arcp.session_id` / `arcp.job_id` / `arcp.trace_id` attributes on every span
146+
- §12 fifteen-code error taxonomy with sealed `ArcpException` /
147+
`RetryableArcpException` / `NonRetryableArcpException` split
148+
149+
## Concurrency
150+
151+
Virtual threads (JEP 444, stable in JDK 21) drive every per-job worker and
152+
every transport publisher. `StructuredTaskScope` is intentionally not used
153+
in published bytecode: it's preview in JDK 21 and finalized in JDK 25 with
154+
a different shape, and the SDK targets `--release 21`.
155+
156+
A single `ScheduledExecutorService` per runtime drives heartbeat ticks and
157+
lease expiry watchdogs; client-side, a similar scheduler emits `session.ack`
158+
and watches the inbound idle timer.
159+
160+
## Conformance
161+
162+
See [CONFORMANCE.md](CONFORMANCE.md) for the spec §-keyed table with file:line
163+
references. Tests at a glance:
164+
165+
- `arcp-core:test` — envelope round-trip, unknown-field tolerance, capability
166+
intersection, feature decode
167+
- `arcp-runtime:test` — agent version resolution, budget counters,
168+
lease guard, expiry, subset checks
169+
- `arcp-client:test` — smoke round-trip, idempotency reuse + conflict,
170+
subscribe with history replay, result-chunk reassembly
171+
- `arcp-otel:test` — outbound + inbound spans through `InMemorySpanExporter`
172+
- `arcp-runtime-jetty:test` — end-to-end client + runtime over loopback WebSocket
173+
- `arcp-middleware-spring-boot:test` — Spring Boot 3.x autoconfig + WebSocket
174+
handler driven from a `@SpringBootTest` with an embedded Tomcat
175+
- `arcp-tck:test` — seven dynamic conformance tests via JUnit `@TestFactory`,
176+
reusable by downstream JVM implementations
177+
178+
Diagrams under [`docs/diagrams/`](docs/diagrams/): module graph, session
179+
lifecycle, job lifecycle, capability negotiation, heartbeat + ack, result-chunk
180+
reassembly. Light + dark variants render via `make -C docs/diagrams`.
78181

79182
## License
80183

81-
Apache License 2.0 — see [`LICENSE`](LICENSE).
184+
[Apache-2.0](./LICENSE).

RFC-0001-v2.md

Lines changed: 0 additions & 7 deletions
This file was deleted.

arcp-client/build.gradle.kts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
plugins {
2+
`java-library`
3+
`maven-publish`
4+
}
5+
6+
dependencies {
7+
api(project(":arcp-core"))
8+
9+
testImplementation(project(":arcp-runtime"))
10+
testImplementation(libs.junit.jupiter)
11+
testRuntimeOnly(libs.junit.platform.launcher)
12+
testImplementation(libs.assertj)
13+
testImplementation(libs.awaitility)
14+
testRuntimeOnly(libs.slf4j.simple)
15+
}
16+
17+
publishing {
18+
publications {
19+
create<MavenPublication>("library") {
20+
from(components["java"])
21+
artifactId = "arcp-client"
22+
pom {
23+
name.set("arcp-client")
24+
description.set("ARCP client SDK.")
25+
licenses {
26+
license {
27+
name.set("Apache-2.0")
28+
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
29+
}
30+
}
31+
}
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)