Skip to main content

WorkflowRun

Struct WorkflowRun 

Source
pub struct WorkflowRun { /* private fields */ }
Expand description

The state of one in-flight workflow execution.

Implementations§

Source§

impl WorkflowRun

Source

pub fn new( spec: &WorkflowSpec, parent_session_id: &str, ) -> Result<WorkflowRun, DeepStrikeError>

Build from a spec. Validates dependency indices + acyclicity (reuses WorkflowSpec).

Source

pub fn resume( spec: &WorkflowSpec, parent_session_id: &str, submissions: &[Vec<WorkflowNode>], submission_bases: &[u32], completed: &[ResumedCompletion], ) -> Result<WorkflowRun, DeepStrikeError>

W0-ABI resume: rebuild an in-flight run by replaying which node agent-ids already completed (e.g. recovered from the session log after an interruption). Those nodes are pre-marked done so ready_batch returns only the remaining work — the kernel then continues the DAG from where it left off.

R3-1: submissions are the runtime Self::submit_nodes batches recorded (in order) before the interruption, re-applied first so dynamically-appended nodes reconstruct. When submission_bases records each batch’s original base index (from the WorkflowNodesSubmitted observation), batches are re-applied at those EXACT indices, gap-filling any interleaved runtime children (tournament entrants/judges) with inert completed placeholders — so a later batch never shifts onto a child’s old index and every completed id maps to the node it originally named. Without bases (legacy logs) batches replay in order, which is exact only when submissions were the sole runtime appends.

Loop iterations complete under wf-node{N}-i{k}: replay advances the iteration cursor to the highest recorded k+1 instead of discarding the finished work — the node re-arms at the next iteration. It completes when max_iters is provably exhausted OR a recorded loop_continue == false proves the semantic early stop (legacy signal-less logs still re-run the final iteration).

A completed Classify node replays its recorded branch choice through the same prune logic as Self::record_completion; with no recorded choice (legacy logs) every branch is pruned — the same “no recognizable choice” contract as the live path, and strictly safer than running a branch the original classification rejected.

A completed Tournament controller is NOT replayed (its children are runtime appends the SDK never logs as node completions): a bracket unresolved at the interruption re-expands and re-runs from its entrants — wasteful but faithful.

Source

pub fn ready_batch(&self) -> Vec<usize>

Node indices whose dependencies are satisfied and that have not yet started.

Source

pub fn current_agent_id(&self, node: usize) -> String

The agent id for a node’s current spawn. For a Spawn node this is the stable wf-node{N}; for a Loop node it is wf-node{N}-i{k} where k is the count of iterations already finished — so each iteration gets a distinct id without any new ABI (the SDK simply spawns the id it is given and feeds it back as a sub_agent_completed).

Source

pub fn manifest_for(&self, node: usize) -> IsolationManifest

Build the isolation manifest for a node’s current spawn, preserving its explicit isolation + context-inheritance (the AgentRunSpecfrom_spec path would overwrite these with role defaults). Capability inheritance for workflow nodes is left to a later round.

Source

pub fn quarantine_violation(&self, node: usize) -> bool

The goal text for a node (for the spawn’s run spec / context injection). W3 quarantine invariant: a quarantined node reads untrusted content and must run read-only. Returns true if the node is Quarantined yet declares a write-capable isolation (Shared/Worktree/Remote) — a privilege contradiction the kernel refuses to spawn, turning the SDK’s “self-discipline” quarantine into an in-kernel, auditable enforcement.

Source

pub fn spawn_info(&self, node: usize) -> WorkflowSpawnInfo

The SDK-facing spawn descriptor for a node (agent id + goal + canonical role/isolation/ inheritance strings + model hint). The kernel owns the spec; this is how the goal reaches the host that runs the node.

Source

pub fn mark_spawned(&mut self, node: usize, agent_id: &str)

Mark a node as spawned: start it in the graph and map its kernel agent id back to the node for completion routing. (The live in-flight set is the executor’s SuspendState::SubAgentAwait.agent_ids — the single source of in-flight truth.)

Source

pub fn mark_denied(&mut self, node: usize)

Mark a node as denied by the syscall gate: fail it in the graph (dependents stay pending and will never become ready). Does not enter the live batch.

Source

pub fn record_completion( &mut self, agent_id: &str, result: LoopResult, ) -> Option<usize>

Record a completed sub-agent against its node. Returns the node index if agent_id belonged to this workflow, else None.

For a Loop node this counts the finished iteration: while more iterations remain (< max_iters) the node is re-armed (set_ready) — so the next ready_batch/spawn round runs wf-node{N}-i{k+1} — and the node stays non-terminal, keeping its dependents pending. Only when the loop is exhausted is the node completed, promoting its dependents.

Source

pub fn expand_ready_controllers(&mut self)

Expand every tournament controller node whose dependencies are now satisfied (status Ready) into its entrant children. The controller is moved to Running (it spawns no agent of its own) and stays non-terminal until its bracket resolves. Called by the executor before each spawn round, so a controller behind upstream deps expands the moment those complete.

Source

pub fn submit_nodes_from( &mut self, submitter: Option<&str>, nodes: Vec<WorkflowNode>, ) -> Vec<usize>

Append a batch of nodes to the in-flight DAG at runtime — the kernel side of the dynamic “submit nodes” capability, generalizing the tournament’s Self::append_child. A running node, on completion, can ask for more work to be spawned: unknown-size discovery (loop-until-done) and per-item fan-out (e.g. a claim-extractor spawning one verifier per claim) both reduce to “append these nodes now”.

Each submitted node’s depends_on is interpreted batch-relative and backward-only: index d refers to the d-th node of this submission, and only d < this node's position is honored — so a submission can carry its own internal forward chain (extractor → dependents) while forward/self/out-of-range references are dropped rather than stranding the node behind an unsatisfiable dependency. Nodes with no (remaining) deps are immediately Ready, exactly like tournament entrants, and flow through the unchanged gated spawn loop — so quota / depth / quarantine apply per node with no new gate. Returns the appended node indices (their agent ids are the deterministic wf-node{idx}).

Pure graph mutation: the caller (state machine) is responsible for routing the trigger through evaluate_syscall before calling this, keeping the kernel’s zero-I/O contract.

G1 no-privilege-escalation: when submitter names a NodeTrust::Quarantined node, every node in this submission is coerced to Quarantined before append. A quarantined agent read untrusted content (which may be adversarial), so the topology it asks for is itself untrusted: it must not be able to launch a trusted (or write-capable) child and thereby escape its sandbox. This is transitive taint — a quarantined origin’s descendants inherit quarantine — the topological analogue of a process spawned by an untrusted process inheriting its label. Trusted (or absent) submitters pass through unchanged. The coercion is enforced here in the kernel rather than trusting the SDK, and composes with the spawn-time Self::quarantine_violation gate (a coerced node that also asked for write isolation is then denied at spawn).

Source

pub fn submit_nodes(&mut self, nodes: Vec<WorkflowNode>) -> Vec<usize>

Source

pub fn owns_agent(&self, agent_id: &str) -> bool

Whether agent_id belongs to this workflow.

Source

pub fn is_agent_quarantined(&self, agent_id: &str) -> bool

R3-3: whether the node behind agent_id is Quarantined (it read untrusted content). The kernel uses this to label that node’s output as untrusted-origin when it crosses into the trusted parent context — the provenance half of the cross-boundary contract (shaping the output into a structured summary stays the SDK’s job; the kernel cannot inspect content).

Source

pub fn outcome(&self) -> (Vec<String>, Vec<String>)

Outcome at finish: (completed_agent_ids, failed_agent_ids) by node. Nodes left Pending/Ready (stalled behind a gated dependency) appear in neither.

Source

pub fn abort_outcome(&self) -> (Vec<String>, Vec<String>)

#2-B abort: outcome when the workflow is preempted — every node that has not already Completed counts as failed (running / ready / pending all abort). Used to emit a terminal WorkflowCompleted when an InterruptNow tears the whole WorkflowRun down.

Source

pub fn len(&self) -> usize

Total node count.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more