TaskDescriptor

@Serializable
data class TaskDescriptor(val op: OpId, val args: ByteArray = ByteArray(0), val traceparent: String? = null, val pinnedOwner: PeerId? = null, val lane: Lane = Lane.ROOT, val affinity: Affinity = Affinity.Anywhere)

The unit of work that travels across the fabric — the task-descriptor envelope.

One envelope does three jobs:

  1. Routes the work. The claiming peer looks op up in its local OpRegistry and runs its own registered copy with args. The code never crosses the wire; only the name does. By default the task is ring-assignedhash(taskId) picks the owner, decoupling who-runs from whose-data (work-stealing). Set pinnedOwner to override this and route the work to exactly one named peer regardless of the hash ring.

  2. Content-addresses the bobbin (future). Once WASM bobbins ship (warp slices C4/C5), op will double as the content-hash of the bobbin — OpId value = hash of the kernel — so peers can verify what they fetched. For named-op dispatch (C1/C2) the op is a stable symbolic name registered at startup from the same compiled binary.

  3. Carries the trace. traceparent is a W3C Trace Context header value (00-<traceId>-<spanId>-<flags>). Null when no trace context is propagated — tracing is a tuning concern, not load-bearing for dispatch.

ByteArray equality. Kotlin's default == on ByteArray is identity, not content. This class overrides equals and hashCode to use ByteArray.contentEquals / ByteArray.contentHashCode so two descriptors built from the same input compare equal. (Declaring them explicitly also suppresses the data modifier's generated versions — data is here for copy, not for equality.)

Derive a descriptor with copy, never by re-invoking the constructor. Every field is part of the opaque envelope, and most default to a "no requirement" sentinel — so a rebuild that names only the fields it cares about silently resets the rest. That is exactly how WarpNode.enqueueLocal dropped lane and affinity on the floor (#1674). The generated copy is derived from the primary constructor, so it carries every present field and every field added later for free; a hand-rolled rebuild has to be re-audited on each new field, and the compiler will not remind anyone. Keep new envelope fields flowing through copy.

See also

Constructors

Link copied to clipboard
constructor(op: OpId, args: ByteArray = ByteArray(0), traceparent: String? = null, pinnedOwner: PeerId? = null, lane: Lane = Lane.ROOT, affinity: Affinity = Affinity.Anywhere)

Properties

Link copied to clipboard

The opaque location-Affinity this task requires — the "can I execute here" predicate (H8, design §14.6). Defaults to Affinity.Anywhereno requirement, so placement is over the whole roster and an unrestricted descriptor is byte-for-byte unchanged on the wire (CBOR omits a field at its default). When set, warp core hashes the task over only the eligible subset of the roster: the peers whose advertised CapSet satisfies this predicate (see WarpNode.advertiseCapabilities). Eligibility is independent of the lane — a task may carry both — and introduces no conserved quantity, so it never touches the ledger's conservation.

Link copied to clipboard

The serialised arguments passed to Op.invoke on the claiming peer.

Link copied to clipboard
val lane: Lane

The opaque fair-share Lane this task rides. Defaults to Lane.ROOTno lane, the untagged path — so warp core assigns it no meaning and an untagged descriptor is byte-for-byte unchanged on the wire (CBOR omits a field at its default). An enforcement adapter (:kuilt-warp-heddle) binds the tag to a fair-share leaf and gates execution on entitlement; warp core never interprets it.

Link copied to clipboard
val op: OpId

The symbolic name of the operation to dispatch.

Link copied to clipboard

When set, this task is owned by exactly this peer regardless of the hash ring; absent (null) ⇒ ring-assigned.

Link copied to clipboard

W3C Trace Context traceparent header value, or null when no trace context is propagated. Not load-bearing for dispatch — a peer without a tracing back-end behaves identically whether this field is null or present.

Functions

Link copied to clipboard
open operator override fun equals(other: Any?): Boolean
Link copied to clipboard
open override fun hashCode(): Int
Link copied to clipboard
open override fun toString(): String
Link copied to clipboard

Return a copy of this descriptor requiring affinity at its execution site — the producer-side eligibility tagging step, the sibling of TaskDescriptor.inLane(...). Everything else (op, args, trace, pin, lane) is preserved, so eligibility composes with a lane. This is the shipped .where { } surface: build a TaskDescriptor, tag it with where, and enqueue it on a WarpNode. Placement then hashes over the eligible subset.