TaskDescriptor
The unit of work that travels across the fabric — the task-descriptor envelope.
One envelope does three jobs:
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-assigned —
hash(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.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.
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
Properties
The opaque location-Affinity this task requires — the "can I execute here" predicate (H8, design §14.6). Defaults to Affinity.Anywhere — no 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.
The opaque fair-share Lane this task rides. Defaults to Lane.ROOT — no 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.
When set, this task is owned by exactly this peer regardless of the hash ring; absent (null) ⇒ ring-assigned.
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
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.