Skip to main content

Module runner

Module runner 

Source
Expand description

One runner seam: the part of an orchestrator adapter that is not about the orchestrator.

Two adapters exist, for Claude Code’s worktree hooks and for a Symphony workspace backend. Written independently, in shell, they converged on the same five steps: derive a stable identity from whatever the orchestrator calls its unit of work, resolve an exact base revision, drive the lifecycle, verify the binding that came back is the one that was asked for, and map Choir’s typed rejections onto a retry decision.

Only the first and last of those are orchestrator-shaped, and only barely. The rest is the lifecycle contract, and it was duplicated: 557 lines of shell holding two hand-rolled copies of the identity derivation and the binding check, which are exactly the parts where a mistake is silent. A workspace name that collides sends two agents into one directory. A binding check that passes vacuously accepts a workspace bound to somebody else’s change.

So the shared half lives here, in one tested place, and an adapter is left with what genuinely differs: its wire format, and its namespace.

§What is deliberately not here

No orchestrator’s field names, and no agent protocol’s concepts. The design note is explicit that one agent protocol must not become Choir’s change model, so this module speaks only in the four identifiers the identifier contract already names: workspace, change, revision and operation.

Structs§

Config
Install-time settings: the node, the repository, and the owner identity that signs. Supplied by the operator, not by the orchestrator, so a request cannot redirect a workspace at another repository or sign with another key.
Failure
A refused request: a stable code, whether retrying can help, and a message safe to hand back to the orchestrator.
Identity
The four identifiers one writing attempt is bound to.
Request
One request from an orchestrator adapter.

Enums§

Operation
One lifecycle step an orchestrator asks for.
Scheme
How a change’s identity is derived, and what that choice costs.

Constants§

PROTOCOL_VERSION
Wire-format version of the runner request and result.

Functions§

base_from_view
Extracts the exact Git object id base_ref currently points at.
bound_base
The base revision the node says the change is actually bound to.
failure_from_response
Turns a Choir error response into a Failure, preserving its code.
is_retryable
Whether a Choir rejection code can succeed on an identical retry.
safe_segment
Whether one path component is safe to place in a workspace path.
split_repo
Splits owner/repo, refusing any other shape.
verify_binding
Checks the node returned the binding that was asked for.