Concepts · 5 of 6
Where Loom ends
Loom proposes an action; the Commission runtime rechecks it and invokes it through an effect port the embedder supplies.
Loom proposes. Commission invokes. Every executor, Loom included, ends a step by returning a
ProposedAction: an action id and its arguments. Loom's side ends there. It makes no connector
call, holds no handle to connectors, and receives no provider credential just because a connection
exists.
pub enum ExecutorOutcome {
ProposedAction(ExecutorOutcomeProposedAction),
NeedsHumanJudgment(ExecutorOutcomeNeedsHumanJudgment),
Suspended(ExecutorOutcomeSuspended),
NoUsefulAction(Unit),
CompletedLocalReasoning(Unit),
CaseMoved(ExecutorOutcomeCaseMoved),
}
Immediately before the effect, the Commission runtime rechecks the frontier, the case revision and
authority. What it admits becomes an AdmittedRequest, which only the runtime can build, and goes
to the embedder's effect port:
pub trait EffectPort {
fn performs(&self, action: &str) -> bool;
fn invoke(
&self,
commission: &Commission<commission_state::Assigned>,
request: &AdmittedRequest,
) -> Result<EffectOutcome, EffectError>;
}
The alternative, Loom making the call itself, was rejected: it saves a hop, but every other executor, such as a human tool or a workflow, would need its own effect path.
What holds today
- The executor returns a
ProposedActionand invokes nothing. - An action that needs authority is proposed too. Loom never suspends for authority: the runtime rechecks the proposal and asks its authority provider.
run_until_blockedinvokes each admitted request once, and moves the case to a new revision only after an effect the port reports asPerformed. A request the port answersPendingis invoked again at the next iteration, revalidated first, until the port answers otherwise.- The slice's
LocalEffectsperformssoftware.change/1actions in a git work tree. It never merges, pushes or deploys. - Commission's
ConnectorEffectsperforms the actions a commission binds to Connector operations, through aConnectorInvoker.b10x-loom-connectors(loom_sdk::connectors) fills that port over a Connectors service, pinned at Connectorsv0.35.0. The host declares oneConnectorEndpointper Connector instance (ess/commission/domains/responsibility.yaml): its URL, a credential reference its own resolver turns into the service credential, and whether plainhttpis admitted. Each binding declares its operation's effect:Writefor an operation the service describes with themutationprofile,Readotherwise.ConnectorsInvokerdescribes the endpoint, invokes the bound operation once onPOST /v1alpha2/invoke, never falls back and never resends.
| Connectors answers | The invoker answers |
|---|---|
| a write's success, with the attempt it recorded | Performed, naming that attempt |
a read's success, with no attempt and its audit record complete | Performed, naming that audit record |
an error whose recorded attempt is refused or not_attempted | Refused |
anything else: a write's success naming no attempt, a read's success with an attempt or an audit record that is not complete, an error without a recorded attempt, an unknown outcome, a protocol or transport failure | Err |
More columns: swipe horizontally, or focus the table and use the arrow keys.
An instance with no declared endpoint, a credential that does not resolve, a service that
describes another instance, and a binding whose effect is not the one the service describes are
Err before the operation is invoked.
An effect port for Substrate is not decided. Whether a released Connectors provider offers the file-edit and test-run operations a coding phase needs is not known yet.