BitQuirky.Behavior.ExternalService
Public behavior trees and state machines: runtime symbols in BitQuirky.Behavior.ExternalService.
Source snapshot ad0983d00d77.
On this page
Assembly: BitQuirky.Behavior.Runtime
AdapterHandoffDecision
Section titled “AdapterHandoffDecision”Category: External services
enum BitQuirky.Behavior.ExternalService.AdapterHandoffDecisionSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:32-50
Underlying type: byte
Decision an adapter takes when a host migration is announced for a follower with at least one outstanding pending id (R-9 / FR authority handoff).
Members
Section titled “Members”Cancel
Section titled “Cancel”Cancel = 0Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:40
Adapter postsCancelledByHandoff for every outstanding pending id on the supplied follower and stops tracking them. Default for adapters that do not opt into replay.
Resume
Section titled “Resume”Resume = 1Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:49
Adapter supports replay-by-id and intends to re-issue every
outstanding pending id on the new authority. The adapter posts
Issuedfor the same
PendingIdon the new host once it has registered the
replay with the wrapped service.
BakedAuthorityContextCode
Section titled “BakedAuthorityContextCode”Category: External services
enum BitQuirky.Behavior.ExternalService.BakedAuthorityContextCodeSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:146-159
Underlying type: byte
Mirror ofBakedAuthorityContextkept POD-compatible
for inclusion inExternalServiceCommandstructs that
cross Burst boundaries. Numerically identical so the cast is free.
Members
Section titled “Members”ClientPresentation
Section titled “ClientPresentation”ClientPresentation = 2Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:155
The issuing node runs on a client instance for presentation only.
EditorTestOnly
Section titled “EditorTestOnly”EditorTestOnly = 3Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:158
The issuing node runs only in editor tests, never in a shipped session.
HostAuthoritative
Section titled “HostAuthoritative”HostAuthoritative = 1Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:152
The issuing node runs only on the authoritative host instance.
Unknown
Section titled “Unknown”Unknown = 0Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:149
No authority was stamped on the command; the adapter refuses it.
BehaviorMemberService
Section titled “BehaviorMemberService”Category: External services
class BitQuirky.Behavior.ExternalService.BehaviorMemberServiceSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:255-314
Reserved internal service identity and command conventions for deferred member operations (coroutine methods and event conditions) that the member binding runtime services in-process . Deferred member requests travel the same command queue, pending-slot, and completion-ring path as external services so they inherit the proven interruption, reset, target-loss, and stale-generation lifecycle, then complete with an exact behavior result through AppendMemberCompletion.
Responsibilities:
- Name the reserved member service id and the deferred command kinds, and build one exact member request command without allocation.
Does NOT:
- Service immediate member operations, which the host resolves through the runtime instance member request channel and a bounded in-tick microstep.
Members
Section titled “Members”KindCoroutine
Section titled “KindCoroutine”public const int KindCoroutine = 1Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:270
Command kind for a deferred coroutine member operation start.
KindEventCondition
Section titled “KindEventCondition”public const int KindEventCondition = 2Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:273
Command kind for a deferred event condition subscription.
ServiceId
Section titled “ServiceId”public const int ServiceId = -1088674145Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:267
The reserved stable member service id member commands carry. Held as a compile-time
constant so the Burst-compiled shared tick core can compare against it without a
runtime static initializer; it equals
BehaviorStableId.Hash("__bq_member_deferred__"), which
AssertServiceIdMatchesTokenverifies outside Burst.
ServiceToken
Section titled “ServiceToken”public const string ServiceToken = "__bq_member_deferred__"Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:258
The reserved internal member service token, never authored in source.
AssertServiceIdMatchesToken()
Section titled “AssertServiceIdMatchesToken()”public static bool AssertServiceIdMatchesToken()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:279-282
Verifies the compile-timeServiceIdequals the hash of ServiceToken. Called outside Burst so the constant cannot silently drift.
BuildRequest(int commandId, int graphId, int operationIndex, int commandKind, int nodeIndex, uint activationGeneration, EntityId entityId, int frameNumber, BakedAuthorityContextCode authority)
Section titled “BuildRequest(int commandId, int graphId, int operationIndex, int commandKind, int nodeIndex, uint activationGeneration, EntityId entityId, int frameNumber, BakedAuthorityContextCode authority)”public static BitQuirky.Behavior.ExternalService.ExternalServiceCommand BuildRequest(int commandId, int graphId, int operationIndex, int commandKind, int nodeIndex, uint activationGeneration, UnityEngine.EntityId entityId, int frameNumber, BitQuirky.Behavior.ExternalService.BakedAuthorityContextCode authority)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:285-313
Builds one exact deferred member request command.
ExternalServiceCancellationReason
Section titled “ExternalServiceCancellationReason”Category: External services
enum BitQuirky.Behavior.ExternalService.ExternalServiceCancellationReasonSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:319-344
Underlying type: byte
Observable reason outstanding external work was cancelled.
Members
Section titled “Members”Interruption
Section titled “Interruption”Interruption = 7Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:343
An explicit host interruption stopped the active behavior.
LowerPriority
Section titled “LowerPriority”LowerPriority = 3Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:331
A reactive observer interrupted the owning branch.
None = 0Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:322
No cancellation has been recorded.
PeerFailure
Section titled “PeerFailure”PeerFailure = 6Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:340
A failed Parallel state action ended its still-running peers.
Reset = 2Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:328
An explicit runtime reset cancelled the work.
Self = 4Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:334
A Self observer cancelled its own guarded branch.
Timeout
Section titled “Timeout”Timeout = 5Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:337
An expired Time Limit decorator ended its running branch.
Transition
Section titled “Transition”Transition = 1Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:325
A state or behavior transition cancelled the work.
ExternalServiceCommand
Section titled “ExternalServiceCommand”Category: External services
struct BitQuirky.Behavior.ExternalService.ExternalServiceCommandSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:39-139
Burst-safe POD command struct posted by a behavior node tick to its service-id slot of the External Service Command Queue.
The fields are deliberately generic: service-specific payload bytes are encoded inPayload0..Payload4; the adapter on the managed side knows the encoding. Strings, references, and managed handles MUST NOT cross this boundary (FR-012a: tick is Burst-only; managed work happens on adapter side).
Members
Section titled “Members”Authority
Section titled “Authority”public BitQuirky.Behavior.ExternalService.BakedAuthorityContextCode AuthoritySource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:105
Authority of the posting node: adapters that wrap host-only services use this to refuse client posts before issuing.
CancellationReason
Section titled “CancellationReason”public BitQuirky.Behavior.ExternalService.ExternalServiceCancellationReason CancellationReasonSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:121
Lifecycle event that caused a cancellation record.
CauseNodeIndex
Section titled “CauseNodeIndex”public int CauseNodeIndexSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:76
Reactive condition that caused an interruption, or -1 for requests.
CommandId
Section titled “CommandId”public int CommandIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:54
Issue id chosen by the runtime instance posting the command.
Travels back to the node via
PendingIdso the
node can resume on the right request. Distinct from
pendingRequestId: the command-id is the runtime’s
per-follower-per-service issue counter;pendingRequestId
is whatever the wrapped service returns. The adapter records
both in the completion ring.
CommandKind
Section titled “CommandKind”public int CommandKindSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:70
Service-specific command kind code (per-adapter contract).
EntityId
Section titled “EntityId”public UnityEngine.EntityId EntityIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:87
Stable 64-bit identity of the follower entity posting the command
(Unity 6.5EntityId, obtained from the
Entityvia its implicit conversion).
The adapter routes the resolved service request back to this
follower’s pending-id slot, and the runtime matches completion
records on this id so a recycled entity slot cannot resume a
predecessor’s command.
FrameNumber
Section titled “FrameNumber”public int FrameNumberSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:92
Deterministic tick frame on which the command or cancellation was emitted.
GraphId
Section titled “GraphId”public int GraphIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:59
Runtime-local graph identity that owns this command.
IsCancellation
Section titled “IsCancellation”public byte IsCancellationSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:116
One when this record cancels previously issued external work.
Operation
Section titled “Operation”public BitQuirky.Behavior.ExternalService.ExternalServiceOperation OperationSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:42
Identifies whether this command requests or interrupts external work.
OwningNodeIndex
Section titled “OwningNodeIndex”public int OwningNodeIndexSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:73
Baked node that owns the request being issued or interrupted.
Payload0
Section titled “Payload0”public int Payload0Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:127
First payload word. The command kind decides what it means, and a float travels as its raw bit pattern: a Move To command carries target x here.
Payload1
Section titled “Payload1”public int Payload1Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:130
Second payload word; target y for a Move To command.
Payload2
Section titled “Payload2”public int Payload2Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:133
Third payload word; target z for a Move To command.
Payload3
Section titled “Payload3”public int Payload3Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:136
Fourth payload word; speed for a Move To command.
Payload4
Section titled “Payload4”public int Payload4Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:138
Fifth generic payload word, added during product iteration 2.
PendingIdSlotOffset
Section titled “PendingIdSlotOffset”public int PendingIdSlotOffsetSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:99
Blackboard byte offset where the issuedpendingRequestId
will be written byExternalServiceCompletionDispatcher.
-1 if the node fires-and-forgets (no resume).
RequiresCompletion
Section titled “RequiresCompletion”public byte RequiresCompletionSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:111
One when the posting action waits for a completion-ring outcome; zero for an immediate emitted command.
ServiceId
Section titled “ServiceId”public int ServiceIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:65
Globally stable service-id hash derived from the service token. Adapters filter on this to drain only their slot.
ExternalServiceCommandQueue
Section titled “ExternalServiceCommandQueue”Category: External services
class BitQuirky.Behavior.ExternalService.ExternalServiceCommandQueueSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:371-505
Implements: IDisposable
Burst-friendly producer-consumer command queue. Each producer (a behavior tick job) appends commands; each consumer (one managed adapter on the main thread) drains the queue once per frame and filters onServiceId.
Responsibilities:
- Own the underlying
NativeQueue'1and provide parallel-writer / writer / reader views suitable for Burst tick jobs and main-thread adapter drains. - Track a running command-id counter so callers can stamp unique ids without a managed allocator.
- Provide aDrainAllhelper that copies pending commands into a managed list (used by adapters).
Does NOT:
- Know about the wrapped service’s command kinds: it is service- agnostic. Each adapter interprets its own slot.
- Allocate managed garbage on the hot path.
- Mutate consumer gameplay data directly: that is the adapter’s job, governed by .
Members
Section titled “Members”public int Count { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:394
Commands posted but not yet drained.
IsCreated
Section titled “IsCreated”public bool IsCreated { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:397
False once disposed, or before the native queue was allocated.
public Unity.Collections.NativeQueue<BitQuirky.Behavior.ExternalService.ExternalServiceCommand> Raw { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:410
The owned native queue, for callers that must hand it to a job directly. The queue still belongs to this instance: never dispose it through this handle.
ExternalServiceCommandQueue(Allocator allocator)
Section titled “ExternalServiceCommandQueue(Allocator allocator)”public ExternalServiceCommandQueue(Unity.Collections.Allocator allocator = Persistent)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:387-391
Allocates the native command queue fromallocatorand starts
command ids at one, so zero always reads as “no command”.
AsParallelWriter()
Section titled “AsParallelWriter()”public Unity.Collections.NativeQueue<BitQuirky.Behavior.ExternalService.ExternalServiceCommand>.ParallelWriter AsParallelWriter()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:403-404
Returns a writer a Burst tick job can append commands through from several threads at once. The writer stays valid until this queue is disposed.
Dispose()
Section titled “Dispose()”public void Dispose()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:482-487
Releases the native queue. Safe to call more than once; any commands still pending are discarded, so drain before disposing if adapters still need them.
DrainAll(List<ExternalServiceCommand> dest)
Section titled “DrainAll(List<ExternalServiceCommand> dest)”public void DrainAll(System.Collections.Generic.List<BitQuirky.Behavior.ExternalService.ExternalServiceCommand> dest)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:449-456
Drain every pending command intodest. The
caller filters onServiceId;
in practice each adapter calls this once per frame and ignores
other slots.
DrainPartitioned(Dictionary<int, List<ExternalServiceCommand>> bins)
Section titled “DrainPartitioned(Dictionary<int, List<ExternalServiceCommand>> bins)”public void DrainPartitioned(System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<BitQuirky.Behavior.ExternalService.ExternalServiceCommand>> bins)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:463-476
Drain every pending command, partitioning by service-id into the supplied dictionary. Allocates only inside the dictionary the caller passes in.
Enqueue(ExternalServiceCommand command)
Section titled “Enqueue(ExternalServiceCommand command)”public int Enqueue(BitQuirky.Behavior.ExternalService.ExternalServiceCommand command)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:433-441
Append a command from the main thread (typically a test or a validator). Tick jobs useAsParallelWriter.
From(BakedAuthorityContext baked)
Section titled “From(BakedAuthorityContext baked)”public static BitQuirky.Behavior.ExternalService.BakedAuthorityContextCode From(BitQuirky.Behavior.Baked.BakedAuthorityContext baked)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:494-495
Helper conversion:BakedAuthorityContext→
BakedAuthorityContextCode. Numerically identical;
kept explicit so the runtime call site is searchable.
ToBaked(BakedAuthorityContextCode code)
Section titled “ToBaked(BakedAuthorityContextCode code)”public static BitQuirky.Behavior.Baked.BakedAuthorityContext ToBaked(BitQuirky.Behavior.ExternalService.BakedAuthorityContextCode code)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:501-502
Converts the POD authority code back toBakedAuthorityContext. The two are
numerically identical, so this only makes the call site searchable.
TryDequeue(out ExternalServiceCommand command)
Section titled “TryDequeue(out ExternalServiceCommand command)”public bool TryDequeue(out BitQuirky.Behavior.ExternalService.ExternalServiceCommand command)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:415-416
Remove the next command without allocating or exposing the owned queue container.
ExternalServiceCompletionRecord
Section titled “ExternalServiceCompletionRecord”Category: External services
struct BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRecordSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:85-156
One row of the External Service Completion Ring. Burst-friendly POD so the tick job can scan it without managed indirection.
Members
Section titled “Members”BehaviorResultOverride
Section titled “BehaviorResultOverride”public byte BehaviorResultOverrideSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:129
Exact behavior result code (mirror of
BitQuirky.Behavior.Execution.BehaviorResultCode) carried by a member
completion. Zero leaves the coarseOutcomemapping in force; a
non-zero value is the exact result the resuming node adopts, so an event condition
can complete with an authored failure and a status method can propagate a status
beyond success and failure .
CommandId
Section titled “CommandId”public int CommandIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:90
Mirror ofCommandId.
EntityId
Section titled “EntityId”public UnityEngine.EntityId EntityIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:113
Stable 64-bit identity of the follower entity this record belongs
to (Unity 6.5EntityId). The runtime
instance reads only its own rows, matching on this id; because the
id encodes the entity’s generation, a record left by a destroyed
agent never matches a successor that recycles the slot.
FrameStamp
Section titled “FrameStamp”public int FrameStampSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:155
Host frame at which the record was written. Retained asynchronous outcomes remain eligible while their command, service, and entity identity match pending work; the runtime selects the matching record with the latest stamp.
HasResultValue
Section titled “HasResultValue”public byte HasResultValueSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:132
One when this completion carries a typed result value to write back.
Outcome
Section titled “Outcome”public BitQuirky.Behavior.ExternalService.ExternalServiceOutcome OutcomeSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:119
Stage this row reports: never written, issued, completed, failed, refused before it was issued, or cancelled by an authority handoff.
OutcomeDetailId
Section titled “OutcomeDetailId”public int OutcomeDetailIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:142
Adapter-defined typed reason code (e.g.path-impossible,
animation-interrupted). Surfaces through
follower.behavior-report.
PendingId
Section titled “PendingId”public int PendingIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:98
Service-side request id (e.g.pathRequestId) returned by
the wrapped service. May equalCommandIdif the
adapter chooses to reuse it; the runtime does not require
equality.
Reserved2
Section titled “Reserved2”public byte Reserved2Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:135
Explicit padding that keeps the record layout stable; carries no meaning.
ResultValueBits
Section titled “ResultValueBits”public long ResultValueBitsSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:148
Optional typed result value bits a member completion writes back (little-endian value bits or an IEEE 754 bit pattern), valid only whenHasResultValueis one.
ServiceId
Section titled “ServiceId”public int ServiceIdSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:104
Interned service-id (matches ServiceId).
ExternalServiceCompletionRing
Section titled “ExternalServiceCompletionRing”Category: External services
class BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRingSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:184-400
Implements: IDisposable
Bounded ring buffer the managed adapter writes to (issue + outcome records) and the Burst tick job reads (resume decisions). Sized at construction; older rows are overwritten when the ring is full: the buffer is FRAME-LIFETIME, not request-lifetime, so adapters MUST size it to comfortably hold one frame’s worth of completions across all followers.
Responsibilities:
- Own the underlying
NativeArray'1+ write cursor. - Provide append helpers safe to call from the main thread (the adapter side); the read side is Burst-callable and uses a slim read-only view (ReadView).
- Stamp the current frame on every record so stale outcomes are ignored on later ticks.
Does NOT:
- Synchronize across multiple writers: the contract is
single-writer / many-reader. Each adapter is the sole writer for
its
ServiceIdrows on a single ring. - Allocate per-record garbage.
- Decide what to do with the records; that’s the runtime instance’s resume logic.
Members
Section titled “Members”Capacity
Section titled “Capacity”public int Capacity { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:219
Number of record slots, fixed at construction. Appending beyond it overwrites the oldest record, so size it for one frame of completions across every follower.
IsCreated
Section titled “IsCreated”public bool IsCreated { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:222
False once disposed, or before the buffer was allocated.
Records
Section titled “Records”public Unity.Collections.NativeArray<BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRecord> Records { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:228
The owned record buffer, for callers that must hand it to a job directly; the ring keeps ownership. PreferGetReadViewfor reading.
ExternalServiceCompletionRing(int capacity, Allocator allocator)
Section titled “ExternalServiceCompletionRing(int capacity, Allocator allocator)”public ExternalServiceCompletionRing(int capacity, Unity.Collections.Allocator allocator = Persistent)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:203-213
Allocates a cleared ring ofcapacityrecords from
allocatorand starts the write cursor at zero.
Exceptions
ArgumentOutOfRangeException:capacityis zero or negative.
Append(ExternalServiceCompletionRecord record)
Section titled “Append(ExternalServiceCompletionRecord record)”public void Append(BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRecord record)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:241-249
Append (or overwrite the oldest slot of) one record. Single-
writer per ring perServiceIdis the contract; the
adapter is responsible for serializing its own writes.
AppendIssued(int commandId, int pendingId, int serviceId, EntityId entityId, int frameStamp)
Section titled “AppendIssued(int commandId, int pendingId, int serviceId, EntityId entityId, int frameStamp)”public void AppendIssued(int commandId, int pendingId, int serviceId, UnityEngine.EntityId entityId, int frameStamp)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:255-267
Convenience builder forIssued records.
AppendMemberCompletion(int commandId, int serviceId, EntityId entityId, byte behaviorResultOverride, bool hasResultValue, long resultValueBits, int frameStamp)
Section titled “AppendMemberCompletion(int commandId, int serviceId, EntityId entityId, byte behaviorResultOverride, bool hasResultValue, long resultValueBits, int frameStamp)”public void AppendMemberCompletion(int commandId, int serviceId, UnityEngine.EntityId entityId, byte behaviorResultOverride, bool hasResultValue, long resultValueBits, int frameStamp)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:296-317
Append one member completion carrying an exact behavior result and an optional typed
result value, used by the member binding runtime for coroutine and event completions
.behaviorResultOverridemirrors
BitQuirky.Behavior.Execution.BehaviorResultCode.
AppendOutcome(int commandId, int pendingId, int serviceId, EntityId entityId, ExternalServiceOutcome outcome, int outcomeDetailId, int frameStamp)
Section titled “AppendOutcome(int commandId, int pendingId, int serviceId, EntityId entityId, ExternalServiceOutcome outcome, int outcomeDetailId, int frameStamp)”public void AppendOutcome(int commandId, int pendingId, int serviceId, UnityEngine.EntityId entityId, BitQuirky.Behavior.ExternalService.ExternalServiceOutcome outcome, int outcomeDetailId, int frameStamp)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:274-288
Appends the terminal outcome of one issued command, with the adapter’s typed detail
code, so the waiting node resumes on a later tick.
frameStampis the host frame the outcome was produced on.
Clear()
Section titled “Clear()”public void Clear()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:322-329
Reset the ring (test helper / shut-down).
Dispose()
Section titled “Dispose()”public void Dispose()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:335-341
Releases the record buffer and the write cursor. Safe to call more than once, and any records the runtime has not read yet are lost.
GetReadView()
Section titled “GetReadView()”public BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRing.ReadView GetReadView()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:234
Snapshot the ring’s contents as a read-only view. Pass into Burst jobs by value.
ExternalServiceFrameContext
Section titled “ExternalServiceFrameContext”Category: External services
class BitQuirky.Behavior.ExternalService.ExternalServiceFrameContextSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:62-87
Frame-scoped context supplied to an adapter’s DrainAndDispatchcall. The adapter reads the queue, issues calls into the wrapped service, and writes outcome records into the completion ring.
Members
Section titled “Members”CompletionRing
Section titled “CompletionRing”public BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRing CompletionRing { get; set; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:77
Ring the adapter writes issue and outcome records to, so waiting nodes resume on a later tick.
FrameNumber
Section titled “FrameNumber”public int FrameNumber { get; set; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:65
Host frame this drain belongs to; stamp it on every record written.
PrePartitionedCommands
Section titled “PrePartitionedCommands”public System.Collections.Generic.IReadOnlyList<BitQuirky.Behavior.ExternalService.ExternalServiceCommand> PrePartitionedCommands { get; set; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:86
Optional pre-partitioned commands. The DrainPartitioned helper lets a host loop drain once and route to multiple adapters. When this is non-null, the adapter MUST NOT drain the queue itself.
public BitQuirky.Behavior.ExternalService.ExternalServiceCommandQueue Queue { get; set; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:71
Queue of commands the tick posted. Drain it unless PrePartitionedCommandsis supplied.
ExternalServiceInterruption
Section titled “ExternalServiceInterruption”Category: External services
readonly struct BitQuirky.Behavior.ExternalService.ExternalServiceInterruptionSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:188-236
Targeted interruption data presented to an interruptible GameObject service adapter.
Responsibilities:
- Identify the agent, request, service, owning node, cause condition, and selected frame.
Does NOT:
- Invoke callbacks or imply a Success or Failure completion.
Members
Section titled “Members”CauseNodeIndex
Section titled “CauseNodeIndex”public int CauseNodeIndex { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:220
Gets the baked reactive condition that caused interruption.
CommandId
Section titled “CommandId”public int CommandId { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:211
Gets the active request identity.
EntityId
Section titled “EntityId”public UnityEngine.EntityId EntityId { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:208
Gets the stable identity of the agent that owns the request.
FrameNumber
Section titled “FrameNumber”public int FrameNumber { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:223
Gets the selected frame in which interruption occurred.
OwningNodeIndex
Section titled “OwningNodeIndex”public int OwningNodeIndex { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:217
Gets the baked node that owns the interrupted request.
ServiceId
Section titled “ServiceId”public int ServiceId { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:214
Gets the stable service identity.
ExternalServiceInterruption(EntityId entityId, int commandId, int serviceId, int owningNodeIndex, int causeNodeIndex, int frameNumber)
Section titled “ExternalServiceInterruption(EntityId entityId, int commandId, int serviceId, int owningNodeIndex, int causeNodeIndex, int frameNumber)”public ExternalServiceInterruption(UnityEngine.EntityId entityId, int commandId, int serviceId, int owningNodeIndex, int causeNodeIndex, int frameNumber)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:191-205
Creates targeted interruption data for one active external request.
From(in ExternalServiceCommand command)
Section titled “From(in ExternalServiceCommand command)”public static BitQuirky.Behavior.ExternalService.ExternalServiceInterruption From(in BitQuirky.Behavior.ExternalService.ExternalServiceCommand command)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:226-235
Creates interruption data from one transported command.
ExternalServiceOperation
Section titled “ExternalServiceOperation”Category: External services
enum BitQuirky.Behavior.ExternalService.ExternalServiceOperationSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:170-177
Underlying type: byte
Additive operation carried by external-service commands.
Responsibilities:
- Distinguish existing requests from targeted synchronous interruptions.
Does NOT:
- Define service-specific payloads or lifecycle outcomes.
Members
Section titled “Members”Interrupt
Section titled “Interrupt”Interrupt = 1Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:176
Stop the identified active request without publishing a completion.
Request
Section titled “Request”Request = 0Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCommandQueue.cs:173
Issue existing external work. The zero value preserves prior commands.
ExternalServiceOutcome
Section titled “ExternalServiceOutcome”Category: External services
enum BitQuirky.Behavior.ExternalService.ExternalServiceOutcomeSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:32-75
Underlying type: byte
Outcome of a service request after the adapter has dispatched it and (where applicable) heard back from the wrapped service.
Members
Section titled “Members”CancelledByHandoff
Section titled “CancelledByHandoff”CancelledByHandoff = 5Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:74
Authority handoff invalidated the request before completion (R-9; seeAuthorityHandoffHandler).
Completed
Section titled “Completed”Completed = 2Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:54
Wrapped service finished the work. Resume the node with
success(or whatever payload the node tick reads from
the slots the adapter filled).
Failed
Section titled “Failed”Failed = 3Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:61
Wrapped service finished the work with a typed failure. Resume
the node withfailure+ the appropriate typed reason
.
Issued
Section titled “Issued”Issued = 1Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:47
Adapter accepted the command and obtained a request id from the wrapped service. Resume on the slot once outcome flips to Completed / Failed / Refused/ CancelledByHandoff.
None = 0Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:39
Slot is empty / never written. Distinct from Issuedso the runtime does not mistake a never- written slot for an in-flight one.
Refused
Section titled “Refused”Refused = 4Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:68
Adapter refused the request before issuing (queue full,
impossible at issue time). Maps to the
external-service-refusedtyped reason on the node.
IBehaviorSteppedService
Section titled “IBehaviorSteppedService”Category: External services
interface BitQuirky.Behavior.ExternalService.IBehaviorSteppedServiceSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IBehaviorSteppedService.cs:14-27
Explicit lifecycle for a GameObject service whose active work advances by selected steps.
Responsibilities:
- Advance, pause, resume, and stop frame-progressing service work.
Does NOT:
- Drain commands, bind blackboard input, or imply interruption support.
Members
Section titled “Members”Advance(float deltaTime, int frameNumber)
Section titled “Advance(float deltaTime, int frameNumber)”void Advance(float deltaTime, int frameNumber)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IBehaviorSteppedService.cs:17
Advances active work for one selected behavior step.
Pause()
Section titled “Pause()”void Pause()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IBehaviorSteppedService.cs:20
Pauses active work without changing its request identity.
Resume()
Section titled “Resume()”void Resume()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IBehaviorSteppedService.cs:23
Resumes work paused by the agent lifecycle.
Stop()
Section titled “Stop()”void Stop()Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IBehaviorSteppedService.cs:26
Stops any active work during agent disposal or reset.
IExternalServiceAdapter
Section titled “IExternalServiceAdapter”Category: External services
interface BitQuirky.Behavior.ExternalService.IExternalServiceAdapterSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:117-161
Managed-side bridge contract every External Service Adapter must
satisfy. Implementations areGameLogicScriptableObjects in
Layer 3; see.
Responsibilities:
- Declare the stable service-id slot the adapter owns (ServiceId).
- Drain that slot from the External Service Command Queue once per frame on the main thread.
- Issue managed calls into the wrapped service; write Issued / Completed / Failed / Refused records into the completion ring.
- Honour
OnAuthorityHandoffper the contract: OnAuthorityHandoffdefaults to Cancel.
Does NOT:
- Mutate consumer gameplay data outside its narrow service contract.
- Reference behavior node types directly (it is service-side; nodes are graph-side).
- Log via Log / LogTrace: surface state through follower.status / follower.behavior-report / follower.behavior-graph like every other surface.
- Use fallbacks. Missing dependencies asserted in GameAwake per constitution §No Fallback Code.
Members
Section titled “Members”ServiceId
Section titled “ServiceId”int ServiceId { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:124
Globally stable service-id this adapter owns. Derived from the adapter’sServiceToken; not a per-artifact string table index.
ServiceToken
Section titled “ServiceToken”string ServiceToken { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:132
Stable token (e.g."path", "animation",
"follower-state") used for diagnostics and to match the
Mermaid%% services:header block. Bake-time validation
asserts uniqueness across registered adapters.
SupportsReplay
Section titled “SupportsReplay”bool SupportsReplay { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:140
True if the adapter supports replay-by-id (Resume handoff).
Bake validation refusesOnAuthorityHandoff = Resumeon
any node whose awaited externals include an adapter that does
NOT support replay.
DrainAndDispatch(ExternalServiceFrameContext context)
Section titled “DrainAndDispatch(ExternalServiceFrameContext context)”void DrainAndDispatch(BitQuirky.Behavior.ExternalService.ExternalServiceFrameContext context)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:147
Drain pending commands and dispatch them. Called once per frame by the host loop. The adapter writes back into CompletionRing.
OnAuthorityHandoff(EntityId entityId, int frameNumber, ExternalServiceCompletionRing completionRing)
Section titled “OnAuthorityHandoff(EntityId entityId, int frameNumber, ExternalServiceCompletionRing completionRing)”BitQuirky.Behavior.ExternalService.AdapterHandoffDecision OnAuthorityHandoff(UnityEngine.EntityId entityId, int frameNumber, BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRing completionRing)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IExternalServiceAdapter.cs:159-160
Authority handoff hook. Invoked once per follower whose host
authority changed mid-tick, identified by its stable 64-bit
EntityId. The adapter posts the
appropriate outcome (CancelledByHandoff
for cancel;Issuedfor
resume) for every outstanding pending id it owns for that
follower. Default decision: Cancel (per
§Authority handoff).
IInterruptibleExternalServiceAdapter
Section titled “IInterruptibleExternalServiceAdapter”Category: External services
interface BitQuirky.Behavior.ExternalService.IInterruptibleExternalServiceAdapterSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IInterruptibleExternalServiceAdapter.cs:14-18
Additive targeted interruption capability for a GameObject external-service adapter.
Responsibilities:
- Stop the identified active request synchronously before new work advances.
Does NOT:
- Publish a terminal completion, invoke game callbacks, or imply stepped lifecycle support.
Members
Section titled “Members”Interrupt(in ExternalServiceInterruption interruption)
Section titled “Interrupt(in ExternalServiceInterruption interruption)”void Interrupt(in BitQuirky.Behavior.ExternalService.ExternalServiceInterruption interruption)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/IInterruptibleExternalServiceAdapter.cs:17
Stops the exactly identified request synchronously.
ReadView
Section titled “ReadView”Category: External services
readonly struct BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRing.ReadViewSource declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:353-397
Burst-readable snapshot of the ring’s storage. Iteration over the records and filtering on follower id / service id / frame stamp lives on the consumer (the runtime instance’s resume logic).
Members
Section titled “Members”Length
Section titled “Length”public int Length { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:367
Number of record slots in the snapshot; zero when the ring is gone.
this[int index]
Section titled “this[int index]”public BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRecord this[int index] { get; }Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:370
Gets the record at a ring slot index in storage order, not in completion order.
ReadView(NativeArray<ExternalServiceCompletionRecord> records)
Section titled “ReadView(NativeArray<ExternalServiceCompletionRecord> records)”public ReadView(Unity.Collections.NativeArray<BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRecord> records)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:361-364
Wraps the ring’s record storage for Burst-side reading. The view borrows the array; it neither owns nor copies it.
TryFindLatestForCommand(int commandId, EntityId entityId, out ExternalServiceCompletionRecord record)
Section titled “TryFindLatestForCommand(int commandId, EntityId entityId, out ExternalServiceCompletionRecord record)”public bool TryFindLatestForCommand(int commandId, UnityEngine.EntityId entityId, out BitQuirky.Behavior.ExternalService.ExternalServiceCompletionRecord record)Source declaration: Packages/io.bitquirky.behavior/Runtime/ExternalService/ExternalServiceCompletionRing.cs:378-396
Find the most recent record matching the supplied
command id, owned by the given follower (matched on the stable
64-bitEntityId).
Returnstrueon hit. Burst-callable.
Source fingerprint: sha256:ad0983d00d773d882bc61865e18d8c5559e009d181e5891575cd7f262515b23e