Skip to content

Commit 0ee254f

Browse files
nficanoclaude
andcommitted
docs: align spec citations, paths, and stubs with the v1.1 workspace
Sweeps documentation drift surfaced by the spec-vs-SDK audit. No code behavior changes — only doc comments, markdown, and the changelog. - RFC section refs corrected to ARCP v1.1 throughout (§8→§6 sessions, §10→§7 jobs, §13→§7.6 subscribe, §15→§9 leases, §18→§12 errors, §22→§4 transport; §11.3/§17/§19/§21 had no v1.1 analog and are removed or re-anchored). SDK extensions beyond v1.1 (the challenge/authenticate auth flow, signed_jwt/none auth schemes, the x-… and arcpx.* extension namespaces, the artifact store, interrupt, Priority) are now flagged as such instead of pretending to cite a spec section. - Broken doc paths fixed: src/* → crates/<crate>/src/* across docs/architecture.md, docs/transports.md, docs/guides/errors.md, docs/guides/jobs.md. - docs/architecture.md and docs/README.md rewritten to describe the actual Cargo workspace (umbrella arcp + arcp-core/client/runtime + four reservation stubs) rather than the old "single arcp crate" layout; feature flag table gains client/runtime rows; persistence section notes runtime feature gating. - docs/getting-started.md, examples/README.md, README.md: bump the install snippet from arcp = "1.1" / "1" to "2"; soften the "runnable" claim on examples that elide setup with todo!(). - CHANGELOG.md gains a 2.0.0 entry covering the workspace split and the reservation stubs. - CONFORMANCE.md §6.6 row downgraded to Partial — the runtime implements list_jobs/job.subscribe but the client API does not yet expose them as first-class Session methods; the publish dry-run gate is updated to iterate the eight workspace crates. - Reservation stub crates (arcp-tower, arcp-axum, arcp-actix-web, arcp-otel) docs now explicitly state they ship no integration types and do not depend on tower/axum/actix-web/opentelemetry, so consumers don't install expecting middleware they don't get. - README license footer updated to MIT OR Apache-2.0 to match Cargo.toml; CONTRIBUTING WebSocket port matches the CLI default 127.0.0.1:7777. - docs/guides/job-events.md adds an explicit "spec §8.2 kind" column next to the SDK wire type column so readers can map between the spec's job.event kind enum and the SDK's top-level Job* variants. - README, CONTRIBUTING, and docs/guides/vendor-extensions.md flag the SDK's session.open / session.accepted as the wire serialization of the spec's §6.2 session.hello / session.welcome envelopes. - recipes/README.md is honest about the recipes not being wired as examples, and points readers at adapting the snippets. Spec-conformance findings that require API changes (rename SessionOpen → SessionHello, add resume_token / heartbeat_interval_sec to the welcome payload, restructure the top-level Job* variants into a kind-tagged JobEvent enum, lease expiration enforcement, credential rotation, JobState terminal set, etc.) are intentionally out of scope for this commit. The full audit is at audit-findings.json / audit-findings.md (kept untracked). Verified locally: cargo check --workspace --all-targets cargo clippy --workspace --all-targets -- -D warnings cargo fmt --all -- --check cargo test --workspace --doc Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Nick Ficano <nficano@gmail.com>
1 parent da4a3bc commit 0ee254f

49 files changed

Lines changed: 509 additions & 315 deletions

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: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,30 @@ 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+
The Rust SDK is a Cargo workspace; the version recorded here tracks
9+
`workspace.package.version` in [`Cargo.toml`](Cargo.toml) and applies to the
10+
co-released `arcp`, `arcp-core`, `arcp-client`, and `arcp-runtime` crates.
11+
The middleware reservation stubs (`arcp-tower`, `arcp-axum`,
12+
`arcp-actix-web`, `arcp-otel`) are versioned independently at
13+
`0.1.0-alpha.0`.
14+
15+
## [2.0.0] - 2026-05
16+
17+
### Changed
18+
19+
- Restructured the single `arcp` crate into a Cargo workspace ahead of 2.0
20+
publish: the umbrella `arcp` crate now re-exports `arcp-core` (wire types,
21+
IDs, transports, error taxonomy), `arcp-client` (`ARCPClient` + type-state
22+
`Session`), and `arcp-runtime` (`ARCPRuntime`, SQLite event log, JWT/bearer
23+
auth, `arcp` CLI). Direct consumers can pull individual crates to slim
24+
dependencies.
25+
26+
### Added
27+
28+
- Reservation stubs for forthcoming middleware: `arcp-tower`, `arcp-axum`,
29+
`arcp-actix-web`, `arcp-otel`. These crates publish at `0.1.0-alpha.0`
30+
and currently re-export `arcp-core` only.
31+
832
## [0.1.0] - 2026-05-10
933

1034
### Added

CONFORMANCE.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The docs mirror is [`docs/conformance.md`](./docs/conformance.md).
1414
| §6.3 Resume | Full | SQLite event log supports replay by session and sequence boundary; resumability examples exercise reconnect flows. |
1515
| §6.4 Heartbeat | Full | `session.ping` / `session.pong` messages and runtime examples are implemented. |
1616
| §6.5 Ack | Full | Runtime ack window and `session.ack` back-pressure are implemented. |
17-
| §6.6 List jobs / Subscribe | Full | `session.list_jobs`, `job.subscribe`, `job.unsubscribe`, and generic subscription fanout are implemented. |
17+
| §6.6 List jobs / Subscribe | Partial | Runtime: `session.list_jobs`, `job.subscribe`, `job.unsubscribe`, and generic subscription fanout are implemented. Client API does not yet expose `list_jobs`/`job.subscribe` as first-class `Session` methods. |
1818
| §7 Jobs | Full | Submit, accept, start, complete, fail, cancel, state inventory, and idempotent retry paths. |
1919
| §7.3 State machine | Full | `JobRegistry` tracks pending, running, and terminal states. |
2020
| §7.4 Cancellation | Full | Cooperative cancellation uses `CancellationToken` and emits cancelled terminal outcomes. |
@@ -47,10 +47,13 @@ Before release, run:
4747

4848
```sh
4949
cargo fmt --all -- --check
50-
cargo check --all-targets --all-features
51-
cargo test --all-features
52-
cargo clippy --all-targets --all-features -- -D warnings
53-
cargo publish --dry-run
50+
cargo check --workspace --all-targets --all-features
51+
cargo test --workspace --all-features
52+
cargo clippy --workspace --all-targets --all-features -- -D warnings
53+
# Publish dry-run iterates the workspace in dependency order:
54+
for crate in arcp-core arcp-client arcp-runtime arcp arcp-tower arcp-axum arcp-actix-web arcp-otel; do
55+
cargo publish --dry-run -p "$crate"
56+
done
5457
```
5558

5659
## Deferred Surfaces

CONTRIBUTING.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ Concretely:
3131
- **Don't invent wire behavior.** No envelope fields, event kinds, error codes,
3232
or feature flags that the spec doesn't define. If you need one, it's a spec
3333
proposal first.
34-
- **Negotiate honestly.** Only advertise a feature flag in `session.hello` once
35-
the SDK actually implements it. The feature matrix in the README must match
36-
what the code negotiates — a row marked `Supported` is a promise.
34+
- **Negotiate honestly.** Only advertise a feature flag in `SessionOpen` (the
35+
SDK's serialization of the spec's `session.hello`) once the SDK actually
36+
implements it. The feature matrix in the README must match what the code
37+
negotiates — a row marked `Supported` is a promise.
3738
- **Respect the semantics.** Sequence numbers stay gap-free and monotonic;
3839
`LEASE_EXPIRED` and `BUDGET_EXHAUSTED` stay non-retryable; the effective
3940
feature set is the intersection of client and runtime advertisements. Tests
@@ -85,8 +86,9 @@ Two layers must pass before a PR merges:
8586
error mapping) needs a test that exercises the real exchange, not a mock that
8687
assumes the answer. Integration tests under [`tests/`](tests/) drive the
8788
in-process runtime end to end; to point them at an out-of-process runtime,
88-
start one with `cargo run -- serve --bearer secret-token --principal alice@example.com`
89-
and connect the WebSocket transport at `ws://127.0.0.1:8765`. See
89+
start one with `cargo run --bin arcp -- serve --bearer secret-token --principal alice@example.com`
90+
and connect the WebSocket transport at `ws://127.0.0.1:7777` (the CLI default
91+
bind; pass `--bind 127.0.0.1:8765` to use a different port). See
9092
[`CONFORMANCE.md`](CONFORMANCE.md) for the section-by-section coverage matrix.
9193

9294
CI runs both on every PR. A PR that changes which feature flags the SDK

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<a href="https://github.com/agentruntimecontrolprotocol/rust-sdk/actions/workflows/test.yml"><img alt="CI" src="https://github.com/agentruntimecontrolprotocol/rust-sdk/actions/workflows/test.yml/badge.svg"></a>
77
<a href="https://codecov.io/gh/agentruntimecontrolprotocol/rust-sdk"><img alt="codecov" src="https://codecov.io/gh/agentruntimecontrolprotocol/rust-sdk/graph/badge.svg"></a>
88
<a href="https://github.com/agentruntimecontrolprotocol/spec/blob/main/docs/draft-arcp-1.1.md"><img alt="ARCP" src="https://img.shields.io/badge/ARCP-v1.1%20draft-blue"></a>
9-
<a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-lightgrey"></a>
9+
<a href="LICENSE-APACHE"><img alt="License" src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-lightgrey"></a>
1010
</p>
1111

1212
<p align="center">
@@ -123,7 +123,7 @@ This is the whole shape of the SDK: open a session, submit work, consume an orde
123123

124124
ARCP organizes everything around four concerns — **identity**, **durability**, **authority**, and **observability** — expressed through five core objects:
125125

126-
- **Session** — a connection between a client and a runtime. A session carries identity (a bearer token), negotiates a feature set in a `hello`/`welcome` handshake, and is *resumable*: if the transport drops, you reconnect with a resume token and the runtime replays buffered events. Jobs outlive the session that started them. See [§6](https://github.com/agentruntimecontrolprotocol/spec/blob/main/docs/draft-arcp-1.1.md).
126+
- **Session** — a connection between a client and a runtime. A session carries identity (a bearer token), negotiates a feature set in a hello/welcome handshake (the SDK serializes these as `SessionOpen`/`SessionAccepted`), and is *resumable*: if the transport drops, you reconnect with a resume token and the runtime replays buffered events. Jobs outlive the session that started them. See [§6](https://github.com/agentruntimecontrolprotocol/spec/blob/main/docs/draft-arcp-1.1.md).
127127
- **Job** — one unit of agent work submitted into a session. A job has an identity, an optional idempotency key, a resolved agent version, and a lifecycle that ends in exactly one terminal state: `success`, `error`, `cancelled`, or `timed_out`. See [§7](https://github.com/agentruntimecontrolprotocol/spec/blob/main/docs/draft-arcp-1.1.md).
128128
- **Event** — the ordered, session-scoped stream a job emits: logs, thoughts, tool calls and results, status, metrics, artifact references, progress, and streamed result chunks. Events carry strictly monotonic sequence numbers so the stream survives reconnects gap-free. See [§8](https://github.com/agentruntimecontrolprotocol/spec/blob/main/docs/draft-arcp-1.1.md).
129129
- **Lease** — the authority a job runs under, expressed as capability grants (`fs.read`, `fs.write`, `net.fetch`, `tool.call`, `agent.delegate`, `cost.budget`, `model.use`). The runtime enforces the lease at every operation boundary; a job can never act outside it. Leases may carry a budget and an expiry, and may be subset and handed to sub-agents via delegation. See [§9](https://github.com/agentruntimecontrolprotocol/spec/blob/main/docs/draft-arcp-1.1.md).
@@ -399,12 +399,12 @@ Full API reference — every type, method, and event payload — is in [`docs/`]
399399

400400
## Versioning and compatibility
401401

402-
This SDK speaks **ARCP v1.1 (draft)**. The SDK follows semantic versioning independently of the protocol; the protocol version it negotiates is shown above and in `session.hello`. A runtime advertising a different ARCP MAJOR is not guaranteed compatible. Feature mismatches degrade gracefully: the effective feature set is the intersection of what the client and runtime advertise, and the SDK will not use a feature outside it.
402+
This SDK speaks **ARCP v1.1 (draft)**. The SDK follows semantic versioning independently of the protocol; the protocol version it negotiates is shown above and in the `SessionOpen` envelope (which the spec names `session.hello`). A runtime advertising a different ARCP MAJOR is not guaranteed compatible. Feature mismatches degrade gracefully: the effective feature set is the intersection of what the client and runtime advertise, and the SDK will not use a feature outside it.
403403

404404
## Contributing
405405

406406
See [`CONTRIBUTING.md`](CONTRIBUTING.md). Protocol questions and proposed changes belong in the [spec repository](https://github.com/agentruntimecontrolprotocol/spec); SDK bugs and feature requests belong here.
407407

408408
## License
409409

410-
Apache-2.0 — see [`LICENSE`](LICENSE).
410+
Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option.

crates/arcp-actix-web/src/lib.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
//! # arcp-actix-web
22
//!
3-
//! actix-web integration for the Agent Runtime Control Protocol (ARCP).
3+
//! Name reservation for a planned actix-web integration. **This crate
4+
//! currently provides no actix types**; it does not depend on `actix-web`.
5+
//! It only re-exports [`arcp_core`] so dependents can prepare imports
6+
//! against a stable crate name.
47
//!
5-
//! ## Status: placeholder
6-
//!
7-
//! This crate is published as a name reservation. A real actix-web
8-
//! integration — handler factory, WebSocket upgrade, and `ARCPRuntime`
9-
//! adapter — is planned for a future minor release. The current version
10-
//! re-exports [`arcp_core`] so dependents can prepare imports.
11-
//!
12-
//! Follow <https://github.com/agentruntimecontrolprotocol/rust-sdk> for
13-
//! progress.
8+
//! A real actix-web integration — handler factory, WebSocket upgrade, and
9+
//! `ARCPRuntime` adapter — is planned for a future minor release. Follow
10+
//! <https://github.com/agentruntimecontrolprotocol/rust-sdk> for progress.
1411
1512
#![deny(unsafe_code)]
1613
#![deny(missing_docs)]

crates/arcp-axum/src/lib.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
//! # arcp-axum
22
//!
3-
//! axum integration for the Agent Runtime Control Protocol (ARCP).
3+
//! Name reservation for a planned axum integration. **This crate currently
4+
//! provides no axum types**; it does not depend on `axum`. It only
5+
//! re-exports [`arcp_core`] so dependents can prepare imports against a
6+
//! stable crate name.
47
//!
5-
//! ## Status: placeholder
6-
//!
7-
//! This crate is published as a name reservation. A real axum integration
8-
//! — Router, WebSocket upgrade handler, and `ARCPRuntime` extractor — is
9-
//! planned for a future minor release. The current version re-exports
10-
//! [`arcp_core`] so dependents can prepare imports.
11-
//!
12-
//! In the meantime, an end-to-end axum + ARCP server example lives at
13-
//! [`examples/axum_server.rs`][example] in the umbrella crate.
8+
//! A real axum integration — Router, WebSocket upgrade handler, and
9+
//! `ARCPRuntime` extractor — is planned for a future minor release. Until
10+
//! then, see [`crates/arcp/examples/axum_server.rs`][example] in the
11+
//! umbrella crate for a hand-rolled axum-plus-ARCP pattern that uses
12+
//! `axum` directly rather than anything in this crate.
1413
//!
1514
//! [example]: https://github.com/agentruntimecontrolprotocol/rust-sdk/blob/main/crates/arcp/examples/axum_server.rs
1615

crates/arcp-client/src/api.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
//! `ARCPClient` and the type-state [`Session<S>`] (RFC §4.6, §8).
1+
//! `ARCPClient` and the type-state [`Session<S>`].
2+
//!
3+
//! Implements the client side of the ARCP v1.1 §6.2 hello/welcome handshake
4+
//! (serialized as `session.open` / `session.accepted`) and §7 job lifecycle
5+
//! over an `arcp-core` [`Transport`][arcp_core::transport::Transport].
26
37
use std::marker::PhantomData;
48
use std::sync::Arc;
@@ -103,7 +107,10 @@ impl<S: sealed::State, T: Transport + 'static> std::fmt::Debug for Session<S, T>
103107
}
104108

105109
impl<T: Transport + 'static> Session<Unauthenticated, T> {
106-
/// Drive the four-step handshake (RFC §8.1) and, on success, return a
110+
/// Drive the ARCP v1.1 §6.2 hello/welcome handshake (serialized by the
111+
/// SDK as `session.open` / `session.accepted`, with an optional
112+
/// SDK-extension challenge / authenticate pair between them when the
113+
/// configured authenticator requests it) and, on success, return a
107114
/// [`Session<Authenticated>`].
108115
///
109116
/// On success a background reader task is spawned to dispatch incoming
@@ -362,7 +369,7 @@ impl<T: Transport + 'static> Session<Authenticated, T> {
362369

363370
/// Invoke a tool by name. Returns a [`JobHandle`] the caller can await
364371
/// for the terminal result, and which carries the runtime-assigned
365-
/// [`JobId`] once `job.accepted` arrives (RFC §10).
372+
/// [`JobId`] once `job.accepted` arrives (ARCP v1.1 §7).
366373
///
367374
/// # Errors
368375
///
@@ -421,7 +428,9 @@ impl<T: Transport + 'static> Session<Authenticated, T> {
421428
})
422429
}
423430

424-
/// Upload an artifact (RFC §16.2). Returns the canonical
431+
/// Upload an artifact (SDK extension; ARCP v1.1 §8.2 defines an
432+
/// `artifact_ref` event kind but no `artifact.*` envelope surface).
433+
/// Returns the canonical
425434
/// [`ArtifactRef`] the runtime minted.
426435
///
427436
/// `data` must be base64-encoded; the caller is responsible for
@@ -507,7 +516,8 @@ impl<T: Transport + 'static> Session<Authenticated, T> {
507516
}
508517
}
509518

510-
/// Release (delete) an artifact (RFC §16.2). The runtime does not
519+
/// Release (delete) an artifact (SDK extension; see the `put_artifact`
520+
/// note above). The runtime does not
511521
/// acknowledge releases; this is fire-and-forget.
512522
///
513523
/// # Errors
@@ -522,8 +532,11 @@ impl<T: Transport + 'static> Session<Authenticated, T> {
522532
self.inner.transport.send(env).await
523533
}
524534

525-
/// Subscribe to runtime events (RFC §13). Returns a
526-
/// [`SubscriptionHandle`] yielding live envelopes that match `filter`.
535+
/// Subscribe to runtime events via the SDK's generic filtered subscription
536+
/// bus. (For per-job subscription as defined by ARCP v1.1 §7.6, see
537+
/// `JobSubscribePayload`; that surface is not yet exposed as a first-class
538+
/// `Session` method.) Returns a [`SubscriptionHandle`] yielding live
539+
/// envelopes that match `filter`.
527540
///
528541
/// # Errors
529542
///
@@ -568,7 +581,8 @@ impl<T: Transport + 'static> Session<Authenticated, T> {
568581
}
569582
}
570583

571-
/// Handle to a live subscription (RFC §13).
584+
/// Handle to a live subscription (see the SDK's generic subscription bus;
585+
/// per-job subscription is ARCP v1.1 §7.6).
572586
///
573587
/// Dropping the handle removes the client-side forwarder and stops local
574588
/// delivery; it does **not** send an `unsubscribe` envelope. Call
@@ -639,7 +653,7 @@ fn map_nack(p: NackPayload) -> ARCPError {
639653
}
640654
}
641655

642-
/// Handle to an in-flight job (RFC §10).
656+
/// Handle to an in-flight job (ARCP v1.1 §7).
643657
pub struct JobHandle {
644658
/// Server-assigned job identifier.
645659
pub job_id: JobId,

crates/arcp-client/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
//!
33
//! Ships [`ARCPClient`] and the type-state [`Session`] for opening,
44
//! authenticating, and driving a session over any
5-
//! [`Transport`][arcp_core::transport::Transport]. Job, stream, and
6-
//! subscription handles hang off `Session<Authenticated>`.
5+
//! [`Transport`][arcp_core::transport::Transport]. Job and subscription
6+
//! handles hang off `Session<Authenticated>`; raw streams are surfaced via
7+
//! subscription events rather than a dedicated stream handle.
78
//!
89
//! Wire-format types are re-exported from `arcp-core` for ergonomics; most
910
//! users should pull in the umbrella `arcp` crate which bundles client +

crates/arcp-core/src/auth/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
//! Authentication scheme adapters (RFC §8.2).
1+
//! Authentication scheme adapters.
22
//!
3-
//! Each [`Authenticator`] implementation validates one auth scheme. The
4-
//! runtime composes these into an [`AuthRegistry`]; on `session.open` the
3+
//! ARCP v1.1 §6.1 collapses authentication to a single bearer token carried
4+
//! in `session.hello.payload.auth.token` (the SDK serializes this envelope as
5+
//! `session.open`). The [`Authenticator`] trait is an SDK extension that
6+
//! lets a runtime support additional schemes (`signed_jwt`, `none`, etc.) —
7+
//! including a legacy challenge / response flow not described by v1.1 — by
8+
//! composing implementations into an [`AuthRegistry`]; on `session.open` the
59
//! runtime dispatches by [`AuthScheme`] and either accepts directly or
610
//! issues a [`session.challenge`][crate::messages::SessionChallengePayload].
11+
//! Bearer is the only scheme normative under v1.1; the others are SDK
12+
//! extensions outside the spec surface.
713
814
use std::collections::HashMap;
915

0 commit comments

Comments
 (0)