Documentation / guides
Bindings and roots
Bind tools to canonical Session-owned workspace roots.
The composition root chooses a placement; individual tools receive only the
capabilities their definition requested. A workspace-bound tool gets a
WorkspaceBinding with a canonical root, a mutation coordinator, and optional
same-loop file observations. A read-only evidence tool gets a
ReadWorkspaceBinding with only a root string.
Placement options
func WithExclusiveWorkspace(
store *workspacestore.Store,
root string,
leaser storage.Leaser,
) rig.Option
func WithSessionWorkspaces(
store *workspacestore.Store,
baseDir string,
) rig.Option
func WithSharedWorkspace(
store *workspacestore.Store,
root string,
) rig.Option
Exactly one of these options may be present. WithExclusiveWorkspace and
WithSharedWorkspace name a fixed root. WithSessionWorkspaces names a base
directory and derives an injective baseDir/<sessionID> destination for every
non-zero session ID. A workspace store or exclusive leaser that is nil is
rejected at definition time.
Canonical roots and lease names
Define turns a root or base directory into an absolute, clean path. If the
path or an existing parent can be resolved, EvalSymlinks is applied so
lexical and symlink aliases converge. Exclusive placement derives the storage
lease name as:
workspace-roots/<sha256(canonical-root) in lowercase hex>
The canonical root and mode also enter the rig fingerprint. Changing either is a durable configuration change, not a runtime-only detail. A root lease is acquired only after the session journal lease has been acquired.
Tool bindings
The public binding structs are intentionally narrow:
type WorkspaceBinding struct {
Root string
Coordinator WorkspaceCoordinator
Observations WorkspaceObservations
}
type ReadWorkspaceBinding struct {
Root string
}
type WorkspaceCoordinator interface {
Acquire(context.Context, WorkspaceOperation, string) (WorkspacePermit, error)
Healthy() error
}
type WorkspacePermit interface { Release() }
WorkspaceOperationPathMutation requires a non-empty canonical path and
serializes overlapping scopes. WorkspaceOperationWholeMutation is an
exclusive whole-tree permit. WorkspaceOperationCheckpoint is the distinct
exclusive snapshot/restore permit and requires an empty path. A canceled wait
returns a typed acquisition error and leaves no permit behind. A mutator must
check Healthy before committing; after exclusive lease loss it fails closed.
WorkspaceObservations is optional shared state for one loop’s file tools and
Bash. It does not grant authority or escape the root.
type Bindings struct {
SessionID uuid.UUID
LoopID uuid.UUID
Workspace *WorkspaceBinding
ReadWorkspace *ReadWorkspaceBinding
Delegate DelegateController
Process *ProcessBinding
}
tool.RequiresWorkspace requires Workspace != nil, a non-empty root, and a
healthy coordinator. tool.RequiresWorkspaceRead requires an absolute clean
read root and exposes no mutation capability. Build calls receive a defensive
attenuation of Bindings, so a definition cannot retain unrelated session
authority.
Persistence boundary
Session journal paths, workspace blob-provider paths, and the snapshot spool
directory must be outside the managed region. Equality and descendants count as
overlap; an ancestor or sibling does not. Define fails with
*rig.PersistenceOverlapError, because a checkpoint must not mutate the tree
it is walking by appending its own journal record.
The source is pkg/rig/workspace.go, internal/sessionruntime/workspace_placement.go, and pkg/tool/definition.go. Canonicalization, alias convergence, overlap, and binding failures are covered by pkg/rig/workspace_test.go and pkg/tool/definition_test.go.