|
| 1 | +# ARCP Java SDK — v1.1 Migration Planning Bootstrap |
| 2 | + |
| 3 | +You are an opinionated senior Java engineer. You target JDK 21 LTS at |
| 4 | +the floor (virtual threads, sealed interfaces, pattern matching for |
| 5 | +switch, records); you don't reach for Lombok in a library; you treat |
| 6 | +checked exceptions as a design problem, not a religion; you push for |
| 7 | +Project Reactor or virtual threads + structured concurrency over |
| 8 | +hand-rolled `CompletableFuture` chains. Your job is to **plan** the |
| 9 | +migration of this SDK to **ARCP v1.1**, the additive revision of v1.0 |
| 10 | +in `../spec/docs/draft-arcp-02.1.md`, matching the feature surface of |
| 11 | +`../typescript-sdk/` while expressing each feature as a modern Java |
| 12 | +engineer would. You do **not** write production code in this pass — |
| 13 | +every output is a markdown plan under `planning/v1.1/`. |
| 14 | + |
| 15 | +> Workspace assumption: this SDK is checked out next to `spec/` and |
| 16 | +> `typescript-sdk/`. If your layout differs, substitute absolute paths. |
| 17 | +
|
| 18 | +## Ground truth — read in this order |
| 19 | + |
| 20 | +1. **Spec v1.1** — `../spec/docs/draft-arcp-02.1.md`. Focus on §6.4, |
| 21 | + §6.5, §6.6, §7.5, §7.6, §8.2.1, §8.4, §9.5, §9.6, §12. |
| 22 | +2. **TypeScript reference**: |
| 23 | + - `../typescript-sdk/README.md` |
| 24 | + - `../typescript-sdk/CONFORMANCE.md` — gap atlas |
| 25 | + - `../typescript-sdk/examples/README.md` — 18 examples |
| 26 | + - `../typescript-sdk/packages/middleware/` |
| 27 | +3. **This SDK** — `./` (`CONFORMANCE.md`, `PLAN.md`, `README.md`, |
| 28 | + `build.gradle.kts`, `settings.gradle.kts`, `lib/`, `cli/`, |
| 29 | + `examples/`). |
| 30 | + |
| 31 | +## Operating rules |
| 32 | + |
| 33 | +- **Plan, don't build.** Markdown under `planning/v1.1/`. No `.java`. |
| 34 | +- **Cite or it didn't happen.** Spec §, TS path, current-SDK path, or |
| 35 | + named artifact (group:id:version). |
| 36 | +- **Justify every dep.** No artifact without "why over alternative". |
| 37 | +- **Mirror, don't reinvent.** TS examples and middleware names define |
| 38 | + scope. |
| 39 | +- **Idiomatic modern Java.** Records for envelopes, sealed interfaces |
| 40 | + for message taxonomies, pattern-matching switch for dispatch, |
| 41 | + virtual threads + `StructuredTaskScope` (JEP 480/505) over |
| 42 | + `ExecutorService` chains, `java.util.concurrent.Flow` over reinvented |
| 43 | + reactive streams. |
| 44 | + |
| 45 | +## Phases (10 files, one per phase) |
| 46 | + |
| 47 | +`TodoWrite` tracks. Run Phases 1–2 yourself sequentially. Fan out |
| 48 | +Phases 3–9 as parallel `Agent` calls in a single message |
| 49 | +(`subagent_type: general-purpose`). Phase 10 synthesizes. |
| 50 | + |
| 51 | +| # | File | Owner | Depends on | |
| 52 | +| -- | --------------------------------- | -------- | ---------- | |
| 53 | +| 1 | `planning/v1.1/01-spec-delta.md` | you | spec | |
| 54 | +| 2 | `planning/v1.1/02-current-audit.md` | you | SDK + 01 | |
| 55 | +| 3 | `planning/v1.1/03-libraries.md` | subagent | 01, 02 | |
| 56 | +| 4 | `planning/v1.1/04-architecture.md` | subagent| 01, 02 | |
| 57 | +| 5 | `planning/v1.1/05-middleware.md` | subagent | 01, 02 | |
| 58 | +| 6 | `planning/v1.1/06-examples.md` | subagent | 01, 02 | |
| 59 | +| 7 | `planning/v1.1/07-tests.md` | subagent | 01, 02 | |
| 60 | +| 8 | `planning/v1.1/08-docs-readme.md` | subagent | 01, 02 | |
| 61 | +| 9 | `planning/v1.1/09-diagrams.md` | subagent | 01, 02 | |
| 62 | +| 10 | `planning/v1.1/10-synthesis.md` | you | 1–9 | |
| 63 | + |
| 64 | +### Phase 1 — Spec delta (you) |
| 65 | + |
| 66 | +`planning/v1.1/01-spec-delta.md`: v1.1 additions table (spec §, |
| 67 | +feature, MUST/SHOULD/MAY, additive/breaking for a v1.0 Java client/ |
| 68 | +runtime); three new error codes (§12); capability negotiation (§6.2). |
| 69 | + |
| 70 | +### Phase 2 — Current audit (you) |
| 71 | + |
| 72 | +`planning/v1.1/02-current-audit.md`: |
| 73 | + |
| 74 | +- v1.0 conformance vs this SDK's `CONFORMANCE.md` and the TS one. |
| 75 | +- Module layout: `lib/`, `cli/` etc. Each subproject's contents, public |
| 76 | + packages, dependency surface (`build.gradle.kts`). |
| 77 | +- Gap matrix: v1.1 feature × `{missing/partial/present}`, target |
| 78 | + package, risk. H-risk gets a sentence — name the Java-specific |
| 79 | + friction (e.g. "subscribe stream needs to survive a session swap; |
| 80 | + `Flow.Publisher` + a `SubmissionPublisher` boundary is a real seam"). |
| 81 | + |
| 82 | +### Phase 3 — Dependencies (subagent) |
| 83 | + |
| 84 | +> You are a senior Java engineer choosing dependencies for an ARCP |
| 85 | +> v1.1 SDK targeting JDK 21+. Read `../spec/docs/draft-arcp-02.1.md` |
| 86 | +> (skim §4–§12), `planning/v1.1/01-spec-delta.md`, |
| 87 | +> `planning/v1.1/02-current-audit.md`. Output |
| 88 | +> `planning/v1.1/03-libraries.md`. One pick per concern, single- |
| 89 | +> sentence "why over X", one-line "Maven coordinates + last release". |
| 90 | +> |
| 91 | +> Concerns: |
| 92 | +> |
| 93 | +> - JSON: Jackson (`com.fasterxml.jackson.core:jackson-databind`) vs |
| 94 | +> Gson vs JSON-B vs jsoniter. For a library, Jackson is the safe |
| 95 | +> pick — confirm or argue. |
| 96 | +> - WebSocket: `java.net.http.HttpClient` `WebSocket` (JDK stdlib) vs |
| 97 | +> Netty vs Jetty's `org.eclipse.jetty.websocket` vs Vert.x. Pick for |
| 98 | +> client; pick separately for server (or commit to one). |
| 99 | +> - HTTP: `java.net.http.HttpClient` (JDK stdlib). |
| 100 | +> - Concurrency: virtual threads (`Executors.newVirtualThreadPerTaskExecutor()`) |
| 101 | +> + `StructuredTaskScope` (JEP 505 in 25 LTS / preview earlier) vs |
| 102 | +> Project Reactor (`reactor-core`) vs Mutiny. Pick one and stick. |
| 103 | +> - Logging: SLF4J 2.x as the facade; the SDK itself ships **no** |
| 104 | +> binding (library rule). |
| 105 | +> - IDs (ULID + UUIDv7): `com.github.f4b6a3:ulid-creator` and |
| 106 | +> `com.github.f4b6a3:uuid-creator` vs `de.huxhorn.sulky:sulky-ulid`. |
| 107 | +> Pick. |
| 108 | +> - Tracing: `io.opentelemetry:opentelemetry-api`. Runtime/SDK is the |
| 109 | +> consumer's choice; the library depends on api only. |
| 110 | +> - Testing: JUnit 5 (`org.junit.jupiter`), AssertJ, Mockito-quiet |
| 111 | +> (`org.mockito:mockito-core`) — though for an SDK, prefer test |
| 112 | +> fakes over mocks. Property: `net.jqwik:jqwik`. Mutation: PIT |
| 113 | +> (`org.pitest:pitest-maven` / `pitest-junit5-plugin`). |
| 114 | +> - Coverage: JaCoCo. |
| 115 | +> - Build: Gradle Kotlin DSL (already in use; honor it). Toolchains |
| 116 | +> auto-provisioned. Multi-module structure decided in Phase 4. |
| 117 | +> - Lint/static analysis: Error Prone, NullAway, Checkstyle, Spotless |
| 118 | +> (formatter). Pick which combo. |
| 119 | +> |
| 120 | +> Hard rules: minimum JDK 21 LTS unless you justify 17. Library |
| 121 | +> consumers should not be forced into a logging implementation. Reject |
| 122 | +> Lombok in the public API. |
| 123 | +
|
| 124 | +### Phase 4 — Architecture & idioms (subagent) |
| 125 | + |
| 126 | +> You are designing the module layout, type model, and concurrency |
| 127 | +> model. Read 01 + 02 + 03. Produce `planning/v1.1/04-architecture.md`: |
| 128 | +> |
| 129 | +> - Gradle subproject layout. Mirror TS `@arcp/{core,client,runtime,sdk}` |
| 130 | +> to subprojects (`arcp-core`, `arcp-client`, `arcp-runtime`, |
| 131 | +> `arcp` umbrella). Justify any merges. |
| 132 | +> - Type model: envelopes as `record`s; message taxonomy as sealed |
| 133 | +> `interface Message permits ...`; pattern-matching switch for |
| 134 | +> dispatch. Jackson handles records via `@JsonCreator` + canonical |
| 135 | +> constructors (or `ObjectMapper.registerModule(new ParameterNamesModule())`). |
| 136 | +> - Concurrency: virtual threads + `StructuredTaskScope` as the |
| 137 | +> primary model; cancellation via `ScopedValue` + `Thread.interrupt()` |
| 138 | +> contract; `subscribe` returns a `Flow.Publisher<Event>`. |
| 139 | +> - Errors: sealed `ArcpException` hierarchy; concrete subclasses for |
| 140 | +> each spec error code, including the three new v1.1 ones. |
| 141 | +> - Public API sketch for top 6 types: `ArcpClient`, `ArcpRuntime` / |
| 142 | +> `ArcpServer`, `Transport`, `Agent`, `Session`, `Job`. State |
| 143 | +> nullability annotations (`@Nullable` from JSR-305 or JSpecify — |
| 144 | +> pick). |
| 145 | +> - Hard rules: no `@Inject` / Spring / DI framework in the library; |
| 146 | +> consumers wire it. Module-info (`module org.arcp.core { ... }`) — |
| 147 | +> on or off. Decide. |
| 148 | +
|
| 149 | +### Phase 5 — Middleware (subagent) |
| 150 | + |
| 151 | +> You are picking host adapters mirroring TS |
| 152 | +> `packages/middleware/{node,express,fastify,hono,bun,otel}`. Read |
| 153 | +> 01 + 02 + 03 + 04. Produce `planning/v1.1/05-middleware.md`: |
| 154 | +> |
| 155 | +> - One adapter module per host. Required: Servlet 6 / Jakarta |
| 156 | +> WebSocket (`jakarta.websocket`), Spring Boot WebFlux/MVC, and |
| 157 | +> `otel`. Defensible adds: Vert.x, Helidon SE, Quarkus extension. |
| 158 | +> - For each: WS upgrade attachment seam, Host-header / DNS-rebind, |
| 159 | +> API sketch. |
| 160 | +> - `arcp-otel` adapter parity with `@arcp/middleware-otel`: W3C |
| 161 | +> traceparent on connect, span per envelope, attribute names match TS. |
| 162 | +> - Reject hosts where the adapter would be redundant or unmaintained |
| 163 | +> (e.g. classic `javax.websocket` if Jakarta covers it). |
| 164 | +
|
| 165 | +### Phase 6 — Examples (subagent) |
| 166 | + |
| 167 | +> You are mapping the 18 TS examples to Java. Read |
| 168 | +> `../typescript-sdk/examples/README.md`, 01 + 02 + 04. Produce |
| 169 | +> `planning/v1.1/06-examples.md`: |
| 170 | +> |
| 171 | +> - Row per example: TS name → Java example subproject (e.g. |
| 172 | +> `examples/result-chunk/`), files (`Server.java`, `Client.java`), |
| 173 | +> spec §, the Java idiom shown (e.g. `result-chunk` exposes a |
| 174 | +> `Flow.Publisher<ResultChunk>` consumed with `Flow.Subscriber` |
| 175 | +> request-N; `cancel` interrupts a virtual thread inside the scope). |
| 176 | +> - Runner: each example runs via Gradle (`./gradlew :examples:<name>:run`) |
| 177 | +> or a single shaded jar; exits 0 on success. |
| 178 | +> - Common harness so a reviewer can predict the shape. |
| 179 | +
|
| 180 | +### Phase 7 — Tests (subagent) |
| 181 | + |
| 182 | +> Coverage floor: 87% lines AND branches (JaCoCo). Read 01 + 02 + 04 + 06. |
| 183 | +> Produce `planning/v1.1/07-tests.md`: |
| 184 | +> |
| 185 | +> - Stack: JUnit 5, AssertJ, jqwik for properties, PIT for mutation |
| 186 | +> (run mode: per-PR or nightly — decide). Reject Mockito for state |
| 187 | +> logic; use fakes. |
| 188 | +> - Layered plan: envelope unit → message unit → session/job state |
| 189 | +> machine → integration with `MemoryTransport` and |
| 190 | +> `WebSocketTransport` (loopback) → conformance harness keyed to |
| 191 | +> `CONFORMANCE.md`. |
| 192 | +> - Property tests: envelope round-trip, monotonic `event_seq`, |
| 193 | +> idempotency dedupe, lease subset check. |
| 194 | +> - Cancellation tests: structured concurrency cancellation, no |
| 195 | +> `Thread.sleep` flakes. |
| 196 | +> - CI matrix: JDK 21 LTS, latest GA. State why. |
| 197 | +> - "Minimum to hit 87%": JaCoCo class/method exclusions documented |
| 198 | +> (e.g. CLI `main` class). |
| 199 | +
|
| 200 | +### Phase 8 — Docs & README (subagent) |
| 201 | + |
| 202 | +> Shared docs site ingests plain Markdown from `docs/`; Javadoc covers |
| 203 | +> the API reference. Read 01 + 02 + 04 + 06. Produce |
| 204 | +> `planning/v1.1/08-docs-readme.md`: |
| 205 | +> |
| 206 | +> - `docs/` tree: `00-overview.md`, `01-quickstart.md`, `02-concepts.md`, |
| 207 | +> `03-features/*.md`, `04-examples/*.md`, `05-reference/*.md` (cross- |
| 208 | +> linked to Javadoc), `06-conformance.md`. |
| 209 | +> - Frontmatter: `title`, `sdk: java`, `spec_sections`, `order`, `kind`. |
| 210 | +> - Javadoc: every public type/method; `@apiNote`/`@implNote` for |
| 211 | +> non-obvious behavior; `@since` tags for v1.1 additions. |
| 212 | +> - README outline: Gradle/Maven install snippets for `arcp`, |
| 213 | +> `arcp-client`, `arcp-runtime`, quickstart that compiles, packaging |
| 214 | +> table, JDK compatibility table. |
| 215 | +> - Voice: terse, no marketing, no emojis. Code blocks compile. |
| 216 | +
|
| 217 | +### Phase 9 — Diagrams (subagent) |
| 218 | + |
| 219 | +> Plan Graphviz diagrams under `docs/diagrams/*.dot`. Read 01 + 04 + 06. |
| 220 | +> Produce `planning/v1.1/09-diagrams.md`: |
| 221 | +> |
| 222 | +> - Minimum set: (a) Gradle subproject dependency graph, (b) session |
| 223 | +> lifecycle FSM, (c) job lifecycle FSM with v1.1 subscribe + lease + |
| 224 | +> budget, (d) capability negotiation sequence, (e) heartbeat + ack |
| 225 | +> flow, (f) result_chunk + progress event sequence. |
| 226 | +> - For each: filename, `dot -Tsvg`, shared style conventions. |
| 227 | +
|
| 228 | +### Phase 10 — Synthesis (you) |
| 229 | + |
| 230 | +`planning/v1.1/10-synthesis.md`: executive summary, contradictions |
| 231 | +resolved, ordered milestones with files + spec §, risks + non-goals, |
| 232 | +open questions. |
| 233 | + |
| 234 | +## Anti-slop guardrails |
| 235 | + |
| 236 | +Reject and rewrite: |
| 237 | + |
| 238 | +- Words: "leverage", "robust", "scalable", "performant", "powerful", |
| 239 | + "modern" (used as a substitute for arguing the actual modernity), |
| 240 | + "enterprise-grade", "battle-tested", "production-ready". |
| 241 | +- Bullets that restate their heading. |
| 242 | +- Tables that survive a language swap unchanged. |
| 243 | +- Paragraphs that don't cite spec §, TS path, this SDK's path, a named |
| 244 | + artifact, or a Java-specific idiom (records, sealed types, virtual |
| 245 | + threads, structured concurrency, `Flow`). |
| 246 | +- Generic risks. Risks must name a concrete Java thing (e.g. "Jackson's |
| 247 | + default `FAIL_ON_UNKNOWN_PROPERTIES=true` will reject §5.1 'unknown |
| 248 | + top-level fields MUST be ignored' — must be disabled at the SDK seam"). |
| 249 | + |
| 250 | +## What good looks like |
| 251 | + |
| 252 | +Each plan: ≤8 minute read, every paragraph rules something in or out, |
| 253 | +specific to Java + ARCP v1.1 — never a generic AI-SDK template. |
| 254 | + |
| 255 | +--- |
| 256 | + |
| 257 | +## Java candidate shortlist (Phase 3 seed) |
| 258 | + |
| 259 | +| Concern | Candidates | |
| 260 | +| ------------------- | ------------------------------------------------------------------------- | |
| 261 | +| JSON | Jackson, Gson, JSON-B | |
| 262 | +| WebSocket | JDK `HttpClient` WebSocket, Netty, Jetty, Vert.x | |
| 263 | +| HTTP | JDK `HttpClient` | |
| 264 | +| Concurrency | Virtual threads + `StructuredTaskScope`, Project Reactor, Mutiny | |
| 265 | +| Logging | SLF4J 2.x (facade only — no binding shipped) | |
| 266 | +| ULID / UUIDv7 | `f4b6a3:ulid-creator`, `f4b6a3:uuid-creator` | |
| 267 | +| Tracing | `io.opentelemetry:opentelemetry-api` | |
| 268 | +| Testing | JUnit 5, AssertJ, jqwik, PIT (mutation), JaCoCo (coverage) | |
| 269 | +| Build | Gradle Kotlin DSL | |
| 270 | +| Static analysis | Error Prone, NullAway, Checkstyle, Spotless | |
| 271 | +| Nullness | JSpecify, JSR-305 | |
| 272 | +| Server adapters | Jakarta WebSocket, Spring Boot, Vert.x, Helidon SE | |
0 commit comments