HeddleAdmissionControl
Binds warp's opaque Lane tags to a weighted fair-share tree and gates warp's free execution path on entitlement — the whole point of the :kuilt-warp-heddle satellite.
Warp answers where a task runs (the consistent-hash ring) and whose turn (the free claim path). It has no notion of how much any lane may take. This adapter supplies that missing dimension without warp core learning a single fair-share type: it implements warp's opaque AdmissionControl, and warp calls it just before running each task. The adapter maps the task's Lane to a fair-share leaf and reserves one task's worth of that leaf's entitlement; when the task finishes warp calls AdmissionTicket.settle, which completes the reservation and charges the ledger exactly once.
The behaviour that falls out, per warp's contract:
Untagged is free. A task on the Lane.ROOT lane (the default) is admitted immediately with a no-op ticket — no reservation, no ledger touch — so an untagged workload is bit-for-bit today's warp.
Exhaustion defers, never drops. When a lane's leaf has no spare entitlement, FairShareExecution.reserve returns
null; this adapter returnsnulltoo, so warp defers the task (leaves it pending) and re-attempts it on a later claim cycle — work resumes when entitlement flows in.Zero consensus on the hot path. reserve / complete are local reads and writes of already-converged holdings; admitting a task adds no consensus round. The heddle's own ledger replication is coordination-free cloth (a
Quilter), not consensus.
Entitlement itself flows the ordinary heddle way — a consumer advertises demand and calls HeddleNode.schedule to delegate holdings down the tree by weight. Two lanes weighted 3:1 therefore complete tasks in a 3:1 ratio: each lane runs exactly as many tasks as it was delegated entitlement for.
Parameters
the fair-share data plane whose holdings this adapter reserves against — the FairShareExecution surface shared by both front doors, so this accepts either a us.tractat.kuilt.heddle.heddleStatic node (no consensus) or an H5 us.tractat.kuilt.heddle.heddleGoverned node (governed) interchangeably. One asymmetry: a governed node must have enrolled itself before it will author any entitlement — until enroll(self) applies, its write gate is closed, so reserve returns null and schedule delegates nothing and this adapter admits no gated task (#1693, design §13.2).
service units reserved and charged per task. Defaults to 1 — the §14.4 "one unit per task" costing; a caller with variable-cost work supplies a per-descriptor cost via costOf.
per-task cost function; defaults to a flat costPerTask for every descriptor.
See also
Samples
// 1. Build the adapter — warp's opaque AdmissionControl, backed by the fair-share ledger.
val admission = HeddleAdmissionControl(heddle)
// Pass it to a node: WarpNode(selfId, seam, roster, scope, clock = …, registry = …,
// admissionControl = admission, epoch = <per-boot counter>)
// 2. Tag a task into a lane on the producer side.
val interactive: TaskDescriptor =
TaskDescriptor(op = OpId("score"), args = "doc-1".encodeToByteArray())
.inLane("acme/interactive")
check(interactive.lane == Lane("acme/interactive"))
// 3. An untagged task rides the default root lane and is admitted un-gated.
val untagged = TaskDescriptor(op = OpId("score"), args = ByteArray(0))
check(untagged.lane == Lane.ROOT)
check(admission.admit(untagged) === AdmissionTicket.NOOP)