-
Notifications
You must be signed in to change notification settings - Fork 3
feat(acp): catch up to the current ACP spec and make drift observable #477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
1b54771
chore(acp): establish spec conformance tracking foundation
yordis ee6e7ff
feat(acp-nats): stop dropping additionalDirectories and unstable capa…
yordis fcd99d6
feat(acp-nats)!: migrate to agent-client-protocol 1.2 with bridge-own…
yordis 0db8187
feat(acp-nats-agent)!: dispatch runner traffic through the bridge-own…
yordis ead731c
feat(acp)!: adapt byte-stream boundaries to SDK 1.2 builder connections
yordis 0548ca5
feat(acp): route session/delete and honor request cancellation end to…
yordis fd9d631
feat(acp): adopt elicitation, providers routing, and MCP-over-ACP pay…
yordis 8edf750
chore(acp): drop the working plan file
yordis 445b725
docs(acp): point plan references at durable artifacts
yordis 01f70c0
refactor(acp-nats): name the boundary handlers
yordis aa3f3d0
refactor(ci): extract the ACP freshness check into a mise task
yordis 72c2e9d
Merge branch 'main' into yordis/check-acp-protocol-version
yordis ab4c4fe
refactor(ci): move drift issue filing into the acp-freshness mise task
yordis 6d92479
feat(dylint): forbid function-local macro_rules and fix the boundary …
yordis f0cfb55
test(acp): satisfy the coverage gate and typed-error lint
yordis 7cfd09d
test(acp-nats): finish covering the new boundary and routing surface
yordis 831020b
style(acp-nats): hoist test imports to module level
yordis 0f8c435
refactor(acp-nats): address review findings on elicitation errors and…
yordis 091a78a
fix(acp-nats): ignore zero-length reads in the EOF signal reader
yordis 22c5976
fix(acp): abort connection tasks when the transport closes
yordis 3616174
fix(ci): box the a2a dispatch error frame and reach the mcp fallthrou…
yordis 672530d
test(acp-nats): make boundary fallthrough coverage deterministic
yordis 270f941
test(acp-nats): hit the request catch-all with a decodable enum variant
yordis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| #!/usr/bin/env bash | ||
| #MISE description="Compare the pinned agent-client-protocol SDK and bundled schema against crates.io latest; set ACP_FRESHNESS_FILE_ISSUE=true to file a drift issue" | ||
| set -euo pipefail | ||
|
|
||
| root="$(cd "$(dirname "$0")/../../.." && pwd)" | ||
|
|
||
| crates_io() { | ||
| curl -sf --retry 3 -A "trogonai-acp-freshness" "https://crates.io/api/v1/crates/$1" | | ||
| jq -r '.crate.max_stable_version // .crate.max_version' | ||
| } | ||
|
|
||
| pinned="$(grep -oE 'agent-client-protocol = \{ version = "=?[0-9]+\.[0-9]+\.[0-9]+"' "$root/rsworkspace/Cargo.toml" | | ||
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)" | ||
| if [[ -z "$pinned" ]]; then | ||
| echo "Could not find pinned agent-client-protocol version in rsworkspace/Cargo.toml" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| bundled_schema="$(grep -A2 'name = "agent-client-protocol-schema"' "$root/rsworkspace/Cargo.lock" | | ||
| grep -oE 'version = "[0-9]+\.[0-9]+\.[0-9]+"' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)" | ||
|
|
||
| latest_sdk="$(crates_io agent-client-protocol)" | ||
| latest_schema="$(crates_io agent-client-protocol-schema)" | ||
|
|
||
| drift=false | ||
| if [[ "$pinned" != "$latest_sdk" || "${bundled_schema:-unknown}" != "$latest_schema" ]]; then | ||
| drift=true | ||
| fi | ||
|
|
||
| echo "ACP freshness:" | ||
| echo " SDK pinned=$pinned latest=$latest_sdk" | ||
| echo " schema bundled=${bundled_schema:-unknown} latest=$latest_schema" | ||
| echo " drift=$drift" | ||
|
|
||
| if [[ -n "${GITHUB_OUTPUT:-}" ]]; then | ||
| { | ||
| echo "pinned=$pinned" | ||
| echo "latest_sdk=$latest_sdk" | ||
| echo "bundled_schema=${bundled_schema:-unknown}" | ||
| echo "latest_schema=$latest_schema" | ||
| echo "drift=$drift" | ||
| } >>"$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| if [[ "$drift" != "true" || "${ACP_FRESHNESS_FILE_ISSUE:-}" != "true" ]]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| title="ACP drift: agent-client-protocol $pinned is behind $latest_sdk" | ||
| body_file="$(mktemp)" | ||
| trap 'rm -f "$body_file"' EXIT | ||
| cat >"$body_file" <<EOF | ||
| The pinned \`agent-client-protocol\` version has fallen behind crates.io. | ||
|
|
||
| | | pinned | latest | | ||
| | --- | --- | --- | | ||
| | SDK (\`agent-client-protocol\`) | $pinned | $latest_sdk | | ||
| | Schema (\`agent-client-protocol-schema\`) | ${bundled_schema:-unknown} | $latest_schema | | ||
|
|
||
| A version bump is never just a version change. Per the upgrade ritual in \`docs/architecture/acp-conformance.md\`, the bump PR must: | ||
|
|
||
| - [ ] Diff the schema changelog between the pinned and latest versions: https://github.com/agentclientprotocol/agent-client-protocol/blob/main/CHANGELOG.md | ||
| - [ ] For each added or stabilized method: add subject mapping in \`acp-nats/src/nats/parsing.rs\`, a handler, and tests, or a conformance matrix row with opt-out rationale | ||
| - [ ] For each added field or \`session/update\` variant: add a round-trip test through the bridge (typed re-encode silently drops unmapped fields) | ||
| - [ ] For each new unstable flag: enable it per the opt-in policy and wire it | ||
| - [ ] Update \`docs/architecture/acp-conformance.md\` (matrix and spec position) in the same PR | ||
|
|
||
| This issue is filed automatically by \`.github/workflows/acp-freshness.yml\` and updated on re-runs. | ||
| EOF | ||
|
|
||
| existing="$(gh issue list --state open --search 'in:title "ACP drift:"' --json number --jq '.[0].number // empty')" | ||
| if [[ -n "$existing" ]]; then | ||
| gh issue edit "$existing" --title "$title" --body-file "$body_file" | ||
| echo "Updated issue #$existing" | ||
| else | ||
| gh issue create --title "$title" --body-file "$body_file" --label dependencies | ||
| echo "Created new drift issue" | ||
| fi | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| name: ACP Freshness | ||
|
|
||
| on: | ||
| schedule: | ||
| # Weekly, Monday 09:00 UTC | ||
| - cron: '0 9 * * 1' | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
| issues: write | ||
|
|
||
| jobs: | ||
| check: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | ||
|
|
||
| - name: Check ACP freshness and file a drift issue if behind | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| ACP_FRESHNESS_FILE_ISSUE: 'true' | ||
| run: ./.config/mise/tasks/acp-freshness |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| --- | ||
| number: "0020" | ||
| slug: acp-sdk-1x-boundary-and-bridge-traits | ||
| status: accepted | ||
| date: 2026-07-07 | ||
| --- | ||
|
|
||
| # ADR 0020: ACP SDK 1.x Boundary and Bridge-Owned Callback Traits | ||
|
|
||
| ## Context | ||
|
|
||
| The `agent-client-protocol` Rust SDK was redesigned in its 0.11.0 release and | ||
| stabilized as 1.x. Two changes force a decision here: | ||
|
|
||
| 1. The SDK's `Agent` and `Client` traits no longer exist. They are role marker | ||
| structs now; message handling is registered through builder callbacks | ||
| (`Agent.builder().on_receive_request(...)`) and outbound calls go through | ||
| `ConnectionTo<Role>::send_request(...)`. Our crates used those traits as the | ||
| internal contract everywhere: runners implement `Agent`, the server-side | ||
| `Bridge` implements `Agent`, and `NatsClientProxy` implements `Client` | ||
| ([ADR 0004](./0004-protocol-and-transport-layering.md) describes this | ||
| layering). | ||
| 2. The SDK now ships official transports (`ByteStreams`, and HTTP/WebSocket in | ||
| `agent-client-protocol-http`). Our ACP-over-NATS transport is hand-rolled, | ||
| which raises the question of whether the official transport abstraction | ||
| should replace parts of it. | ||
|
|
||
| ## Decision | ||
|
|
||
| ### 1. Keep the hand-rolled NATS transport | ||
|
|
||
| The SDK transports model point-to-point byte streams between exactly two | ||
| peers. The NATS leg is not that: it is subject-routed (per-session subjects, | ||
| global subjects, wildcard subscriptions), durable where required (JetStream | ||
| COMMANDS stream with keepalive acks), and multi-peer. Flattening it into a | ||
| `ByteStreams` pair would discard the routing model that ADR 0003 and ADR 0004 | ||
| establish. The SDK builder connections are used only at true byte-stream | ||
| boundaries: the WebSocket duplex in `acp-nats-server` and stdio in | ||
| `acp-nats-stdio`. | ||
|
|
||
| ### 2. Bridge-owned callback traits replace the removed SDK traits | ||
|
|
||
| `acp-nats` defines its own `AgentHandler` and `ClientHandler` traits, | ||
| mirroring the method surface the bridge routes (the SDK's `schema::v1::*` | ||
| request/response types remain the argument and return types, so wire | ||
| compatibility is unchanged). The names avoid colliding with the 1.x SDK's own | ||
| `AcpAgent` subprocess helper. Runners implement `AgentHandler`; the | ||
| server-side `Bridge` implements `AgentHandler` by forwarding over NATS; | ||
| `NatsClientProxy` implements `ClientHandler`. This was | ||
| already the intended shape in ADR 0004 (an "ACP agent SDK" exposing agent | ||
| callback traits); the SDK redesign makes it mandatory rather than optional. | ||
|
|
||
| ### 3. SDK builder callbacks adapt boundaries to the bridge traits | ||
|
|
||
| At each byte-stream boundary, a thin adapter registers one `on_receive_*` | ||
| callback per routed method and delegates to the `AgentHandler`/`ClientHandler` | ||
| implementation. Outbound calls from the bridge to the peer go through the | ||
| connection handle (`ConnectionTo<...>`). Adapters contain no logic beyond | ||
| delegation, per the zero-cost passthrough rule in `rsworkspace/crates/AGENTS.md`. | ||
|
|
||
| The adapters are shared by `acp-nats-server` (WebSocket and HTTP duplex) and | ||
| `acp-nats-stdio`, so they live in one place: the `boundary` module of | ||
| `acp-nats`. That module is the single SDK-connection-aware part of the crate; | ||
| the NATS routing core remains free of connection machinery. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - The bridge's method surface is defined in one place (the bridge traits), and | ||
| the conformance matrix (`docs/architecture/acp-conformance.md`) tracks it. | ||
| - New spec methods require touching trait, adapter, and subject mapping. The | ||
| upgrade ritual in the conformance doc makes that explicit instead of | ||
| accidental. | ||
| - The SDK's own request cancellation, session helpers, and future transport | ||
| work apply at the boundaries without constraining the NATS leg. | ||
| - We keep full control of JetStream durability semantics, backpressure, and | ||
| keepalives, which the SDK transport abstraction does not model. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| --- | ||
| number: "0021" | ||
| slug: typed-decode-over-passthrough-forwarding | ||
| status: accepted | ||
| date: 2026-07-07 | ||
| --- | ||
|
|
||
| # ADR 0021: Typed Decode over Passthrough Forwarding | ||
|
|
||
| ## Context | ||
|
|
||
| The ACP-over-NATS bridge decodes every message into typed SDK structs and | ||
| re-serializes them (`acp-nats/src/wire.rs`). During the schema 0.11.4 to 1.4.0 | ||
| catch-up this bit us: fields the pinned SDK did not model were silently | ||
| stripped in transit, and unknown `session/update` variants failed decode and | ||
| were dropped. The catch-up effort (issue #474) asked whether the bridge should instead forward | ||
| payloads losslessly (raw `serde_json::Value` passthrough, typed validation | ||
| only where the bridge reads fields), so future spec additions degrade to | ||
| "forwarded" instead of "dropped". | ||
|
|
||
| ## Decision | ||
|
|
||
| Keep typed decode. The evaluation concluded that passthrough trades a managed | ||
| maintenance cost for the loss of properties the bridge depends on: | ||
|
|
||
| 1. **Validation at the boundary.** The bridge rejects malformed payloads with | ||
| `InvalidParams` before they reach runners or JetStream durable streams. | ||
| With passthrough, malformed frames propagate and fail deep inside | ||
| consumers, where the blast radius includes persisted garbage in the | ||
| COMMANDS stream. | ||
| 2. **The bridge reads most of what it routes.** Session ids, cwd, mcp server | ||
| counts, prompt payloads for telemetry spans, response session ids for | ||
| session-ready scheduling: the majority of routed messages are already | ||
| inspected, so "validate only where we read" converges back to typed decode | ||
| for most of the surface anyway. | ||
| 3. **The failure mode is now managed, not silent.** The original harm was | ||
| silent drift. That is addressed by the tracking foundation instead of by | ||
| loosening the wire layer: decode failures emit a `session_update` / | ||
| `decode_failure` error metric, the weekly freshness workflow files an issue | ||
| the moment upstream moves, and the upgrade ritual in | ||
| `docs/architecture/acp-conformance.md` makes round-trip tests for new | ||
| fields a mandatory part of every bump. | ||
| 4. **Schema-level leniency reduces the sharp edges.** Since schema 1.x, | ||
| unknown optional fields tolerate errors (`DefaultOnError` annotations), and | ||
| enum extension guidance is landing upstream for v2. The cost of typed | ||
| decode shrinks with each upstream release rather than growing. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - A peer sending a field newer than our pin still loses that field until the | ||
| next bump. The freshness workflow bounds that window to roughly a week of | ||
| detection latency plus the bump turnaround, and the conformance matrix makes | ||
| the gap visible instead of silent. | ||
| - Re-evaluate if either condition changes: upstream begins shipping breaking | ||
| schema changes faster than the bump cadence can absorb, or the bridge stops | ||
| reading payloads it routes (for example a pure relay deployment mode). In | ||
| that case a passthrough mode scoped to specific methods is the fallback | ||
| design. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # ACP Conformance | ||
|
|
||
| This document is the single source of truth for where this repository stands relative to the Agent Client Protocol (ACP) specification. Update it in the same PR as any `agent-client-protocol` version bump or any change to the bridged method surface. | ||
|
|
||
| ## Spec position | ||
|
|
||
| | Fact | Value | | ||
| | --- | --- | | ||
| | Wire protocol | v1 | | ||
| | Pinned Rust SDK | `agent-client-protocol` 1.2.0 (`rsworkspace/Cargo.toml`) | | ||
| | Bundled schema (effective spec level) | 1.4.0 (plus direct `agent-client-protocol-schema` dependency for schema-only unstable flags) | | ||
| | Latest upstream SDK at last review | 1.2.0 (2026-07-07) | | ||
| | Latest upstream schema at last review | 1.4.0 (2026-07-06) | | ||
| | Last reviewed | 2026-07-08 | | ||
|
|
||
| Upstream repositories: [spec/schema](https://github.com/agentclientprotocol/agent-client-protocol), [Rust SDK](https://github.com/agentclientprotocol/rust-sdk). | ||
|
|
||
| ## Policy | ||
|
|
||
| Opt in to unstable spec features ahead of stabilization. The default for every unstable feature is to enable the flag, wire the routing, and test it. Opting out is the exception and requires a rationale in the matrix below. | ||
|
|
||
| ## Why this matters here | ||
|
|
||
| The bridge decodes every message into typed SDK structs and re-serializes them (`acp-nats/src/wire.rs`). Fields the pinned SDK does not model are silently stripped in transit, and unknown `session/update` variants fail decode. Spec lag means silent data loss, not graceful passthrough, so this matrix must stay accurate. | ||
|
|
||
| ## Conformance matrix | ||
|
|
||
| Status values: `implemented` (routed, typed, tested), `capabilities implemented` (capability payloads round-trip, but the methods behind them are not routed), `unwired` (SDK flag enabled but no routing), `dropped` (peers may send it, the bridge strips or rejects it), `unrepresentable` (pinned SDK cannot express it), `not supported` (deliberate opt-out with rationale), `watch-only` (tracked for adoption, deliberately not implemented while upstream still churns). | ||
|
|
||
| ### Agent-side methods (client to agent) | ||
|
|
||
| | Spec surface | Spec stage (schema 1.4.0) | Our status | Notes | | ||
| | --- | --- | --- | --- | | ||
| | `initialize` | stable | implemented | | | ||
| | `authenticate` | stable | implemented | `unstable_auth_methods` shapes enabled | | ||
| | `logout` | stable (0.13.3) | implemented | | | ||
| | `session/new` | stable | implemented | includes `additionalDirectories` | | ||
| | `session/load` | stable | implemented | includes `additionalDirectories` | | ||
| | `session/list` | stable | implemented | | | ||
| | `providers/list` | unstable (0.11.7) | unrepresentable | not a routing gap: bridge-owned `AgentHandler::list_providers` and NATS subject routing (`providers.list`) are implemented and tested, but `agent-client-protocol` 1.2.0 cannot express the request at the byte-stream boundary (no `unstable_llm_providers` feature, provider types omitted from its `JsonRpcRequest` registrations); blocked on upstream SDK support | | ||
| | `providers/set` | unstable (0.11.7) | unrepresentable | see `providers/list`; `AgentHandler::set_provider` and NATS subject routing (`providers.set`) implemented and tested | | ||
| | `providers/disable` | unstable (0.11.7) | unrepresentable | see `providers/list`; `AgentHandler::disable_provider` and NATS subject routing (`providers.disable`) implemented and tested | | ||
| | `session/prompt` | stable | implemented | | | ||
| | `session/cancel` (notification) | stable | implemented | | | ||
| | `session/set_mode` | stable | implemented | | | ||
| | `session/set_config_option` | stable | implemented | 1.4.0 shape, boolean and `model_config` round-trip tested | | ||
| | `session/set_model` | **removed upstream** (0.13.5) | removed | deleted with the SDK migration; model switching goes through `model_config` config options | | ||
| | `session/fork` | unstable | implemented | | | ||
| | `session/resume` | stable (0.12.2) | implemented | | | ||
| | `session/close` | stable (0.12.2) | implemented | | | ||
| | `session/delete` | stable (0.13.6) | implemented | routed end to end with tests, span `acp.session.delete` | | ||
| | JSON-RPC request cancellation | stable (1.2.0) | implemented | boundary honors `$/cancel_request`: bridge-side work is dropped and the request answers with `request_cancelled` (tested); prompt-turn cancellation on the runner side remains `session/cancel` per spec | | ||
| | `ext/*` (extension methods) | stable | implemented | passthrough | | ||
|
|
||
| ### Client-side methods (agent to client) | ||
|
|
||
| | Spec surface | Spec stage | Our status | Notes | | ||
| | --- | --- | --- | --- | | ||
| | `fs/read_text_file` | stable | implemented | | | ||
| | `fs/write_text_file` | stable | implemented | | | ||
| | `session/request_permission` | stable | implemented | | | ||
| | `session/update` | stable | implemented | unknown variants fail decode and are dropped with a `session_update`/`decode_failure` error metric | | ||
| | `terminal/create` | stable | implemented | | | ||
| | `terminal/output` | stable | implemented | | | ||
| | `terminal/release` | stable | implemented | | | ||
| | `terminal/wait_for_exit` | stable | implemented | | | ||
| | `terminal/kill` | stable | implemented | | | ||
| | `elicitation/create` | unstable | implemented | `unstable_elicitation` SDK flag; routed both through the bridge-owned `ClientHandler::elicitation_create` and the SDK byte-stream boundary (`AgentRequest::CreateElicitationRequest`); `ElicitationScope::Request` (pre-session, no session id) is not routable since all NATS client subjects and `NatsClientProxy` construction are session-scoped | | ||
| | `elicitation/complete` (notification) | unstable | implemented | `unstable_elicitation` SDK flag; routed as a `ClientHandler::elicitation_complete` notification | | ||
| | `ext/*` | stable | implemented | passthrough, plus bullard-specific `ext/session/prompt_response` | | ||
|
|
||
| ### Payload-level capabilities | ||
|
|
||
| | Spec surface | Spec stage | Our status | Notes | | ||
| | --- | --- | --- | --- | | ||
| | `additionalDirectories` (session/new, session/load) | stable (0.13.5) | implemented | round-trip tested through the bridge | | ||
| | Message IDs on chunks | stable (0.13.6) | implemented | 1.4.0 shape, round-trip tested | | ||
| | Session usage updates | stable (0.13.6) | implemented | 1.4.0 shape, round-trip tested | | ||
| | Session config options | stable | implemented | 1.4.0 shape, `ConfigOptionUpdate` round-trip tested | | ||
| | Boolean config options | stable (1.3.0) | implemented | stabilized shape, round-trip tested | | ||
| | `model_config` option category | stable (1.1.0) | implemented | round-trip tested | | ||
| | NES (next edit suggestions) | unstable | capabilities implemented | capability payloads round-trip via schema-level flag; NES document sync methods are not routed (no runner demand yet, revisit with Phase 4 adoption cadence) | | ||
| | Plan operations | unstable (0.13.4) | implemented | `PlanUpdate`/`PlanRemoved` round-trip tested via schema-level flag | | ||
| | Providers | unstable (0.11.7) | unrepresentable | see `providers/list`/`providers/set`/`providers/disable` rows above | | ||
| | MCP-over-ACP message types | unstable (0.13.0) | implemented | `McpServer::Acp` and `McpCapabilities.acp` payload round-trip tested via schema-level and `unstable_mcp_over_acp` SDK flag; the `mcp/connect`, `mcp/message`, `mcp/disconnect` RPC methods are not routed (no runner demand yet, revisit with Phase 4 adoption cadence) | | ||
| | Elicitation enum option descriptions | unstable (1.4.0) | implemented | `EnumOption` descriptions on `StringPropertySchema.one_of` round-trip tested | | ||
| | Protocol v2 | unstable, heavy churn | watch-only | adopt once upstream marks it preview; the freshness workflow surfaces every release it churns in | | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| ## Upgrade ritual | ||
|
|
||
| A version bump of `agent-client-protocol` (or the schema it bundles) is never just a version change. Every bump PR must: | ||
|
|
||
| 1. Diff the schema changelog between the old and new pinned versions ([changelog](https://github.com/agentclientprotocol/agent-client-protocol/blob/main/CHANGELOG.md)). | ||
| 2. For each added or stabilized method: add subject mapping in `acp-nats/src/nats/parsing.rs`, a handler, and tests, or add a matrix row with an opt-out rationale. | ||
| 3. For each added field or `session/update` variant: add a round-trip test through the bridge. Typed re-encode means unmapped fields are silently dropped, so a green compile proves nothing about coverage. | ||
| 4. For each new unstable flag: enable it per the opt-in policy and wire it. | ||
| 5. Update this document (matrix and spec position table) in the same PR. | ||
|
|
||
| The scheduled freshness workflow (`.github/workflows/acp-freshness.yml`) embeds this checklist in the issue it files when drift is detected. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.