Story
As an XMD user who opens a Claude coding session in its native terminal UI, I want a later ACP interaction with that logical session to continue the exact same Claude conversation, so switching between the native UI and document-driven interaction never loses or substitutes its history.
Common path
- XMD launches Claude natively under a client-allocated session identity.
- The user works in Claude's terminal UI and closes it.
- XMD later asks Claude to continue that same logical session through ACP.
- The ACP turn sees the native conversation's history and appends to that conversation.
Current gap
The embedded @agentclientprotocol/claude-agent-acp@0.70.0 accepts the retained UUID for session/resume, but the returned ACP handle has no canonical agentSessionId. Its backendSessionId matches the requested UUID, but that value is not independent evidence: it can be the identifier XMD supplied.
XMD therefore refuses before sending a prompt. That refusal is correct, but it means the native-to-ACP capability delivered by #561 is not usable with the real current adapter.
A one-shot observation against Claude Code 2.1.263 established:
- the adapter attachment returned;
agentSessionId was absent;
backendSessionId matched the requested identity;
- zero prompts were sent;
- the Claude transcript was unchanged; and
- the adapter and experiment processes closed cleanly.
This is the same safety boundary behind #639 and the silent history-splitting risk reported upstream in agentclientprotocol/claude-agent-acp#1019. It is narrower than #639's ACP-created session/new path: this defect is the session/resume bridge from an XMD client-native route.
Contract
Before an ACP turn enters a client-native Claude session, the live adapter must independently report the actual provider-native session identity it opened. That identity must exactly equal the immutable identity retained by the XMD route and launch journal.
The requested UUID, ACP session key, backendSessionId, transcript filename, or another value derived from XMD's request is not sufficient proof by itself. An absent or different provider assertion refuses before a turn, without creating replacement history or rewriting durable state.
The repair may update or patch the embedded Claude adapter, but must not weaken XMD's identity comparison. It preserves the accepted cross-compatible-release contract: the live executable independently passes protocol, capability, positive CLI-shape, and host admission; version and digest remain audit evidence rather than a same-build lock. Existing ownership, privacy, cancellation, replay, and teardown behavior remains unchanged.
Acceptance
- A marker introduced only in a native Claude turn is recovered by a later marker-free ACP prompt through the same logical XMD session.
session/resume independently reports the exact Claude session identity, and XMD compares it with the immutable route and journal identity before sending the prompt.
- Removing, changing, or replacing that assertion causes a refusal with zero prompts, zero substitute sessions, and unchanged route, journal, ownership, and ACP arrangement state.
- A matching
backendSessionId with an absent agentSessionId still refuses, proving the repair does not trust an echo of the request.
- Compatible cross-release continuation remains supported; protocol, profile, host, capability, provider, launcher, or identity disagreement remains fail-closed.
- Completed replay performs no live adapter work. Incomplete replay uses the retained identity without allocating or rewriting it.
- Cancellation and teardown close every handle through the runtime that created it and leave no adapter or provider resources running.
- Evidence exercises the embedded real Claude adapter contract rather than supplying
agentSessionId from a fake runtime.
Evidence
Extend the native-to-ACP Claude proof with a real-adapter identity row and a discriminating missing-identity mutation. Keep the marker-based history check: UUID equality without recovery of native-only history is not success.
Do not use the terminal-grid demo as automated evidence because it launches real agent sessions. A separate explicitly authorized live gate may validate the final embedded adapter and installed Claude combination.
Relationships
Out of scope
- Trusting
backendSessionId or another client-supplied value as provider identity.
- Reading Claude transcript files to authorize ACP continuation.
- Sending prompts to a terminal TUI or coupling XMD to its screen state.
- Changing tmux pane behavior or the passive session-file observer.
Story
As an XMD user who opens a Claude coding session in its native terminal UI, I want a later ACP interaction with that logical session to continue the exact same Claude conversation, so switching between the native UI and document-driven interaction never loses or substitutes its history.
Common path
Current gap
The embedded
@agentclientprotocol/claude-agent-acp@0.70.0accepts the retained UUID forsession/resume, but the returned ACP handle has no canonicalagentSessionId. ItsbackendSessionIdmatches the requested UUID, but that value is not independent evidence: it can be the identifier XMD supplied.XMD therefore refuses before sending a prompt. That refusal is correct, but it means the native-to-ACP capability delivered by #561 is not usable with the real current adapter.
A one-shot observation against Claude Code 2.1.263 established:
agentSessionIdwas absent;backendSessionIdmatched the requested identity;This is the same safety boundary behind #639 and the silent history-splitting risk reported upstream in agentclientprotocol/claude-agent-acp#1019. It is narrower than #639's ACP-created
session/newpath: this defect is thesession/resumebridge from an XMD client-native route.Contract
Before an ACP turn enters a client-native Claude session, the live adapter must independently report the actual provider-native session identity it opened. That identity must exactly equal the immutable identity retained by the XMD route and launch journal.
The requested UUID, ACP session key,
backendSessionId, transcript filename, or another value derived from XMD's request is not sufficient proof by itself. An absent or different provider assertion refuses before a turn, without creating replacement history or rewriting durable state.The repair may update or patch the embedded Claude adapter, but must not weaken XMD's identity comparison. It preserves the accepted cross-compatible-release contract: the live executable independently passes protocol, capability, positive CLI-shape, and host admission; version and digest remain audit evidence rather than a same-build lock. Existing ownership, privacy, cancellation, replay, and teardown behavior remains unchanged.
Acceptance
session/resumeindependently reports the exact Claude session identity, and XMD compares it with the immutable route and journal identity before sending the prompt.backendSessionIdwith an absentagentSessionIdstill refuses, proving the repair does not trust an echo of the request.agentSessionIdfrom a fake runtime.Evidence
Extend the native-to-ACP Claude proof with a real-adapter identity row and a discriminating missing-identity mutation. Keep the marker-based history check: UUID equality without recovery of native-only history is not success.
Do not use the terminal-grid demo as automated evidence because it launches real agent sessions. A separate explicitly authorized live gate may validate the final embedded adapter and installed Claude combination.
Relationships
claude --session-idconversation silently completes without its history instead of loading it or failing agentclientprotocol/claude-agent-acp#1019: upstream report that native-session resume may silently continue without native history.Out of scope
backendSessionIdor another client-supplied value as provider identity.