Changeset Channel
Reference for the ahp-changeset:/<id> channel — server-owned views of file changes (uncommitted, session-wide, per-turn, etc.) that clients can subscribe to and invoke operations on. See the Changesets guide for an overview of the model.
JSON Schema: state.schema.json
State Types
Changeset
Catalogue entry describing one changeset the server can produce for a session.
Catalogue entries are intentionally lightweight — just enough to render a chip or list row without subscribing. Full per-changeset detail ({@link ChangesetState}) lives on the subscribable URI obtained by expanding {@link uriTemplate}.
| Field | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Human-readable label, e.g. "Uncommitted Changes". |
uriTemplate | string | Yes | RFC 6570 URI template. Clients parse the variables directly out of the template using the standard {name} syntax — they are not redeclared here.Only the following template shapes are defined by this protocol; any other variable name MUST be ignored by clients (there is no protocol-defined way to obtain values for unknown variables): | Variables in template | Meaning | | ------------------------------------------- | ------------------------------------------------------------------------------------ | | (none) | A static, session-wide changeset. The template is itself a subscribable URI. | | {turnId} | Per-turn slice. Expand with a Turn.id from the session. | | {originalTurnId} and {modifiedTurnId} | Diff between two turns. Both variables MUST be present. |Future protocol versions MAY add new well-known variables. |
description | string | No | Optional longer description. |
changeKind | string | Yes | Advisory hint describing what kind of changeset this is, so clients can group, sort, or render an appropriate icon without parsing {@link uriTemplate}. Recognized values include: - 'session': a static, session-wide changeset covering all changes the agent has produced in this session. - 'branch': changes relative to a base branch (e.g. a feature branch diffed against main). - 'uncommitted': the workspace's current uncommitted changes. - 'turn': changes produced by a single turn. Typically paired with a {turnId} variable in {@link uriTemplate}. - 'compare-turns': a diff between two turns. Typically paired with {originalTurnId} and {modifiedTurnId} variables in {@link uriTemplate}.Implementations MAY provide additional values; clients SHOULD fall back to a reasonable default when an unknown value is encountered. |
capabilities | ChangesetCapabilities | No | Optional capability declarations for this changeset. Absent (or an empty object) means the changeset advertises no optional capabilities. Because the catalogue entry is delivered up-front on {@link ChangesetState | the session's changeset list}, clients can decide whether to surface capability-gated UI (such as review checkboxes) without first subscribing to the changeset URI. Mirrors the presence-flag convention of ClientCapabilities. |
ChangesetCapabilities
Optional capabilities a changeset advertises on its catalogue {@link Changeset} entry.
Each field is a presence flag: an empty object {} means "supported", absence means "not supported". Sub-fields on individual capabilities are reserved for future per-capability options.
| Field | Type | Required | Description |
|---|---|---|---|
review | Record<string, never> | No | The changeset supports the per-file review workflow. When declared, clients MAY surface a GitHub-style "Viewed" toggle per file and dispatch {@link ChangesetFilesReviewChangedAction | changeset/filesReviewChanged} to set each file's {@link ChangesetFile.reviewed} flag. Clients that omit handling MUST treat the changeset as non-reviewable. |
ChangesetStatus
Computation lifecycle of a {@link ChangesetState}.
| Member | Value | Description |
|---|---|---|
Computing | 'computing' | The server is still computing the contents of this changeset. |
Ready | 'ready' | The changeset has been fully computed and is up-to-date. |
Error | 'error' | Computation failed. The cause is described by {@link ChangesetState.error}. |
ChangesetState
Full state for a single changeset, returned when a client subscribes to an expanded changeset URI.
The client already knows the URI it subscribed to, so this state does not redundantly carry it (or the catalogue's id, label, etc.). Aggregate counts (additions, deletions, files) are likewise omitted: clients trivially compute them from files[].edit.diff.
| Field | Type | Required | Description |
|---|---|---|---|
status | ChangesetStatus | Yes | Computation lifecycle. |
error | ErrorInfo | No | Present iff status === ChangesetStatus.Error. |
files | ChangesetFile[] | Yes | Files in this changeset, keyed by {@link ChangesetFile.id}. |
operations | ChangesetOperation[] | No | Operations the client may invoke against this changeset. Omit when no operations are available. |
ChangesetFile
One file entry within a {@link ChangesetState}.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Stable identifier within the changeset. Typically after.uri (or before.uri for deletions). |
edit | FileEdit | Yes | Reuses the existing {@link FileEdit} shape. Clients derive line additions, deletions, and rename/create/delete semantics from this. |
reviewed | boolean | No | Whether a reviewer has marked this file as reviewed (the GitHub-style "Viewed" checkbox). Absent is equivalent to false — clients MUST treat a missing value as not-yet-reviewed.Requires the changeset to advertise {@link ChangesetCapabilities.review}. Clients toggle it by dispatching {@link ChangesetFilesReviewChangedAction | changeset/filesReviewChanged}; the server MAY also originate it (e.g. an agent self-reviewing its own output).There is no content version in the protocol, so review is not reset automatically when a file's contents change under a stable id. The server, which is the authority on what changed, resets review explicitly — either by re-emitting the file (via {@link ChangesetFileSetAction} or {@link ChangesetContentChangedAction}) without reviewed: true, or by dispatching changeset/filesReviewChanged with reviewed: false. |
_meta | Record<string, unknown> | No | Server-defined opaque metadata, surfaced to operations and tooling but not interpreted by the protocol. |
ChangesetOperationStatus
Execution lifecycle of a {@link ChangesetOperation}.
An operation is invoked imperatively via invokeChangesetOperation, but its progress and outcome are reflected back into changeset state so that every subscriber observes a consistent view (e.g. a spinner on a "Create Pull Request" button, or an inline error after a failed "revert").
| Member | Value | Description |
|---|---|---|
Idle | 'idle' | The operation is ready to be invoked. This is the default when {@link ChangesetOperation.status} is omitted. |
Running | 'running' | An invocation of this operation is currently in flight. |
Error | 'error' | The most recent invocation failed. The cause is described by {@link ChangesetOperation.error}. |
Disabled | 'disabled' | The operation is currently disabled and cannot be invoked. |
ChangesetOperationScope
Where a {@link ChangesetOperation} can be invoked.
| Member | Value | Description |
|---|---|---|
Changeset | 'changeset' | Applies to the whole changeset. |
Resource | 'resource' | Applies to a single file within the changeset. |
Range | 'range' | Applies to a line range within a single file. |
ChangesetOperation
A server-declared invokable verb the client can run against a changeset, a file, or a range — "stage", "revert", "create-pr", and so on.
The term "operation" is used deliberately to avoid colliding with the protocol-level Actions that mutate state.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Stable identifier, unique within this changeset. |
label | string | Yes | Human-readable button/menu label. |
description | string | No | Optional longer description shown on hover or in tooltips. |
scopes | ChangesetOperationScope[] | Yes | Where this operation can be invoked. |
confirmation | StringOrMarkdown | No | Optional confirmation prompt to show before invoking. When present, the client MUST display this message to the user (typically in a confirmation dialog) and only invoke the operation after the user accepts. The presence of this field also signals that the operation is destructive — clients SHOULD style the affirmative button accordingly (e.g. with a warning colour). |
icon | string | No | Optional generic icon hint, e.g. "check", "trash". |
group | string | No | Optional group identifier, used to group related operations together. |
status | ChangesetOperationStatus | Yes | Current execution status. The server sets {@link ChangesetOperationStatus.Running | Running} while an invocation is in flight, {@link ChangesetOperationStatus.Error | Error} when the most recent invocation failed, and {@link ChangesetOperationStatus.Idle | Idle} otherwise. Clients SHOULD reflect this state in the UI — e.g. disabling the control or showing a spinner while Running, and surfacing {@link error} while Error. |
error | ErrorInfo | No | Cause of failure. Present iff status === ChangesetOperationStatus.Error; otherwise omitted. |
Actions
Mutate ChangesetState. Scoped to a changeset URI via the enclosing ActionEnvelope.channel.
JSON Schema: actions.schema.json
changeset/statusChanged
The {@link ChangesetState.status} for this changeset transitioned (e.g. computing → ready). The error payload is set together with status whenever it transitions to {@link ChangesetStatus.Error | Error}.
| Field | Type | Required | Description |
|---|---|---|---|
type | ActionType.ChangesetStatusChanged | Yes | |
status | ChangesetStatus | Yes | New computation lifecycle status. |
error | ErrorInfo | No | Cause when status === ChangesetStatus.Error; otherwise omitted. |
changeset/fileSet
Upsert a {@link ChangesetFile} in the changeset — adds a new entry, or replaces an existing one identified by {@link ChangesetFile.id}.
| Field | Type | Description |
|---|---|---|
type | ActionType.ChangesetFileSet | |
file | ChangesetFile | The new or replacement file entry. |
changeset/fileRemoved
Remove a {@link ChangesetFile} from the changeset by its id.
Typically dispatched when a file is reverted, staged out, or otherwise no longer in scope (e.g. a renamed file is replaced by a new entry).
| Field | Type | Description |
|---|---|---|
type | ActionType.ChangesetFileRemoved | |
fileId | string | The {@link ChangesetFile.id} of the file to remove. |
changeset/filesReviewChanged
Set the {@link ChangesetFile.reviewed} flag for one or more files — the GitHub-style "Viewed" toggle, applied in a single batch.
Targets files by their {@link ChangesetFile.id}. Ids in {@link files} that do not match a file currently present in the changeset are ignored; if none match, the action is a no-op. Only the {@link ChangesetFile.reviewed} field of each matched file is affected; the files' {@link ChangesetFile.edit | edit} and {@link ChangesetFile._meta | _meta} are left untouched.
Only meaningful on a changeset that advertises {@link ChangesetCapabilities.review}. Unlike every other changeset/* action this one is client-dispatchable: a reviewer toggles review state directly, applying it optimistically through the write-ahead reducer and letting the server echo it back on the normal action envelope stream. The server MAY also originate it (e.g. an agent marking its own output reviewed).
There is no protocol-level content version, so review is not reset automatically when a file's contents change under a stable id. The server, which is the authority on what changed, resets review explicitly — either by re-emitting the file without reviewed: true, or by dispatching this action with reviewed: false.
| Field | Type | Description |
|---|---|---|
type | ActionType.ChangesetFilesReviewChanged | |
files | string[] | The {@link ChangesetFile.id | ids} of the files whose review state changed. |
reviewed | boolean | New review state applied to every listed file: true once reviewed, false to clear it. |
changeset/contentChanged
The changeset's full content changed. Full replacement semantics: files replaces the previous file list, and operations, when present, replaces the previous operation list.
Producers SHOULD use this action for initial snapshots and bulk refreshes; use {@link ChangesetFileSetAction}, {@link ChangesetFileRemovedAction}, and {@link ChangesetOperationsChangedAction} for incremental updates.
| Field | Type | Required | Description |
|---|---|---|---|
type | ActionType.ChangesetContentChanged | Yes | |
files | ChangesetFile[] | Yes | Full replacement file list. |
operations | ChangesetOperation[] | No | Full replacement operation list. Omit when operations are unchanged. |
error | ErrorInfo | No | Error information, if the changeset content change failed. |
changeset/operationsChanged
The set of operations available on this changeset changed. Full replacement semantics: operations replaces the previous list (or removes it entirely when operations is undefined).
| Field | Type | Description |
|---|---|---|
type | ActionType.ChangesetOperationsChanged | |
operations | ChangesetOperation[] | undefined | Updated operation list. Pass undefined to clear all operations. |
changeset/operationStatusChanged
The {@link ChangesetOperation.status} for a single operation transitioned (e.g. idle → running → idle, or running → error). The error payload is set together with status whenever it transitions to {@link ChangesetOperationStatus.Error | Error}, and cleared on any other transition.
Targets one operation by its {@link ChangesetOperation.id}. If no operation with that id is currently present in the changeset, the action is a no-op. Use {@link ChangesetOperationsChangedAction} to add, remove, or otherwise replace the operation list itself.
| Field | Type | Required | Description |
|---|---|---|---|
type | ActionType.ChangesetOperationStatusChanged | Yes | |
operationId | string | Yes | The {@link ChangesetOperation.id} whose status changed. |
status | ChangesetOperationStatus | Yes | New execution status. |
error | ErrorInfo | No | Cause when status === ChangesetOperationStatus.Error; otherwise omitted. |
changeset/cleared
Drop every file from the changeset.
Two cases use this:
- The underlying source moved (branch switched, fork point invalidated, …) and the server is recomputing from scratch — subsequent {@link ChangesetFileSetAction} entries will repopulate it.
- The owning session has ended and the URI is becoming un-subscribable — the server will unsubscribe all clients shortly after dispatching this action.
Clients SHOULD release any references on receipt and SHOULD NOT distinguish the two cases from the action alone — instead, react to the corresponding session-level lifecycle signal (e.g. root/sessionRemoved) for the "going away" case.
| Field | Type | Description |
|---|---|---|
type | ActionType.ChangesetCleared |
Commands
JSON Schema: commands.schema.json
invokeChangesetOperation
Invokes a server-defined {@link ChangesetOperation} against a changeset, a single file, or a line range.
The server validates that operationId exists in the changeset's current operations list and that the requested target.kind is contained in the operation's scopes. Invalid combinations result in a JSON-RPC error.
State changes resulting from invocation flow back through the normal changeset/* action stream on the relevant changeset URIs. Clients SHOULD NOT synthesise local optimistic changes for invocations unless the server explicitly opts in via a future capability.
| Property | Value |
|---|---|
| Direction | Client → Server |
| Type | Request |
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
channel | URI | Yes | The expanded changeset URI. |
operationId | string | Yes | Matches {@link ChangesetOperation.id} from the changeset's operations list. |
target | ChangesetOperationTarget | No | Target of the operation. Required iff the chosen scope is 'resource' or 'range'. Omit for changeset-scoped operations. |
Result:
| Field | Type | Required | Description |
|---|---|---|---|
message | StringOrMarkdown | No | Optional human-readable message describing the result. |
followUp | ChangesetOperationFollowUp | No | Optional follow-up: a URI to open (e.g. a PR), a content ref, etc. |