Argument bindings for planned tool calls. A string value inside a
planned call’s args may embed {{steps.N.path}} (data captured from a
prior step) or {{calls.K.path}} (an earlier call in the same step,
zero-based). Extraction feeds strict-save validation; resolution
substitutes live or pinned run data at execution/preview time.
One matcher per SOP trigger source. SopTrigger::behavior is the only place
that names every variant for matching; field specs are generated separately
by the TriggerFields derive, so neither matching nor the authoring
registry hand-lists a source. Add a variant and the compiler forces its arm
here (matching) and the derive supplies its fields.
Wire-edit application: translates a visual editor’s connect/disconnect
gesture into the corresponding StepRouting/StepFailure mutation on a
draft Sop. The graph is a projection; these edits write back to the
source of truth it was projected from.
The canonical legend for the SOP canvas: flow-wire roles, pin classes, and
run states. The single authority a surface reads to render a legend and
per-handle/per-wire hover context, so no surface hardcodes these lists.
Canvas geometry carried on every serialized graph so the web canvas reads
placement pitch from the wire instead of a local literal. The values are
fixed by LayoutGeometry::CANONICAL; the struct rides on GraphLayout
only to expose them to non-Rust surfaces.
Grid placement for one node: column = longest flow path from an entry,
row = order of insertion within that column. x/y carry a persisted
canvas coordinate when the node has been dragged; absent otherwise.
Injected side-effect adapters for build_sop_engine. Each is optional and
fail-closed when absent: the route falls back to the log-only no-op adapter,
and the forge.comment / llm.generate capabilities report a clear failure
instead of acting. The daemon injects real implementations; CLI / standalone
callers pass SopEngineAdapters::default().
Build a single shared SopEngine + SopAuditLogger pair.
This is the sole construction site for SOP state within a daemon.
Callers receive Arc<Mutex<SopEngine>> and Arc<SopAuditLogger>
handles — never call SopEngine::new or SopAuditLogger::new
directly outside this module.
Renumber steps to a contiguous 1..=N sequence (positional order wins)
and remap every internal reference: routing.next, depends_on,
switch goto targets, and on_failure: goto. References to steps that
no longer exist are dropped (goto falls back to Fail). No-op when
step numbers are ambiguous (duplicates), since a remap would guess.
Runs automatically inside save_sop.
Parse procedure steps from SOP.md content.
Expects a ## Steps heading followed by numbered items (1., 2., …).
Each item’s first bold text (**...**) is the step title; the rest is body.
Sub-bullets parse execution hints and dark per-step contract metadata.
Render steps back to SOP.md markdown, the inverse of parse_steps.
Every contract field (tools, scope, schema, routing, failure policy,
mode) becomes a sub-bullet, so render -> parse is lossless.
Enumerate every run the engine holds (active + retained terminal),
newest first, optionally scoped to one SOP. Errors only if the engine
lock is poisoned. This is the Runs surface’s data source.
Persist an SOP to <sops_dir>/<name>/ as SOP.toml + SOP.md.
Normalizes step numbers first, then rejects the write entirely if
strict validation finds blocking problems; nothing touches disk on
failure.
Build the tool-spec map an SOP graph projection uses to type step pins.
Keys are tool names; values are the tool’s declared parameters (input
pins) and output (output pin) schema. Derived once from the agent’s
resolved security policy so the pins mirror the exact tools the step can
call, not a hand-authored list.