Skip to main content

Crate tilo_actions

Crate tilo_actions 

Expand description

§Tilo ACTION model

The state layer behind Ctrl+K and cross-peer collaboration: a serializable, replayable unit of CRDT mutation.

§Play locally, replay anywhere

An Action is a value that deterministically mutates a CRDT Doc. Applied to the local replica, its ActionEnvelope is replicated; a peer starting from the same state replays it and lands on the identical document — the executor pins the Automerge actor id (from the action’s ActionId) and commit timestamp on every apply, so the resulting change is content-addressed identical everywhere.

Replayable Action values are strictly not presentation and mutate only shared CRDT state. The wider resource/action protocol also describes client-local OperationKind::View and external OperationKind::Effect operations. Those use the same typed descriptors, permission checks and invocation receipts, but are dispatched through the toolkit’s operation handler instead of being replayed as document history.

§Resources

An app publishes the tree of Resources it currently has open (a video → its comments; a book → its annotations) through the toolkit’s PublishesResources. Each resource exports ActionSpecs; the palette lists them, and choosing one dispatches the underlying action.

§The door

A resource tree is only useful to the app that built it until someone else can reach it. door is that reach: door::survey turns a live tree into inert, stably-addressed descriptors, and door::invoke performs one attributed to the caller — so another session acts on an app without the app growing a remote-control surface of its own.

§Remote use

remote carries the door across machines: a versioned, transport-neutral vocabulary for listing, invoking, observing and cancelling another peer’s actions, and the remote::ActionHost trait a peer implements to answer it. The caller is always the principal the transport authenticated, and invocations are idempotent per InvocationId.

§Execution locus

Each action declares an ExecutionLocus: ClientLocal (this client applies + replicates; peers replay) or ServerPreferred (route to an authoritative host). dispatch honours it against an ActionTransport and refuses the operation when no host answers.

§Sharing this vocabulary with the compositor

params is the same vocabulary the compositor’s headless action API speaks — ParamType, ActionParam, ArgValue, and the strict ActionArgs::bind — lifted into one definition rather than left to converge by accident. The wire spellings of text / integer / boolean and the bind semantics (unknown argument refused, first failure wins, nothing partial reaches an action) are unchanged from that surface, and the const constructors keep a const PARAMS: &[ActionParam] = &[…] compiling as written.

Two additive extensions: ParamType::Number, because the app-side arguments this replaces are overwhelmingly fractional and rounding them would discard the values they exist to carry; and ActionParam::choices, which turns a prose list into something a caller can read and binding can enforce. The string fields are Cow<'static, str> rather than &'static str because an app builds its parameters per frame out of live document state — a const declaration is Cow::Borrowed and costs nothing.

Modules§

action
The Action trait and its serializable envelope-side vocabulary.
appearance
The name and avatar a bot shows for one action, as a webhook does: a bridge posts a Discord user’s message under that user’s name. The bot stays the author; an appearance is presentation recorded in provenance, never identity. A value that fails validation refuses the invocation; it is never cleaned up, so what a reader sees is exactly what the bot sent.
compact
The compact form a history entry takes in a change message.
content
Large parts of a recorded action, kept as content and named by hash.
context
The history entry an action carries into its committed change.
contract
Machine-readable operational semantics for exported actions.
door
The door: how a participant that is not the app enumerates what it has open and performs one of its exported operations.
entry
What a committed action did, as data.
envelope
The ActionEnvelope: what actually replicates.
executor
Applying, replaying, and dispatching actions.
framework
Changes the framework makes to a record, which no app action produces.
group_form
How a group’s payload is written: its members, with what they share written once.
interaction
Semantic, transient presence for an action invocation.
key
Naming an action as data, and what kind of action it is.
optimistic
Latency-hiding action lifecycle for a UI backed by a remote model host.
outcome
Typed invocation identity, progress, failure, and successful results.
params
Typed action parameters: what an invocation must carry, and the strict bind that checks it before anything runs.
protocol
Runtime validation for an application’s published protocol surface.
registry
The ActionRegistry: type_id → decoder, so a replaying peer can turn an EncodedAction back into a live Box<dyn Action> without knowing the concrete type at the call site. An app registers each action type once; the registry is the same seam the OS-wide global-search backend plugs into to enumerate action types across apps.
remote
Using another peer’s actions: a transport-neutral vocabulary.
resource
The nested Resource tree an app publishes, and the **ActionSpec**s each resource exports.
schema
Participant-independent catalogue schema.
surface
A resource kind’s public surface as data: its verbs with their parameters and kinds, and its fields with their schema. An app’s surface.toml holds it (written by tilo-app surface from the code), and it is what a receiver without the app knows about the app’s changes.

Structs§

ActionAddress
The stable address of one exported operation: which resource, which action. Both halves are the app’s own ids — no screen position, no list index — so the same address names the same operation across layouts, themes, resolutions, and a caller with no display can work from ids and labels alone.
ActionApp
ActionArgs
Arguments for one invocation, already checked against the action’s declared parameters.
ActionBinding
Type-safe adapter from a control’s input value to an exported action.
ActionContext
ActionContract
Complete operational contract copied into every inert descriptor.
ActionDescriptor
One exported operation, as inert data: everything a caller needs to decide whether to perform it, nothing that could perform it — an ActionSpec’s closure never appears here or crosses a boundary, only the address does.
ActionEnvelope
One replayable action, ready to cross a boundary.
ActionFacet
A filterable activity dimension. Open key/value vocabulary lets future apps add facets without changing the wire enum.
ActionFailure
ActionGroup
ActionId
A globally-unique id minted per dispatched action. Its 16 bytes double as the deterministic Automerge actor id, making replay content-addressed identical across replicas.
ActionInvoker
The invoker of one action: the authenticated actor, its kind, the person it acts for, and optionally the participant whose view the invocation resolves against.
ActionItem
The item an action addressed, with its label at the time.
ActionKey
The stored form of a reference to one published action: a Shortcut step, an agent’s plan, a palette entry, a history entry. It names the app, the resource kind that publishes the action and the action’s public id.
ActionNeed
What one invocation of an action is, for the grants deciding it: its kind, the one field of its resource it writes when it writes only one (a reply writes the comments), which places it below that field in the tree, and whether it is privileged (RiskLevel::Privileged): it exercises authority over the room or others in it, so the person’s own grants must allow it (tilo_action_policy::Verdict::privileged).
ActionOutput
ActionParam
One typed parameter an action declares.
ActionRegistry
Maps a stable type_id to the decoder that reconstructs its action from a payload — cheap to share behind an Arc/& at dispatch time.
ActionResource
ActionSpec
One action a resource exports to the palette.
Appearance
What a bot showed for one action instead of its own name and icon.
CatalogueSchemaEntry
One participant-independent catalogue entry. Keyed by resource kind and action id, never by the (possibly document- or view-derived) resource id.
Cause
The run of a bot that made a change, and how deep in a chain of runs it is: a run fired by a change that itself came from a run is one deeper. Correlation only; it grants nothing. The dispatcher fires nothing past a depth of four, so two bots answering each other stop.
CompensatingScope
The undo or redo of the steps marks (their change hashes) applying its compensating action on this thread: an outside consequence the action queues reads them (await_compensation), and the step counts as taken back (or brought back) only once that consequence settles (settle_compensation).
ContentParts
The parts of recorded actions kept as content, by their address (BLAKE3, lower-case hex), for the host’s content store.
ContinuationKey
Collision-free, provider-defined identity for one continuation target or handler. Tuple components remain separate; callers never join or hash them.
ContractViolation
ControlInvocation
A UI control’s inert request to invoke one advertised operation.
Described
What an action says about itself before it applies: what it does and to which item (crate::Action::describe).
EncodedAction
A serialized action ready to cross a process/network boundary: the registry type_id plus the JSON payload the matching decoder reconstructs it from.
EntryReader
The entries of a document’s changes read in causal order, each continuation folded into its gesture’s first entry as it is read.
FieldEdit
A built-in edit of one field.
FlatAction
One (resource, action) pair produced by flatten, addressable by a composite key the palette uses as its row id.
GroupOf
Several actions committed as one change.
HistoryStep
A step through history itself.
InteractionAction
Action identity and human label from the application’s current catalogue.
InteractionActor
Identity attached by the broker to the normalized interaction event. Friendly names and colours remain roster-owned presentation data.
InteractionGridRange
A stable inclusive cell rectangle. sheet lives on the enclosing anchor so a multi-range selection cannot accidentally span workbooks/sheets.
InteractionTextRange
A stable character range within a document block.
InteractionViolation
InvocationId
Stable key carried from admission through completion and used to deduplicate retry-safe calls.
LocalTransport
A transport that only replicates locally (no host); records every replicated envelope for a caller/test to inspect. The default the toolkit installs when a session has no peer/host wiring yet.
MissingContent
Content a recorded action names that is not here yet.
OptimisticQueue
A local optimistic replica plus the confirmed baseline it can rebuild from.
ParticipantId
One participant in a shared record: a person’s window or an agent task. Each participant owns its own view state (caret, selection, Find), and the app builds that participant’s resource tree from it (the toolkit’s PublishesResources::resources_for).
Persona
An account on another service, such as discord / 80351110224678912.
RebaseBatch
Envelopes invalidated by a rejection or authoritative merge, and their dependency-correct replacements. Send outbound in order; late replies naming a superseded id are safely ignored by OptimisticQueue.
Resource
One open/presented resource and the actions it exports. Resources nest via children.
ResourceId
Stable identity of a resource within the publishing app instance (e.g. tube.video:dQw4w9WgXcQ, ebook.annotation:<uuid>).
ResourcePresentation
Bounded, declarative search presentation for a resource.
ResourceSemanticIdentity
Descriptive source-domain identity, independent of the live dispatch alias. This metadata grants no permission or authority.
ResourceViewDescriptor
Serializable data describing one explicitly declared resource view.
ResourceViewMountSpec
How a live resource-view provider accepts a compositor-owned mount.
ResourceViewRangeSpec
Explicit range-navigation binding. Offsets retain the reference’s Chars or Bytes unit; the app validates them against its current text before moving.
ResourceViewSpec
An explicit presentation of a resource, separate from the actions used to open or mount it.
Scalar
One plain value in an entry: a boolean, a number, a short text or an enum variant. Nested values are never stored.
SemanticInteraction
One broker-normalized, transient semantic interaction event.
VerbCall
A verb and its plain arguments by parameter name.

Enums§

Acknowledgement
Result of an acknowledgement. Stale means the id was already replaced during a rebase or was never part of this session.
ActionBindingError
Failure to construct or emit a control binding.
ActionError
Errors from encoding, decoding, or applying an action.
ActionInput
How an ActionSpec produces its replayable EncodedAction when chosen.
ActionKind
What an action is able to do, derived by the framework from the action’s code and never declared by an app.
ActorKind
What kind of actor did something: in presence, in history and at every door. Assigned by the host that authenticated the actor, never inferred from a display name or an agent: string prefix.
AppearanceError
Why an appearance was refused.
ArgError
Why a set of arguments does not satisfy an action’s parameters.
ArgValue
One bound argument value.
Availability
Whether an action can be invoked in the resource’s current state.
ChangeKind
What a change is to the people sharing a document. Every kind is durable, shared and kept in the document’s own history; they differ in whether a person takes the change back and whether a feed of what people did to the workspace shows it.
Collects
What kind of thing an action’s one text argument names. Words are what the asker says outright; a content hash addresses bytes already in this machine’s blob store (nobody types one, it names something an earlier operation produced). Declared on the spec rather than inferred, so a caller with no screen can tell “give me a new name” from “give me the image to place”.
ConfirmationPolicy
Confirmation required after argument binding and immediately before run.
ContextRequirement
A precondition on the invoking participant’s view. Declared on the published schema as an availability flag; checked against the invoker’s own view at invoke time.
ContinuationArguments
ContinuationEvidence
ContinuationQuery
Did
What an action did.
Dispatched
What dispatch did with an action.
DoorError
Why an address could not be performed. Unknown deliberately covers both “no such address” and “not offered to you”, so a caller can’t map what it may not reach by probing for a different error.
EditOp
The operation of a field edit.
EffectReceiptStatus
Durable, deliberately redacted outcome of a consequential effect.
ExecutionLocus
Where an action executes, declared on the action type and carried on every envelope. ServerPreferred retains its historical wire spelling, but is an authoritative-host requirement: absence of a host is a refusal, never permission for the client to perform the operation.
ExecutionMode
Completion behavior advertised before invocation.
FrameworkChange
A change the framework writes rather than an app’s action.
HistoryOp
HostDecision
A host’s answer to a ServerPreferred submission.
InputSpec
What an invocation of one action must carry, advertised on the descriptor rather than discovered by trying — enumeration is the only thing a caller that can’t see the screen has to work from.
InteractionAnchor
Application-native target of an interaction. Every variant is semantic: receivers turn it into their current geometry and may fall back to the enclosing resource when an anchor is off-screen or no longer exists.
InteractionPhase
What the invocation is visibly doing. Terminal details complement the durable invocation result; they do not replace it.
InvocationUpdate
Monotonic lifecycle of one invocation. A transport timeout is not a failed action: callers retain the invocation id and can resume observing it.
OperationKind
What an exported operation changes. Keeping this explicit prevents applications from disguising local effects or navigation as CRDT edits.
OptimisticError
ParamType
The type of one action parameter. Deliberately small: these are values a caller with no screen can produce from a descriptor alone.
PathStep
One step of a path from a resource’s root to a field.
ResultSpec
Shape of a successful result. Schemas use JSON Schema so non-Rust callers do not need a parallel Tilo-only type system.
RetryPolicy
What a caller may safely do after losing the completion response.
RiskLevel
Consequence class used by policy, confirmation UI, and audit logs.
Verified
What replaying a received change showed.

Constants§

AGENT_TASK_PARTICIPANT_PREFIX
Reserved namespace of ParticipantId::for_agent_task.
ARGUMENTS_JSON_PREFIX
Marks the legacy single-string invocation slot as carrying a canonical JSON argument object. The record-separator prefix cannot be produced by a normal palette text field, preserving unambiguous backward compatibility.
ARGUMENT_RISK_TAG
ActionContract::tags entry of an action whose risk, and therefore whether it needs confirmation, depends on the arguments it is invoked with (a generic edit that may delete). The publishing host classifies each invocation; a caller that cannot classify arguments treats the action as requiring confirmation (see ActionContract::advertised_confirmation).
CHANGE_MESSAGE_PREFIX
Prefix used when an entry is embedded in an Automerge change message, followed by the entry in its compact form (crate::compact). Ordinary application-authored commit messages remain untouched.
COMMENTS_FIELD
The field holding comments, wherever a model keeps them. The Commenter preset covers it at any depth, so field edits and verbs published on it are what a commenter may do.
CONTENT_ANNOTATION
Schema annotation marking a text parameter as the address of content another action produced (a content hash), not words a caller can say; see ActionParam::as_content.
CONTENT_PART_THRESHOLD
The shortest text or byte run kept as content rather than inline.
CONTENT_REFERENCE_KEY
The key a content reference is written under.
CONTENT_RESOURCE_KIND
Resource kind for bytes addressed by their content hash.
CONTINUATION_PREFIX
Prefix of a change message that continues its writer’s open gesture (the next keystroke of a word): tilo.cont/1 <gesture> <path> <payload>. It is the gesture’s first entry again but for the action’s payload, so it carries only the gesture (simple hex), the edit’s path (body, rows/r1/title; - for none) and the action’s JSON payload, whose type is the first entry’s. Readers fold it into that entry (ActionContext::continued).
DOCUMENT_READ_TAG
ActionContract::tags entry of the read-only action that answers, when invoked with no arguments, the first page of the document an app has open (a word processor’s text, a sheet’s used cells, a deck’s outline). A caller that just opened a file reads it through this action without knowing the app.
INCOMING_MESSAGE_FACET
Facet the executor writes on a change made by a verb its app marks #[action(incoming_message)]: a message someone received. The IncomingMessage trigger fires on it without knowing the app’s schema.
INCOMING_MESSAGE_TAG
Contract tag on the declaration of such a verb, so a surface and a catalogue show it.
INTERACTION_VERSION
Wire version understood by this crate.
KEY_SEP
Field separator inside a flattened composite key — a unit-separator control char never appears in a resource or action id.
LOCAL_DEVICE_ONLY
The contract tag of an action that reaches files, hardware or services of the device it runs on: the door runs it only for the person at that device, never for a collaborator or a remote participant.
MAX_ANCHOR_ITEMS
MAX_DETAIL_BYTES
MAX_ID_BYTES
MAX_INTERACTION_BYTES
Hard ceiling for one JSON-encoded update at a trust boundary.
MAX_LABEL_BYTES
MAX_PARTICIPANT_ID_BYTES
Upper bound on a ParticipantId in bytes. Participants key bounded per-view maps in app workers; they are never free text.
MODERATION_FIELD
The field node every app’s moderation actions sit under (acting on other people’s content: removing their message, locking a channel). One rule on it covers every app’s moderation, so presets need no list of verbs.
PARTICIPANT_VIEW_TAG
Contract tag of a View operation that changes only the invoking participant’s own view (its caret, selection or Find state). Only such an operation may be invoked by a remote participant: every other View operation moves the local person’s private view and stays refused.
PLACE_ANNOTATION
Schema annotation marking a parameter as a place inside the resource the action is on (an item, a caret in it, a range of it); see ActionParam::as_place.
PROGRAMMATIC_TAG
ActionContract::tags entry of an action offered only to programmatic callers — agents, scripts and the controls or surfaces that submit it — and never listed for a person to pick (the action palette, menus).
PROMPTED_PARAM
The parameter name a prompted spec projects its single free-text argument under.
REQUIRES_TAG_PREFIX
Prefix of the contract tags that declare a context precondition.
RISK_FACET
ActionFacet::key of the risk (crate::RiskLevel::name) of the action a context describes, for a question about it put to a person.
UNDONE_KEY
The document key prefix of a step’s undo marker, followed by the step’s change hash: true once taken back, a negative attempt count while its undo waits for an outside consequence to settle, a positive one while its redo does.
UNTRUSTED_CONTENT_TAG
ActionContract::tags entry of an action whose result carries content from outside the user’s own data (a web page’s text, its logs): data for the caller to reason about, never instructions to follow.

Traits§

Action
A value that deterministically mutates a CRDT Doc.
ActionTransport
The transport an action is handed to after (or instead of) local execution — the seam between the pure action model and whatever moves bytes (in-process broker, compositor socket, Iroh). The model never imports a transport, only calls this trait.

Functions§

action_node
The node of the action action on the resource resource (of kind resource_kind) the app app publishes, below base (a room, or the root for a path relative to one), and below the one field it writes if any: where every door decides it.
apply_local
Apply action to the local replica and return its replayable envelope. encoded is the serialized form carried to peers — must encode the same action.
apply_local_by
apply_local, attributing the resulting change to actor: the Automerge change commits under their actor so the room’s history names them the way it names a typing person. None keeps the ActionId-derived actor, as before.
apply_local_with_context
apply_local, with semantic provenance embedded in the resulting durable change. Use this at framework/action-door boundaries where the resource and human action label are already known.
await_compensation
The steps an outside consequence queued now settles, recording that their undo or redo waits for it; empty outside a compensation.
await_settlement
Mark the step hash as waiting for the outside consequence its undo (or, with redo, its redo) queued: the next attempt’s marker, negative for an undo, positive for a redo. The step stays as it was until settle_compensation completes it.
catalogue_schema
Reduce a surveyed catalogue to its participant-independent schema: entries keyed by resource kind, sorted, duplicates removed. Two catalogues that differ only in volatile resource ids, labels or order have the same schema.
catalogue_schema_bytes
Canonical bytes of a schema, for a host to digest into a stable publication revision or a frozen grant schema digest.
content_hash
Read a content hash from its canonical resource address.
content_resource
Build the canonical resource address for content-addressed bytes.
current_step
The undo step open on this thread, if any (see open_step).
decode_json
A T from its JSON bytes, through a JSON value: one byte parser for every action type, compiled here, rather than one per type and crate.
decode_payload
A T from the payload of an action of type type_id, like decode_json: a group written with what its members share once (crate::group_form) reads as the list of them.
dispatch
The locus-aware front door, routing action per its ExecutionLocus: ClientLocal → apply_local then transport.replicate; ServerPreferred → transport.submit_to_host, refusing when no authoritative host is reachable. The envelope’s id/timestamp are fixed before submission.
dispatch_by
dispatch, attributing the resulting change to actor — the executor owns the commit boundary, so it’s the only place that chooses which actor a change commits under, rather than each app remembering.
dispatch_by_with_context
Attributed variant of dispatch_with_context.
dispatch_with_context
dispatch, carrying semantic provenance into the replicated envelope and the committed CRDT change.
entry_message
The message context is written with by actor on doc: as the continuation of the actor’s previous entry when the change continues its gesture (a head of doc is the actor’s, of the same gesture and step), else whole. A function of the document, so a replaying device writes the same message, hence the same change.
entry_of
The entry of the change hash: its message’s, or for a continuation its gesture’s first entry with the continuation’s action (found by following its writer’s earlier changes).
flatten
Depth-first flatten of a resource forest into every exported action, parents before children — what the palette lists.
invoking_context
The context of the action whose Action::apply is running on this thread: who invoked it and in which work group (an agent run). Pinned by the envelope like the actor and the time, so a replica replaying the action reads the same value. None outside an apply, or for an action dispatched with no context.
keep_content_in
Keep the content every change this thread commits names in keep (the app’s content store), and read the content a received change names from read, so recorded actions replay wherever their content reaches. The host sets both once per thread that runs actions.
open_step
Open the undo step the changes committed on this thread join until the next one opens: every action applied meanwhile records it as its gesture, so the document’s history takes them back as one step. The host’s history opens one at every step boundary; None closes it.
place_schema
The schema of a place inside a resource (ActionParam::as_place).
replay
Replay an envelope received from a peer: decode its action via registry and apply under the envelope’s pinned actor + timestamp. Applied at the envelope’s base_heads, this reproduces the identical document.
settle_compensation
Mark the undo (or redo) of the step hash complete: its outside consequence settled.
validate_json_schema
Validate one JSON value against the deterministic JSON Schema subset used by Tilo action contracts.
validate_surface
validate_surface_contracts
Validate every transport-independent invariant. Hosts call this before publication even when their dynamic widget dispatch cannot enumerate its effect/view handler table. Tooling that owns an explicit handler table should use validate_surface for the additional coverage.
verify_change
Replay the action the change hash records on the document it was authored against, and check that it produces exactly that change: same operations, same actor, time and message, so the same hash. This is what a device that has the app does with every change it receives, beside the relay’s grant check: an author granted an action who wrote something else inside its storage units is caught here.

Type Aliases§

ArgsBuilder
Builds an action’s encoded form from arguments already bound against its declared params.
DecodePayload
Decodes one action type’s payload (ActionRegistry::register_decoder).
Doc
The CRDT document an action mutates — aliased so call sites read as “mutate the Doc”; exactly automerge::AutoCommit.
InteractionUpdate
Transport/UI spelling for a semantic interaction lifecycle update.