Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1dfd57c
docs: propose OpenClaw Control Model
giodl73-repo Aug 11, 2026
e0b7e3c
docs: clarify artifact capability ownership
giodl73-repo Aug 11, 2026
585c374
docs: expose client-selectable view offers
giodl73-repo Aug 11, 2026
b964e72
Refine control model view offers
giodl73-repo Aug 11, 2026
110604c
Clarify durable artifact projections
giodl73-repo Aug 11, 2026
97d6bfc
docs(rfc): place Control Model in Gateway Client
Aug 14, 2026
b64f7ee
docs(rfc): record completed adopter evidence
giodl73-repo Aug 15, 2026
1d17154
docs(rfc): record board and config model evidence
giodl73-repo Aug 15, 2026
61e00db
docs(rfc): link adjacent model proofs
giodl73-repo Aug 15, 2026
dacfda0
docs: record adjacent model proof gates
giodl73-repo Aug 15, 2026
a3e8945
docs: prepare Control Model RFC filing
giodl73-repo Aug 16, 2026
af57756
docs: tighten Control Model filing scope
giodl73-repo Aug 16, 2026
ea3836e
docs: record first OC5 hardening slice
giodl73-repo Aug 16, 2026
4f8292a
docs(rfc): plan incremental Control UI adoption
giodl73-repo Aug 16, 2026
9caac23
docs: record CU4 Control UI command adoption
giodl73-repo Aug 16, 2026
c0fd250
docs(rfc-0029): record Control UI CU5 adoption
giodl73-repo Aug 16, 2026
85c4501
docs(rfc-0029): record complete fixture families
giodl73-repo Aug 16, 2026
7012832
docs(rfc-0029): record OC5 performance proof
giodl73-repo Aug 16, 2026
7ffba4e
docs(rfc-0029): record compatibility canary
giodl73-repo Aug 16, 2026
e6abbaa
docs(rfc-0029): record lifecycle performance gate
giodl73-repo Aug 16, 2026
b02efc3
docs(rfc-0029): record security review gate
giodl73-repo Aug 16, 2026
574a8e0
docs(rfc-0029): nominate publication owners
giodl73-repo Aug 16, 2026
ec85014
docs: record control model review closeout
giodl73-repo Aug 17, 2026
46c837d
RFC(0029): add handshake & capability-advertisement section; server f…
giodl73-repo Aug 21, 2026
bd7da59
RFC(0029): appendix mapping a2ui -> uiDetails; implementation guidanc…
giodl73-repo Aug 21, 2026
dd2a153
docs: clarify control model additive scope
giodl73-repo Aug 21, 2026
c079692
docs: point control model rfc to upstream pr
giodl73-repo Aug 21, 2026
c6a3bef
docs: link control model upstream drafts
giodl73-repo Aug 21, 2026
7bcfefd
docs: link hosted policy siblings
giodl73-repo Aug 21, 2026
bca94c8
docs: add hosted control ui policy sidecar
giodl73-repo Aug 21, 2026
939dc20
docs: align rfc submission status
giodl73-repo Aug 23, 2026
6a7d949
docs: mark Lobster native table evidence merged
giodl73-repo Aug 23, 2026
7a8f437
docs: link session-list follow-up evidence
giodl73-repo Aug 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
705 changes: 705 additions & 0 deletions rfcs/0029-openclaw-control-model.md

Large diffs are not rendered by default.

299 changes: 299 additions & 0 deletions rfcs/0029/conformance-and-adoption-plan.md

Large diffs are not rendered by default.

371 changes: 371 additions & 0 deletions rfcs/0029/control-model-v1-spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,371 @@
# Control Model v1 specification

This document defines the candidate behavioral contract for
`@openclaw/gateway-client/model`. It specifies framework-neutral state and
commands above the Gateway Client browser transport. It does not define
presentation, product authentication, or another wire protocol.

Status: submitted draft sidecar for RFC 0029. It has not been accepted or
released upstream; implementation evidence remains draft and review-gated.

## Scope

A conforming v1 model provides:

- explicit lifecycle and disposal;
- immutable connection and session-catalog snapshots;
- lazily created conversation snapshots;
- history/live/reconnect reconciliation;
- typed tool, approval, question, and run state needed by chat;
- typed commands with structured failure;
- renderer-neutral UI artifacts; and
- finite retained state with observable partial/lag conditions.

## Host binding

The model consumes one host-owned Gateway binding. The binding must provide:

- the current connection snapshot and an invalidation subscription;
- Gateway event subscription;
- correlated request execution;
- the accepted hello/protocol metadata required for feature detection; and
- typed request and connection errors.

The binding is a construction-only capability for the host and model
implementation. It must not be exposed through public snapshots, conversation
handles, artifacts, renderer registrations, or framework adapters.

The host owns:

- socket creation and route selection;
- credentials, signing, and device-token persistence;
- product authentication and tenant admission;
- reconnect policy outside shared Gateway-client behavior; and
- logging and telemetry sinks.

The model must not start a network connection at import or construction time.
It must not persist credentials.

## Handshake and capability advertisement

The client may advertise a bounded capability object during the initial
session handshake or subscription request so the server can filter or rank
offered artifact views and avoid sending unsupported large artifacts.
Advertisement is advisory only; it does not install a renderer, disclose the
full local registry, grant trust, or authorize an operation.

Suggested capability object (client to server):

```json
{
"clientId": "product/instance-version",
"capabilities": {
"artifactViews": [
{
"templateUri": "clawpilot://widgets/table",
"artifactVersion": 1,
"dataVersions": [1],
"surfaces": ["inline", "expanded"]
}
],
"sandboxFallbacks": ["mcp-app", "canvas"],
"structuredFallback": true,
"progressiveRevisions": true,
"supports_actions": true,
"max_artifact_size_bytes": 65536
}
}
```

Server guidance:

1. If an offered view matches an advertised template URI, artifact version, and
data version, the server may rank that view higher or include bounded inline
data.
2. If the renderer is unsupported but a structured/text fallback exists,
send the fallback instead.
3. If artifact size exceeds `max_artifact_size_bytes`, send a bounded
structured fallback or expose the view as deferred. V1 publishes complete
immutable revisions; it does not standardize JSON Patch, JSONL, or
fragment/CID transport.
4. Never expose private or scrubbed fields to clients lacking required
authorization regardless of advertised capabilities.
5. Treat capability advertisement as potentially stale or incomplete; the
client may still decline or ignore offers at render time.

Privacy guidance:

- advertise exact supported template/version pairs, not unrelated installed
component inventory;
- keep renderer capability metadata between the trusted client and Gateway by
default rather than forwarding it verbatim to extensions;
- let extensions ask bounded compatibility questions when needed; and
- require the host registry to validate the selected view again before native
rendering, because the advertisement may be stale.

## Root lifecycle

Construction is inert except for validating options. `start()` may subscribe to
an already managed Gateway binding; alternatively, construction may start
subscriptions when the API makes that behavior explicit. The selected shape
must have one unambiguous lifecycle.

`dispose()` is idempotent and must:

- unsubscribe from Gateway state and events;
- abort or retire model-owned refreshes;
- wake model waiters with a terminal disposed error;
- retire conversation epochs;
- release retained snapshots not reachable by the caller; and
- prevent later events from mutating published state.

No subscription callback may fire after its unsubscribe function returns,
except a callback already executing on the same stack.

Gateway event callbacks must not synchronously run consumer render or
subscriber work. The model may enqueue bounded reconciliation work and publish
outside the protocol receive stack. It must not await subscribers. One
subscriber exception must not prevent other subscribers or future Gateway
events from being processed.

## Snapshot contract

Snapshots are immutable values. A consumer must be able to:

1. read a snapshot;
2. subscribe;
3. read again to close the read/subscribe race; and
4. compare snapshot identity to determine whether state changed.

Every state transition publishes a new root or capability snapshot identity.
Unchanged state must retain identity where practical to avoid unnecessary
renderer work.

Snapshots use JSON-compatible data except documented opaque handles. Dates are
ISO-8601 strings or integer epoch milliseconds consistently within one public
type family.

## Connection snapshot

The connection projection contains:

- phase: stopped, connecting, connected, reconnecting, offline, or disposed;
- a monotonically increasing connection epoch;
- accepted protocol version and declared capabilities where available;
- current session/instance identity safe for presentation;
- structured last error and reconnect classification; and
- whether state is complete, stale, partial, or resynchronizing.

A transport connection alone does not imply conversation readiness. Readiness
requires the required initial snapshots or an explicit partial state.

## Session catalog

The catalog contains stable session keys and the Gateway-authoritative fields
needed to list and identify sessions. Unknown additive fields must not break
projection.

The model owns:

- initial list loading;
- live `sessions.changed` reconciliation;
- explicit deleted-session handling;
- refresh after sequence gaps or observer outages;
- duplicate suppression;
- connection-epoch retirement;
- bounded retry for retryable observer errors; and
- typed loading, refreshing, stale, and error state.

Any future optional catalog mutation must specify reconciliation and rollback.
A failed mutation must not leave success-shaped catalog state.

## Conversation model

`conversation(sessionKey)` returns a stable model handle for that normalized
session key until release or root disposal. A host may release inactive
conversation handles through an explicit API. The package must bound inactive
retention.

The conversation snapshot contains:

- normalized session identity;
- loading, ready, stale, partial, terminal, and error state;
- canonical ordered messages with stable IDs;
- the active run and stream projection;
- tool invocations and outcomes;
- approval and question requests;
- UI artifacts;
- command availability hints; and
- the connection and history revisions used to derive the snapshot.

## History and live reconciliation

The model must define one deterministic merge for:

- an initial or refreshed history response;
- live messages received before, during, or after history loading;
- duplicate live and persisted messages;
- live tool calls and later persisted tool results;
- run start, progress, terminal, abort, and disconnect;
- sequence gaps;
- history truncation or pagination; and
- reconnection to a replacement Gateway client.

Stable server IDs are authoritative. Where the server does not provide an ID,
the model may derive a bounded provisional key, but it must expose provisional
status and reconcile it when canonical state arrives.

A reconnect must not duplicate a message, tool invocation, approval, question,
or UI artifact. Events from a retired connection epoch must not mutate the
current conversation.

When a gap prevents complete reconciliation, the model publishes explicit
partial/stale state and requests an authoritative refresh. It must not silently
continue with success-shaped complete state.

## Tool and run projection

Every tool invocation has:

- a stable call ID;
- tool identity safe for display;
- finite structured input or a redacted/unavailable marker;
- pending, running, succeeded, failed, cancelled, or unknown outcome;
- live progress with finite retention;
- structured output or a redacted/unavailable marker;
- associated UI artifact IDs; and
- timestamps/revisions needed for deterministic ordering.

Approved-but-failed execution remains distinct from approval denial.
Cancellation remains distinct from failure. Unknown output is not success.

Progress retention must be bounded by count and bytes. Truncation is explicit.

## Approval and question projection

An approval or question contains:

- a stable request ID and owning session/run/tool identity;
- typed presentation-safe description;
- exactly the actions currently allowed by the Gateway contract;
- pending, answered, expired, cancelled, or unavailable lifecycle;
- an optional deadline; and
- structured source/authority information safe for presentation.

The model must reject a locally requested action that is not in the current
allowed set, but that preflight is not authorization. The Gateway independently
authorizes the request.

When the server provides a safe denial reason, policy source, or responsible
owner, the projection preserves it so adapters can present an actionable
explanation rather than a generic disabled state. Adapters must not widen or
replace the server-provided allowed-action set.

## Commands

Candidate v1 commands are:

- refresh session catalog;
- load/refresh conversation history;
- send chat content and supported attachments;
- abort the active run;
- answer a question;
- approve or deny a pending request; and
- materialize one exact deferred UI view for the current artifact revision; and
- retry only where the Gateway exposes a safe retry contract.

Session creation, rename, archive, delete, and other administration operations
are not required by v1 conformance. A later optional capability must add its own
independent-adopter, authorization, reconciliation, rollback, and deletion
evidence.

Each command defines:

- required current state;
- exact Gateway method and parameter contract;
- whether it is idempotent;
- abort behavior;
- stale/retired epoch behavior;
- optimistic state, if any;
- success result; and
- typed failures.

The model must not retry a non-idempotent command automatically unless the
Gateway contract provides an idempotency key and the retry preserves it.

## Error contract

Public errors distinguish at least:

- disconnected or not ready;
- disposed;
- unsupported by negotiated capability;
- invalid input;
- stale connection/session epoch;
- forbidden;
- conflict;
- not found or expired;
- timeout or abort;
- retryable transport/startup failure;
- sequence gap/partial state; and
- malformed or incompatible server data.

Errors preserve safe canonical codes, retryability, and retry-after hints where
available. Arbitrary server details, credentials, raw headers, and unbounded
payloads must not enter public messages or logs.

## Bounds

V1 must define finite defaults for:

- retained inactive conversations;
- messages per loaded page and total retained pages;
- live progress lines and bytes;
- pending tool/approval/question entries;
- UI artifacts per message/conversation;
- artifact data bytes/depth;
- observer retry delay;
- refresh concurrency; and
- command timeout inheritance.

The package must expose truncation, pagination, or partial state rather than
silently dropping retained state.

The implementation must also bound queued reconciliation work between Gateway
event delivery and snapshot publication. Exceeding that bound produces an
explicit lag/partial state and authoritative refresh rather than unbounded
memory growth.

## Framework neutrality

The published runtime graph must not import:

- Lit, React, Vue, Svelte, or framework adapters;
- DOM custom elements or browser storage;
- Control UI routes, theme, localization, CSS, or components;
- product authentication or telemetry; or
- Node-only modules from the browser entry.

Framework adapters may live in separate optional packages or adopter
repositories.

## Required conformance evidence

Before v1 support is claimed, shared fixtures must cover:

- read/subscribe race closure and immutable identity;
- initial session list plus live create/update/delete;
- retryable observer outage and authoritative refresh;
- history/live overlap;
- duplicate and out-of-order message/tool events;
- sequence gap and explicit partial state;
- reconnect with retired-epoch event rejection;
- active stream completion, cancellation, and disconnect;
- approval allowed/denied/expired paths;
- typed command rejection and conflict;
- artifact association and revision ordering;
- bounds and truncation; and
- disposal during every active wait.

At least OpenClaw Control UI and one independent host must consume the same
fixtures before publication.
Loading