README

colmugx/posoco/kernel does not have a README file

#
CallId

pub(all) struct CallId {
value : String
} derive(Eq, Hash,
Debug
)

Stable identifier for a single tool call requested by the assistant. The reducer and scheduler only ever compare/store this string; it is opaque to the Kernel and is produced by the model adapter or by the host.

#
CallId::new

fn CallId::new(value : String) -> Result[CallId, String]

Construct a CallId. Empty strings are rejected — an empty id would make correlation ambiguous. The Kernel invariant treats a missing/empty call id in a streamed completion as ModelParseFailure, not as a usable call.

#
CallId::to_string

fn CallId::to_string(self : CallId) -> String

#
CallId::unchecked

fn CallId::unchecked(value : String) -> CallId

Internal constructor used by Kernel tests and by callers that have already validated the string. Production callers should prefer CallId::new and handle the typed rejection.

#
CancelDisposition

pub(all) enum CancelDisposition {
Propagated
NotPropagated
AlreadySettled
} derive(Eq,
Debug
)

What an adapter reports after a CancelOutstanding effect. The reducer never waits for this.

#
CancelReason

pub(all) enum CancelReason {
HostRequested(detail~ : String?)
DeadlineReached
} derive(Eq,
Debug
)

Why a Run was cancelled.

#
CatalogVersion

pub(all) struct CatalogVersion {
value : Int
} derive(Eq,
Debug
)

Catalog version — bumped every time a snapshot is built. The reducer and executor correlate CallModel and ExecuteTool effects back to the exact snapshot version the model was prompted against; a mismatch is a kernel invariant failure (InvariantViolation::StaleSnapshot).

#
CatalogVersion::CatalogVersion

fn CatalogVersion::CatalogVersion(value : Int) -> CatalogVersion

#
CatalogVersion::to_int

fn CatalogVersion::to_int(self : CatalogVersion) -> Int

#
CompactMode

pub(all) enum CompactMode {
NewThread
Replace
Append
} derive(Eq)

How posoco applies the result of ModelPort::compact.
impl Show for CompactMode

#
CompactResult

pub(all) struct CompactResult {
compacted_messages : Array[Message]
mode : CompactMode
} derive(Eq)

Return value of ModelPort::compact.

#
CompactTrigger

pub(all) enum CompactTrigger {
Auto
Manual
} derive(Eq,
Debug
)

What triggered a compact. Advisory — modelport may ignore.

#
Completion

pub(all) struct Completion {
message : CompletionPayload
usage : Usage?
} derive(Eq,
Debug
)

A completed assistant step. The message field is the canonical assistant message that the reducer appends to the transcript; tool calls and reasoning live there (single source of truth, ADR §2.11). The usage field reports token consumption observed for this step, which the reducer may aggregate into the Run budget.

Construction note: do NOT build this by hand in production code. The from_assistant_message constructor enforces the invariant that the message payload is consistent (assistant role, no ToolMessage shape, etc.).

#
Completion::Completion

fn Completion::Completion(content~ : Array[Content], tool_calls~ : Array[ToolCall], reasoning~ : Reasoning?, finish_reason~ : FinishReason, usage~ : Usage?) -> Completion

Build an Completion from its parts. The reducer constructs this from a ModelCompleted input after parsing the model adapter's wire representation.

#
Completion::finish_reason

fn Completion::finish_reason(self : Completion) -> FinishReason

Returns the finish reason. Length is preserved as a distinct variant so the reducer can refuse to emit ExecuteTool effects for a truncated completion (ADR §2.7, M0 StreamAccumulator::to_response behaviour).

#
Completion::has_tool_calls

fn Completion::has_tool_calls(self : Completion) -> Bool

Convenience: does this completion request any tool calls?

#
Completion::tool_calls

fn Completion::tool_calls(self : Completion) -> Array[ToolCall]

Returns the tool calls in source order (already a copy of the internal array).

#
CompletionPayload

pub(all) struct CompletionPayload {
content : Array[Content]
tool_calls : Array[ToolCall]
reasoning : Reasoning?
finish_reason : FinishReason
} derive(Eq,
Debug
)

Re-flattened assistant payload used inside Completion. We cannot reuse Message::AssistantMessage directly because that variant already carries finish_reason; the completion's message field is the transcript entry, while the usage lives at the completion level. This struct mirrors only the fields that travel together as the assistant's contribution to a single step.

#
Content

pub(all) enum Content {
Text(String)
Image(media_type~ : String, data~ : String)
} derive(Eq,
Debug
)

Canonical content block. Text is the common case; Image carries a stable media-type identifier plus opaque payload data (base64, URL, or an adapter-managed handle — the Kernel does not interpret it).
impl Show for Content

#
EffectId

pub(all) struct EffectId {
value : Int
} derive(Eq, Hash,
Debug
)

Identifier for a single declared Effect. Monotonic per Run. Each completion input must correlate to a pending effect with this id; a mismatch is InvariantViolation::StaleCorrelation.
impl Show for EffectId

#
EffectId::first

fn EffectId::first() -> EffectId

#
EffectId::next

fn EffectId::next(self : EffectId) -> EffectId

#
EffectId::to_int

fn EffectId::to_int(self : EffectId) -> Int

#
ExecutionPolicy

pub(all) enum ExecutionPolicy {
Sequential
Parallel
Exclusive
} derive(Eq,
Debug
)

How a tool may be batched with other tools in the same model completion.

  • Sequential: occupies a single-element wave. Safe default; file/shell side effects never race.
  • Parallel: may share a wave with adjacent Parallel calls.
  • Exclusive: forms a barrier before and after; never shares a wave.

Sequential is the safe default. Products opt into Parallel only for tools whose effects are independently safe, and use Exclusive at a visible side-effect boundary.

#
FinishReason

pub(all) enum FinishReason {
Stop
Length
ToolCalls
Other(String)
} derive(Eq,
Debug
)

Why the assistant finished a step. It is owned by the assistant message (per ADR §2.11: single source of truth).

Length is preserved as a distinct variant because the reducer must NOT emit ExecuteTool effects after a length-truncated completion, even if the provider tried to stream partial tool calls.

#
InvocationScope

pub(all) struct InvocationScope {
session_id : SessionId
run_id : RunId
effect_id : EffectId?
} derive(Eq,
Debug
)

Invocation identity for a single model-side call (ModelPort::chat / ModelPort::compact, and their Runtime correspondences). Constructed by posoco at the effect-interpretation layer and passed down unchanged; ports and hosts MUST treat it as read-only.

This is the canonical answer to "which session/run is this call serving": adapters that key behaviour on session identity (continuity, telemetry, cost attribution, per-session policy) read it from here instead of smuggling it through messages or config.

Invariants:
  • session_id / run_id always identify the Run that issued the call, including compact (compact is host-driven but still scoped to a Run).
  • effect_id is Some iff the call executes a reducer-allocated CallModel effect; it is None for compact, which is not an effect. Hosts that propagate cancellation key in-flight model calls by this id, mirroring the tool side's EffectContext.effect_id.

#
Message

pub(all) enum Message {
SystemMessage(content~ : Array[Content])
UserMessage(content~ : Array[Content])
AssistantMessage(content~ : Array[Content], tool_calls~ : Array[ToolCall], reasoning~ : Reasoning?, finish_reason~ : FinishReason)
ToolMessage(call_id~ : CallId, tool_name~ : ToolName, outcome~ : ToolOutcome)
} derive(Eq,
Debug
)

Canonical conversation message. The role determines which payload is legal, making invalid role/payload combinations unrepresentable.

Invariants:
  • SystemMessage / UserMessage never carry tool calls.
  • AssistantMessage is the ONLY variant that carries tool calls and the ONLY variant that carries reasoning.
  • ToolMessage is the ONLY variant that carries a call_id correlation and a ToolOutcome. It never carries tool calls.

#
ModelCallResult

pub(all) struct ModelCallResult {
completion : Completion
processed_messages : Array[Message]
} derive(Eq)

Return value of HostRuntime::call_model and ModelPort::chat. Bundles the model completion with the processed message tree.

The pump ALWAYS replaces the transcript body with processed_messages, then appends completion as the new assistant entry.

#
ModelFailure

pub(all) enum ModelFailure {
RequestBuild(reason~ : String)
Transport(reason~ : String)
Runtime(reason~ : String)
Parse(reason~ : String)
HostRejected(reason~ : String)
} derive(Eq,
Debug
)

Categorises why a model step failed (ADR §2.4). The reducer maps this to a FailureReason::Model* variant. Each variant carries a safe bounded label, never a raw provider payload.

#
NotExecutedReason

pub(all) enum NotExecutedReason {
UnknownTool
SchemaMismatch(json_path~ : String, expected~ : String, actual~ : String)
} derive(Eq,
Debug
)

Discriminator for the reason a tool call was NOT executed even though the model requested it (ADR §2.7).

  • UnknownTool: the requested tool name is not present in the catalog snapshot that was handed to the CallModel effect.
  • SchemaMismatch: the model's arguments parsed successfully but failed validation against the tool's input schema. The diagnostic carries a safe JSON path and type expectation; it never includes the raw argument payload.

Malformed-argument cases never reach this variant — they are ModelParseFailure at the reducer boundary (ADR §2.4).

#
OwnerId

pub(all) struct OwnerId {
value : String
} derive(Eq, Hash,
Debug
)

Stable identifier for the provider that owns a tool. The Kernel uses this only for owner lookup in the runtime registry; it does not call into the owner through this type.

#
OwnerId::new

fn OwnerId::new(value : String) -> Result[OwnerId, String]

#
OwnerId::to_string

fn OwnerId::to_string(self : OwnerId) -> String

#
OwnerId::unchecked

fn OwnerId::unchecked(value : String) -> OwnerId

#
Reasoning

pub(all) struct Reasoning {
content : String
raw : Json?
} derive(Eq,
Debug
)

Reasoning trace produced by the assistant (e.g. DeepSeek deepseek-reasoner chain-of-thought, OpenAI o-series reasoning content). The Kernel never interprets the content; it stores and replays it. None means the assistant produced no reasoning for this step.

raw is a provider-defined replay payload: OpenAI Responses API reasoning items must be replayed verbatim when the host manually manages conversation state (per the official reasoning guide), so the adapter stores the raw items here. The kernel never interprets it; providers that replay plain content text (DeepSeek, Kimi, OpenAI-compatible) leave it None.
impl Show for Reasoning

#
RunId

pub(all) struct RunId {
value : String
} derive(Eq, Hash,
Debug
)

Stable identifier for a single Run. Supplied by the host in the Start input and carried through every state.
impl Show for RunId

#
RunId::new

fn RunId::new(value : String) -> Result[RunId, String]

#
RunId::to_string

fn RunId::to_string(self : RunId) -> String

#
RunId::unchecked

fn RunId::unchecked(value : String) -> RunId

#
SchemaDiagnostic

pub(all) struct SchemaDiagnostic {
json_path : String
expected : String
actual : String
} derive(Eq,
Debug
)

Result of validating parsed tool arguments against a ToolDef's input schema. The validator (T05) returns this; the reducer (T03) maps Err into a ToolOutcome::NotExecuted(SchemaMismatch) carrying the original call id.

The diagnostic deliberately excludes the raw argument payload; it reports only a JSON path and a type expectation, so that prompts and tool arguments never leak into logs.

#
SessionId

pub(all) struct SessionId {
value : String
} derive(Eq, Hash,
Debug
)

Stable identifier for a product session. The Kernel never opens or materializes session storage; it carries this identity through effects, journal entries, and committed event envelopes.

#
SessionId::new

fn SessionId::new(value : String) -> Result[SessionId, String]

#
SessionId::to_string

fn SessionId::to_string(self : SessionId) -> String

#
SessionId::unchecked

fn SessionId::unchecked(value : String) -> SessionId

#
ToolCall

pub(all) struct ToolCall {
call_id : CallId
name : ToolName
arguments : Json
} derive(Eq,
Debug
)

Tool arguments as parsed JSON. This is the post-parsing representation: if the model stream produced malformed JSON, the reducer has already terminated the Run with ModelParseFailure before this type is constructed. Therefore any ToolCall reaching the scheduler has well-formed arguments, but the arguments may still fail the catalog schema (handled separately as NotExecuted(SchemaMismatch)).
impl Show for ToolCall

#
ToolDef

pub(all) struct ToolDef {
name : ToolName
description : String
input_schema : Json
owner : OwnerId
policy : ExecutionPolicy
provenance : String?
} derive(Eq,
Debug
)

A single tool's definition as the model and the executor see it. Owned by the catalog snapshot (T05), not by individual providers.
impl Show for ToolDef

#
ToolDef::ToolDef

fn ToolDef::ToolDef(name~ : ToolName, description~ : String, input_schema~ : Json, owner~ : OwnerId, policy~ : ExecutionPolicy, provenance~ : String?) -> ToolDef

Internal builder used by the catalog. Most fields are required; provenance is optional. The catalog builder (T05) validates the schema and policy before constructing this, so by the time a ToolDef reaches the reducer, it has already passed composition.

#
ToolName

pub(all) struct ToolName {
value : String
} derive(Eq, Hash,
Debug
)

A tool name as it appears in the catalog (call-visible name). The Kernel uses this only for lookup in the catalog snapshot; it never re-parses or re-normalizes it.

#
ToolName::new

fn ToolName::new(value : String) -> Result[ToolName, String]

#
ToolName::to_string

fn ToolName::to_string(self : ToolName) -> String

#
ToolName::unchecked

fn ToolName::unchecked(value : String) -> ToolName

#
ToolOutcome

pub(all) enum ToolOutcome {
Success(content~ : String, structured~ : Json?)
ToolReportedError(content~ : String, structured~ : Json?)
RuntimeFailure(error_category~ : String, message~ : String)
NotExecuted(reason~ : NotExecutedReason, original_call_id~ : CallId)
} derive(Eq,
Debug
)

Outcome of a single tool invocation (ADR §2.4, §2.11).

Variants:
  • Success: tool ran and returned structured data. structured is the model-facing JSON payload; content is the human-readable mirror used by the transcript.
  • ToolReportedError: tool ran and reported a business-level failure. The Run continues; the failure is fed back to the model as a normal tool message.
  • RuntimeFailure: tool did not run to completion — adapter raised a RuntimeError. Still non-terminal for the Run.
  • NotExecuted: model requested a tool that was not executed (unknown name or parseable-but-schema-invalid args). The original call id is preserved so the model can correlate the feedback.

There is deliberately no boolean is_error field here. The variant tag IS the error status.
impl Show for ToolOutcome

#
ToolOutcome::is_failure

fn ToolOutcome::is_failure(self : ToolOutcome) -> Bool

Whether the outcome represents a non-success path (any variant other than Success). Product adapters may use this for presentation, while canonical control flow pattern-matches the outcome exhaustively.

#
ToolOutcome::summary

fn ToolOutcome::summary(self : ToolOutcome) -> String

Single-line summary that excludes raw payloads. Used by Show and by any debug/log surface, so that prompts and tool arguments never leak.

#
Transcript

pub(all) struct Transcript {
messages : Array[Message]
} derive(Eq,
Debug
)

Canonical conversation transcript. Every transition produces a fresh array (the reducer never mutates caller-owned arrays, ADR §2.10). The reducer is the only writer.

#
Transcript::append

fn Transcript::append(self : Transcript, message : Message) -> Transcript

Returns a new transcript with message appended. The original transcript is not mutated (ADR §2.10).

#
Transcript::append_all

fn Transcript::append_all(self : Transcript, messages : Array[Message]) -> Transcript

Returns a new transcript with messages appended in order.

#
Transcript::empty

fn Transcript::empty() -> Transcript

#
Transcript::from_array

fn Transcript::from_array(messages : Array[Message]) -> Transcript

#
Transcript::length

fn Transcript::length(self : Transcript) -> Int

Returns the number of messages.

#
Transcript::messages_snapshot

fn Transcript::messages_snapshot(self : Transcript) -> Array[Message]

Read-only snapshot of the message array. Returns a copy so callers cannot mutate the reducer-owned transcript.

#
TurnId

pub(all) struct TurnId {
value : String
} derive(Eq, Hash,
Debug
)

Identifier for a single turn within a Run. A Run may contain multiple turns (initial prompt + follow-ups); turns never outlive their Run. follow_up allocates a new TurnId under the same RunId.
impl Show for TurnId

#
TurnId::new

fn TurnId::new(value : String) -> Result[TurnId, String]

#
TurnId::to_string

fn TurnId::to_string(self : TurnId) -> String

#
TurnId::unchecked

fn TurnId::unchecked(value : String) -> TurnId

#
Usage

pub(all) struct Usage {
input_tokens : Int?
output_tokens : Int?
total_tokens : Int?
} derive(Eq,
Debug
)

Token usage reported by the model for a single step. The Kernel only counts what is actually reported; absent dimensions are None, never silently coerced to 0 (ADR §2.9 — unknown usage is never reported as 0).
impl Show for Usage