sessionmove

package
v0.172.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package sessionmove defines WB's portable agent-session handoff protocol and the local durable aggregate used by both source and target machines. Couriers transport these types but do not interpret or own them.

Index

Constants

View Source
const (
	SynchestraDispatchSchemaVersion        = 1
	SynchestraSessionAcceptHandler         = "wb.session.accept.v1"
	SynchestraSessionMessageHandler        = "wb.session.message.v1"
	MessageSynchestraDispatchSchemaVersion = 1
)
View Source
const (
	RequestSchemaVersion            = 1
	ReceiptSchemaVersion            = 1
	MessageSchemaVersion            = 1
	MessageReceiptSchemaVersion     = 1
	MessageRecordSchemaVersion      = 1
	MessagePasteIntentSchemaVersion = 1
	EventSchemaVersion              = 1
	DigestAlgorithmSHA256           = "sha256"
	// MaxMessageBodyBytes bounds agent-authored message content before it is
	// admitted to an outbox, transported, or copied into a tmux buffer.
	MaxMessageBodyBytes = 64 << 10
	// MaxSourceOfferFieldBytes bounds each exact Work Log offer field carried
	// by a request. Keeping the source-authored content in the immutable
	// request lets crash repair recreate the offer without parsing Markdown.
	MaxSourceOfferFieldBytes = 64 << 10
	// MaxHandoverContentBytes bounds Request.HandoverContent: the rendered
	// handover document, which wraps an operator-supplied body (itself capped
	// at 1<<20 bytes at the CLI boundary) in a small fixed header. The extra
	// headroom here is for that wrapper, not a separate operator-facing limit.
	MaxHandoverContentBytes = 2 << 20
)
View Source
const DirName = "handoffs"

DirName is the directory under WB_HOME containing private handoff aggregates. Each handoff has one immutable request, zero or one immutable receipt, and an append-only events directory.

View Source
const (

	// HandoverFileName is the fixed private artifact EnsureHandoverUnderLock
	// materializes inside a handoff's retained aggregate directory. It is
	// never a repository path; see PrivateHandoverPath.
	HandoverFileName = "handover.md"
)
View Source
const RouteSchemaVersion = 1
View Source
const SuccessorAddressSchemaVersion = 1

Variables

View Source
var (
	ErrDigestMismatch  = errors.New("handoff digest does not match the supplied bytes")
	ErrHandoffConflict = errors.New("handoff identity conflicts with durable state")
)

Functions

func EncodeMessage

func EncodeMessage(message Message) ([]byte, error)

func EncodeMessageReceipt

func EncodeMessageReceipt(receipt MessageReceipt) ([]byte, error)

func EncodeReceipt

func EncodeReceipt(receipt Receipt) ([]byte, error)

func EncodeRequest

func EncodeRequest(request Request) ([]byte, error)

EncodeRequest validates and renders the canonical JSON spelling used by a source. A receiver still preserves whichever exact valid bytes it receives.

func ExternalHandoffClaimID

func ExternalHandoffClaimID(requestDigest Digest, successorWBSessionID string) (string, error)

ExternalHandoffClaimID derives the stable target claim identity from only immutable move identity. Length prefixes prevent field-boundary ambiguity; attempt PIDs and timestamps deliberately do not participate.

func NewHandoffID

func NewHandoffID() (string, error)

NewHandoffID returns an opaque identity suitable for both the tracked handover filename and the private aggregate directory. It is deliberately independent of either endpoint session ID.

func NewMessageID

func NewMessageID() (string, error)

NewMessageID returns a caller-owned identity that can be persisted before courier use and supplied to the explicit retry path after ambiguity.

func NormalizeSourceOfferContent

func NormalizeSourceOfferContent(message, nextAction string) (string, string)

NormalizeSourceOfferContent returns the one canonical spelling checkpoint writers must place in Request. The exact normalized strings are carried on the wire so receipt-time crash repair never has to reverse-parse a handover document to recover Work Log event content.

func PrivateHandoverPath added in v0.62.3

func PrivateHandoverPath(storeRoot, handoffID string) string

PrivateHandoverPath returns the deterministic absolute path of the private materialized handover for handoffID under storeRoot. It never depends on caller-supplied data beyond identifiers already validated elsewhere, so both the writer (EnsureHandoverUnderLock) and every reader can recompute it without trusting a persisted path value.

func ValidateMessageForRequest

func ValidateMessageForRequest(message Message, request Request) error

ValidateMessageForRequest corroborates all immutable lineage carried by a message against the original handoff. Only the predecessor may address its recorded successor, and replies always return to that predecessor.

func ValidateMessageReceipt

func ValidateMessageReceipt(receipt MessageReceipt, message Message, digest Digest, tmuxName string, pid int) error

ValidateMessageReceipt binds an acknowledgement to exact message bytes and the previously corroborated tmux identity. Success means recorded+pasted; it never means processed by the harness.

func ValidateReceiptForRequest

func ValidateReceiptForRequest(receipt Receipt, request Request, digest Digest) error

ValidateReceiptForRequest binds every deterministic receipt field to the exact admitted request identity and Task 4's harness-selection policy.

Types

type Admission

type Admission struct {
	Request Request
	Digest  Digest
	Replay  bool
	Receipt *Receipt
}

Admission reports whether the exact request already existed and, when the target completed previously, carries the immutable receipt to return.

type Config

type Config struct {
	Targets map[string]TargetConfig `yaml:"targets" json:"targets"`
}

Config is the session_move section of ~/.config/wb/wb.yaml.

func LoadConfig

func LoadConfig(configPath string) (Config, error)

LoadConfig reads and validates only session_move while tolerating unrelated top-level WB configuration sections.

func (Config) Target

func (c Config) Target(machine string) (TargetConfig, bool)

Target resolves a canonical WB machine name without consulting courier aliases or addresses.

type Courier

type Courier string

Courier names the configured delivery adapter. Machine identity remains the target map key; courier addresses are deliberately nested beneath it.

const (
	CourierSSH        Courier = "ssh"
	CourierLoopback   Courier = "loopback"
	CourierSynchestra Courier = "synchestra"
)

type Digest

type Digest string

Digest identifies exact bytes at a courier or durable-state boundary. Its textual form names the algorithm so a future protocol can add one without silently reinterpreting old state.

func DigestBytes

func DigestBytes(raw []byte) Digest

DigestBytes returns the sha256 digest of exact bytes.

func DigestSourceOffer

func DigestSourceOffer(message, nextAction string) Digest

DigestSourceOffer derives the authenticated content digest for an immutable source Work Log offer. Length-prefixing the domain and both normalized fields prevents boundary ambiguity.

func (Digest) Matches

func (d Digest) Matches(raw []byte) bool

Matches reports whether d names the exact supplied bytes.

type ExecutionLock

type ExecutionLock struct {
	// contains filtered or unexported fields
}

ExecutionLock serializes resumable target-side execution for one admitted handoff. The stable lock inode is retained instead of unlinked on release; removing a flock file permits two waiters to lock different inodes.

func (*ExecutionLock) Close

func (lock *ExecutionLock) Close() error

Close releases the execution fence. It is idempotent for defer-friendly use.

func (*ExecutionLock) HeldForSession

func (lock *ExecutionLock) HeldForSession(expectedRoot, aggregateID, digest string) bool

HeldForSession adapts the existing request-bound execution proof to the courier-neutral sessionauthority.Fence interface. The final HeldForStore call still reopens and descriptor-compares the exact store, aggregate, request file, and stable flock inode; this method does not weaken authority to an ID plus digest assertion.

func (*ExecutionLock) HeldForStore

func (lock *ExecutionLock) HeldForStore(expectedRoot string, request Request, digest Digest) bool

HeldForStore reports whether this process still owns the execution fence for the exact admitted request in the exact canonical Store root. Path text alone is not authority: the root, handoff directory, and stable lock entry must still name the retained filesystem objects acquired after admission.

func (*ExecutionLock) RetainHandoffForStore

func (lock *ExecutionLock) RetainHandoffForStore(expectedRoot string, request Request, digest Digest) (*os.File, error)

RetainHandoffForStore returns a CLOEXEC duplicate of the exact admitted handoff directory retained by this held execution fence. Callers use the descriptor as authority for a multi-step transaction so a later path swap cannot split reads, locks, and immutable publications across directories. The caller owns the returned file.

func (*ExecutionLock) RetainSessionDir

func (lock *ExecutionLock) RetainSessionDir(expectedRoot, aggregateID, digest string) (*os.File, error)

RetainSessionDir returns a duplicate of the same descriptor-authenticated handoff directory already exposed to legacy session-move callers.

func (*ExecutionLock) RetainStoreRootForStore

func (lock *ExecutionLock) RetainStoreRootForStore(expectedRoot string, request Request, digest Digest) (*os.File, error)

RetainStoreRootForStore returns a CLOEXEC duplicate of the exact Store root retained with this admitted handoff. It is used for indexes whose key spans handoff aggregates while the held execution fence supplies authority.

type HandoffEvent

type HandoffEvent struct {
	SchemaVersion int       `json:"schema_version"`
	Sequence      uint64    `json:"sequence"`
	HandoffID     string    `json:"handoff_id"`
	RequestDigest Digest    `json:"request_digest"`
	Phase         Phase     `json:"phase"`
	At            time.Time `json:"at"`
	Diagnostic    string    `json:"diagnostic,omitempty"`
}

HandoffEvent is one append-only private state record.

type Message

type Message struct {
	SchemaVersion        int         `json:"schema_version"`
	MessageID            string      `json:"message_id"`
	HandoffID            string      `json:"handoff_id,omitempty"`
	SenderWBSessionID    string      `json:"sender_wb_session_id,omitempty"`
	RecipientWBSessionID string      `json:"recipient_wb_session_id"`
	ReplyToWBSessionID   string      `json:"reply_to_wb_session_id,omitempty"`
	Kind                 MessageKind `json:"kind"`
	Body                 string      `json:"body,omitempty"`
	SentAt               time.Time   `json:"sent_at"`
}

Message is a courier-neutral durable message addressed by WB session ID.

func DecodeMessage

func DecodeMessage(raw []byte) (Message, error)

type MessageDirection

type MessageDirection string

MessageDirection distinguishes the predecessor's durable outbox from the successor's durable inbox. Both records bind the same caller-owned ID and exact payload digest.

const (
	MessageDirectionOutgoing MessageDirection = "outgoing"
	MessageDirectionIncoming MessageDirection = "incoming"
)

type MessageKind

type MessageKind string

MessageKind distinguishes ordinary successor input from WB's standard request to hand control back. Delivery is implemented by a later layer.

const (
	MessageKindText           MessageKind = "text"
	MessageKindRequestHandoff MessageKind = "request_handoff"
)

type MessagePasteIntent

type MessagePasteIntent struct {
	SchemaVersion        int       `json:"schema_version"`
	MessageID            string    `json:"message_id"`
	MessageDigest        Digest    `json:"message_digest"`
	HandoffID            string    `json:"handoff_id"`
	RecipientWBSessionID string    `json:"recipient_wb_session_id"`
	TmuxName             string    `json:"tmux_name"`
	PaneID               string    `json:"pane_id"`
	PID                  int       `json:"pid"`
	IntendedAt           time.Time `json:"intended_at"`
}

MessagePasteIntent is published before the sole automatic tmux paste attempt. Its presence without a receipt is deliberately ambiguous: replay must not paste again automatically.

type MessageReceipt

type MessageReceipt struct {
	SchemaVersion        int         `json:"schema_version"`
	MessageID            string      `json:"message_id"`
	MessageDigest        Digest      `json:"message_digest"`
	HandoffID            string      `json:"handoff_id"`
	SenderWBSessionID    string      `json:"sender_wb_session_id"`
	RecipientWBSessionID string      `json:"recipient_wb_session_id"`
	ReplyToWBSessionID   string      `json:"reply_to_wb_session_id"`
	Kind                 MessageKind `json:"kind"`
	TmuxName             string      `json:"tmux_name"`
	PaneID               string      `json:"pane_id"`
	PID                  int         `json:"pid"`
	RecordedAt           time.Time   `json:"recorded_at"`
	PastedAt             time.Time   `json:"pasted_at"`
}

MessageReceipt acknowledges only durable target recording plus one successful paste into the exact corroborated tmux pane. It deliberately contains no field that could imply the harness or agent processed the bytes.

func DecodeMessageReceipt

func DecodeMessageReceipt(raw []byte) (MessageReceipt, error)

type MessageRecord

type MessageRecord struct {
	SchemaVersion int              `json:"schema_version"`
	Direction     MessageDirection `json:"direction"`
	MessageID     string           `json:"message_id"`
	MessageDigest Digest           `json:"message_digest"`
	HandoffID     string           `json:"handoff_id"`
	RecordedAt    time.Time        `json:"recorded_at"`
}

MessageRecord is the strict durable source/target admission record.

type MessageState

type MessageState struct {
	Message Message
	Digest  Digest
	Raw     []byte
	Record  MessageRecord
	Replay  bool
	Intent  *MessagePasteIntent
	Receipt *MessageReceipt
}

MessageState is one loaded durable outbox or inbox entry.

type MessageSynchestraDispatch

type MessageSynchestraDispatch struct {
	SchemaVersion int    `json:"schema_version"`
	HandoffID     string `json:"handoff_id"`
	RequestDigest Digest `json:"request_digest"`
	MessageID     string `json:"message_id"`
	MessageDigest Digest `json:"message_digest"`
	Runner        string `json:"runner"`
	InvocationID  string `json:"invocation_id"`
	Handler       string `json:"handler"`
	DispatchID    string `json:"dispatch_id"`
}

MessageSynchestraDispatch is the exact accepted transport identity for one outgoing message. Target MessageID/digest admission remains authoritative: a hub invoke ambiguity before this record exists may create another dispatch, but it can never authorize a second inbox or paste.

type Phase

type Phase string

Phase is one durable point in the handoff state machine. Phase records are evidence, not a mutable current-state file; State derives the latest phase by reading the ordered append-only event sequence.

const (
	PhaseOffered          Phase = "offered"
	PhaseReceived         Phase = "received"
	PhaseWorktreeReady    Phase = "worktree_ready"
	PhaseSuccessorStarted Phase = "successor_started"
	PhaseCompleted        Phase = "completed"
	PhaseFailed           Phase = "failed"
	PhaseCancelled        Phase = "cancelled"
)

type Receipt

type Receipt struct {
	SchemaVersion          int       `json:"schema_version"`
	HandoffID              string    `json:"handoff_id"`
	RequestDigest          Digest    `json:"request_digest"`
	SuccessorWBSessionID   string    `json:"successor_wb_session_id"`
	PredecessorWBSessionID string    `json:"predecessor_wb_session_id"`
	TargetMachine          string    `json:"target_machine"`
	TmuxName               string    `json:"tmux_name"`
	Runtime                string    `json:"runtime"`
	Model                  string    `json:"model,omitempty"`
	NativeHarnessID        string    `json:"native_harness_id,omitempty"`
	AttemptID              string    `json:"attempt_id"`
	AttemptIndex           uint64    `json:"attempt_index"`
	PID                    int       `json:"pid"`
	TargetWorkLogReference string    `json:"target_work_log_reference"`
	PinnedCommit           string    `json:"pinned_commit"`
	StartedAt              time.Time `json:"started_at"`
}

Receipt is written only after the target successor is durably registered. RequestDigest binds it to the exact admitted request bytes.

func DecodeReceipt

func DecodeReceipt(raw []byte) (Receipt, error)

type Request

type Request struct {
	SchemaVersion          int    `json:"schema_version"`
	HandoffID              string `json:"handoff_id"`
	SuccessorWBSessionID   string `json:"successor_wb_session_id"`
	PredecessorWBSessionID string `json:"predecessor_wb_session_id"`
	SourceMachine          string `json:"source_machine"`
	TargetMachine          string `json:"target_machine"`
	RepositoryRemote       string `json:"repository_remote"`
	Branch                 string `json:"branch"`
	SourceWorkCommit       string `json:"source_work_commit"`
	BundleCommit           string `json:"bundle_commit"`
	// HandoverPath is deprecated and retained only so a handoff admitted by a
	// binary older than the ContinuationPrivate cutover still decodes and
	// replays: it names the repository-relative path, under the pinned
	// worktree, where that older binary committed the handover document into
	// the repo under work. It is set only together with an empty
	// HandoverContent, and no code path emits it anymore.
	HandoverPath   string `json:"handover_path,omitempty"`
	HandoverDigest Digest `json:"handover_digest"`
	// HandoverContent is the rendered handover document itself, carried
	// inline so it never touches the repo under work. A non-empty value
	// means this handoff is delivered as sessionauthority.ContinuationPrivate:
	// the target materializes it as a private 0600 file (see
	// Store.EnsureHandoverUnderLock) and hands the successor that path via
	// WB_SESSION_CONTINUATION_FILE. Every checkpoint created after the
	// ContinuationPrivate cutover sets this and leaves HandoverPath empty.
	HandoverContent       string    `json:"handover_content,omitempty"`
	SourceRuntime         string    `json:"source_runtime"`
	SourceModel           string    `json:"source_model,omitempty"`
	SourceNativeHarnessID string    `json:"source_native_harness_id,omitempty"`
	RequestedHarness      string    `json:"requested_harness,omitempty"`
	RequestedModel        string    `json:"requested_model,omitempty"`
	WorkLogReference      string    `json:"work_log_reference"`
	SourceOfferMessage    string    `json:"source_offer_message"`
	SourceOfferNextAction string    `json:"source_offer_next_action"`
	SourceOfferDigest     Digest    `json:"source_offer_digest"`
	CreatedAt             time.Time `json:"created_at"`
}

Request is the immutable courier-neutral handoff description. Its encoded bytes, rather than a re-marshalled projection, are what Digest authenticates.

func DecodeRequest

func DecodeRequest(raw []byte) (Request, error)

type Route

type Route struct {
	SchemaVersion int               `json:"schema_version"`
	HandoffID     string            `json:"handoff_id"`
	RequestDigest Digest            `json:"request_digest"`
	TargetMachine string            `json:"target_machine"`
	Courier       Courier           `json:"courier"`
	SSH           *SSHConfig        `json:"ssh,omitempty"`
	Synchestra    *SynchestraConfig `json:"synchestra,omitempty"`
}

Route is the immutable source-side courier address selected before the first delivery attempt. Resume always reuses it, so config/default changes cannot switch an ambiguous handoff to another courier or SSH host.

type SSHConfig

type SSHConfig struct {
	Host string `yaml:"host" json:"host"`
	// User is an optional target account. It is passed to OpenSSH as a fixed
	// `-l` argv pair, never joined with Host or remote command text.
	User   string `yaml:"user,omitempty" json:"user,omitempty"`
	WBPath string `yaml:"wb_path,omitempty" json:"wb_path,omitempty"`
}

func (SSHConfig) Validate

func (c SSHConfig) Validate() error

Validate rejects values that OpenSSH could reinterpret when it constructs the remote shell command. Host is deliberately limited to a configured SSH alias, and a custom WBPath may contain only shell-inert ASCII path segments. An empty WBPath selects the fixed remote command name "wb".

type State

type State struct {
	Request Request        `json:"request"`
	Digest  Digest         `json:"request_digest"`
	Events  []HandoffEvent `json:"events"`
	Receipt *Receipt       `json:"receipt,omitempty"`
}

State is the loaded projection of one durable handoff aggregate.

type Store

type Store struct {
	Root string
	// contains filtered or unexported fields
}

Store persists handoff state at Root, normally <WB_HOME>/handoffs.

func NewStore

func NewStore(root string) Store

func (Store) AcquireExecutionLock

func (s Store) AcquireExecutionLock(ctx context.Context, handoffID string, digest Digest) (*ExecutionLock, error)

AcquireExecutionLock waits interruptibly for the per-handoff receive fence. Callers admit and authenticate exact request bytes before taking this lock.

func (Store) Admit

func (s Store) Admit(raw []byte, digest Digest) (Admission, error)

Admit durably installs exact request bytes. The first caller wins an atomic no-replace publication. Later callers with the same ID must present both the same digest and byte-identical request; they receive any existing receipt.

func (Store) AdmitIncomingMessageUnderLock

func (s Store) AdmitIncomingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, raw []byte, recordedAt time.Time) (MessageState, error)

AdmitIncomingMessageUnderLock installs exact canonical payload bytes in the successor inbox before any paste intent is published.

func (Store) AdmitOutgoingMessageUnderLock

func (s Store) AdmitOutgoingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, raw []byte, recordedAt time.Time) (MessageState, error)

AdmitOutgoingMessageUnderLock installs exact canonical payload bytes in the predecessor outbox before any courier is invoked.

func (Store) AppendEvent

func (s Store) AppendEvent(handoffID string, digest Digest, event HandoffEvent) (HandoffEvent, error)

AppendEvent assigns the next sequence and creates a new immutable event file. It never rewrites a prior phase, including a prior failure.

func (Store) AppendEventUnderLock

func (s Store) AppendEventUnderLock(lock *ExecutionLock, handoffID string, digest Digest, event HandoffEvent) (HandoffEvent, error)

AppendEventUnderLock appends relative to the exact admitted handoff directory retained by a held execution fence.

func (Store) EnsureHandoverUnderLock added in v0.62.3

func (s Store) EnsureHandoverUnderLock(lock *ExecutionLock, handoffID string, digest Digest) (string, error)

EnsureHandoverUnderLock durably and idempotently materializes an admitted request's inline handover content (Request.HandoverContent) as a private 0600 file inside the retained handoff directory, for delivery to the successor as sessionauthority.ContinuationPrivate, and returns its absolute path. Repeat calls for the same handoff are safe: the content comes from the immutable admitted request, so it is always byte-identical, and publishImmutableAt's first-caller-wins publication makes a repeat write a no-op. A pre-cutover request with no inline content is never materialized here; it is delivered the old way instead, by reading the content already committed into the pinned worktree at its legacy HandoverPath.

func (Store) Load

func (s Store) Load(handoffID string) (State, error)

Load reads and validates one complete durable projection.

func (Store) LoadIncomingMessageUnderLock

func (s Store) LoadIncomingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageState, error)

func (Store) LoadOutgoingMessageSynchestraDispatchUnderLock

func (s Store) LoadOutgoingMessageSynchestraDispatchUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageSynchestraDispatch, error)

func (Store) LoadOutgoingMessageUnderLock

func (s Store) LoadOutgoingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageState, error)

func (Store) LoadRoute

func (s Store) LoadRoute(handoffID string) (Route, error)

func (Store) LoadRouteUnderLock

func (s Store) LoadRouteUnderLock(lock *ExecutionLock, handoffID string, digest Digest) (Route, error)

LoadRouteUnderLock reads the courier route from the exact handoff aggregate retained by the held execution fence.

func (Store) LoadSuccessorAddress

func (s Store) LoadSuccessorAddress(successorWBSessionID string) (SuccessorAddress, error)

LoadSuccessorAddress resolves a stable successor WB session ID without consulting current courier configuration.

func (Store) LoadSuccessorAddressUnderLock

func (s Store) LoadSuccessorAddressUnderLock(lock *ExecutionLock, handoffID string, digest Digest) (SuccessorAddress, error)

LoadSuccessorAddressUnderLock corroborates the immutable completed-successor index against the exact request, receipt, and route retained by a held execution fence. Source custody uses this proof immediately before sealing the predecessor Work Log terminal.

func (Store) LoadSynchestraDispatch

func (s Store) LoadSynchestraDispatch(handoffID string) (SynchestraDispatch, error)

LoadSynchestraDispatch returns the exact accepted dispatch for resume.

func (Store) LoadUnderLock

func (s Store) LoadUnderLock(lock *ExecutionLock, handoffID string, digest Digest) (State, error)

LoadUnderLock reads request, events, and receipt from the exact admitted aggregate retained by a held execution fence.

func (Store) ReadHandover added in v0.62.3

func (s Store) ReadHandover(handoffID string) ([]byte, error)

ReadHandover re-reads and re-verifies the private artifact EnsureHandoverUnderLock materialized, using the same hardened single-link, mode-0600 checks as every other durable handoff artifact. It is the exec-time counterpart the private launcher calls right before handing the harness its continuation, so a change to the file between materialization and exec is caught rather than silently trusted.

func (Store) ReadmitUnderLock

func (s Store) ReadmitUnderLock(lock *ExecutionLock, handoffID string, digest Digest, raw []byte) (Admission, error)

ReadmitUnderLock revalidates exact request bytes and returns any durable receipt relative to the aggregate retained by a held execution fence. It is deliberately read-only: callers use it after waiting for the lock, when a path-based Admit could otherwise publish into a swapped decoy directory.

func (Store) RequestBytes

func (s Store) RequestBytes(handoffID string) (Request, Digest, []byte, error)

func (Store) ResumeOutgoingMessageUnderLock

func (s Store) ResumeOutgoingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageState, error)

ResumeOutgoingMessageUnderLock repairs the sole safe source-side admission crash gap: message.json was published but record.json was not. Outgoing RecordedAt is defined to equal caller-owned SentAt, so the exact payload carries all bytes needed to recreate the missing record without guessing.

func (Store) SaveIncomingMessageReceiptUnderLock

func (s Store) SaveIncomingMessageReceiptUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, receipt MessageReceipt) (MessageReceipt, bool, error)

func (Store) SaveIncomingPasteIntentUnderLock

func (s Store) SaveIncomingPasteIntentUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, intent MessagePasteIntent) (MessagePasteIntent, bool, error)

func (Store) SaveOutgoingMessageReceiptUnderLock

func (s Store) SaveOutgoingMessageReceiptUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, receipt MessageReceipt) (MessageReceipt, bool, error)

func (Store) SaveOutgoingMessageSynchestraDispatchUnderLock

func (s Store) SaveOutgoingMessageSynchestraDispatchUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, identity MessageSynchestraDispatch) (MessageSynchestraDispatch, bool, error)

SaveOutgoingMessageSynchestraDispatchUnderLock publishes the first exact dispatch returned for an already-durable outbox message.

func (Store) SaveReceipt

func (s Store) SaveReceipt(handoffID string, digest Digest, receipt Receipt) (Receipt, bool, error)

SaveReceipt durably publishes the target receipt without replacement. Repeating the identical receipt is a successful replay; any change is a conflict because a handoff can have only one successor identity.

func (Store) SaveReceiptUnderLock

func (s Store) SaveReceiptUnderLock(lock *ExecutionLock, handoffID string, digest Digest, receipt Receipt) (Receipt, bool, error)

SaveReceiptUnderLock publishes a receipt relative to the exact handoff directory retained by the held execution fence. Production receive and source-acknowledgement paths use this form so a pathname swap cannot move publication to a different aggregate.

func (Store) SaveRoute

func (s Store) SaveRoute(route Route) (Route, bool, error)

func (Store) SaveSuccessorAddressUnderLock

func (s Store) SaveSuccessorAddressUnderLock(lock *ExecutionLock, handoffID string, digest Digest, receipt Receipt) (SuccessorAddress, bool, error)

SaveSuccessorAddressUnderLock publishes the stable completed-successor index under the exact Store root retained by this handoff's execution lock.

func (Store) SaveSynchestraDispatch

func (s Store) SaveSynchestraDispatch(identity SynchestraDispatch) (SynchestraDispatch, bool, error)

SaveSynchestraDispatch publishes one exact invocation-to-dispatch mapping beneath the already-admitted handoff. The immutable route corroborates the runner; the request corroborates invocation and payload identity.

type SuccessorAddress

type SuccessorAddress struct {
	SchemaVersion          int       `json:"schema_version"`
	SuccessorWBSessionID   string    `json:"successor_wb_session_id"`
	PredecessorWBSessionID string    `json:"predecessor_wb_session_id"`
	HandoffID              string    `json:"handoff_id"`
	RequestDigest          Digest    `json:"request_digest"`
	SourceMachine          string    `json:"source_machine"`
	TargetMachine          string    `json:"target_machine"`
	SourceWorkLogReference string    `json:"source_work_log_reference"`
	TargetWorkLogReference string    `json:"target_work_log_reference"`
	TmuxName               string    `json:"tmux_name"`
	Runtime                string    `json:"runtime"`
	Model                  string    `json:"model,omitempty"`
	NativeHarnessID        string    `json:"native_harness_id,omitempty"`
	AttemptID              string    `json:"attempt_id"`
	AttemptIndex           uint64    `json:"attempt_index"`
	PID                    int       `json:"pid"`
	PinnedCommit           string    `json:"pinned_commit"`
	StartedAt              time.Time `json:"started_at"`
	Route                  Route     `json:"route"`
}

SuccessorAddress is the durable courier-neutral address of one completed successor. It is keyed by stable WB session ID so later messaging and a handoff-back request do not depend on a harness-native session identifier.

type SynchestraConfig

type SynchestraConfig struct {
	Runner string `yaml:"runner" json:"runner"`
}

func (SynchestraConfig) Validate

func (c SynchestraConfig) Validate() error

Validate keeps the configured runner safe to pass as one fixed argv value. The runner is routing data only; it never contributes shell or command text.

type SynchestraDispatch

type SynchestraDispatch struct {
	SchemaVersion int    `json:"schema_version"`
	HandoffID     string `json:"handoff_id"`
	RequestDigest Digest `json:"request_digest"`
	Runner        string `json:"runner"`
	InvocationID  string `json:"invocation_id"`
	Handler       string `json:"handler"`
	DispatchID    string `json:"dispatch_id"`
}

SynchestraDispatch is the immutable transport identity returned by the first accepted typed invocation. Resume observes this exact dispatch rather than selecting a new runner or manufacturing a second invocation.

type TargetConfig

type TargetConfig struct {
	Machine        string            `yaml:"-" json:"machine"`
	DefaultCourier Courier           `yaml:"default_courier" json:"default_courier"`
	SSH            *SSHConfig        `yaml:"ssh,omitempty" json:"ssh,omitempty"`
	Synchestra     *SynchestraConfig `yaml:"synchestra,omitempty" json:"synchestra,omitempty"`
}

TargetConfig is one WB machine and its separate courier addresses. Machine is populated from the targets map key and is never decoded from an address.

type UnconfiguredError

type UnconfiguredError struct{ Path string }

UnconfiguredError distinguishes an absent session_move section from invalid configured values, so a future command can map the former to usage help.

func (*UnconfiguredError) Error

func (e *UnconfiguredError) Error() string

type WorkLogReference

type WorkLogReference struct {
	EffortID string
	RunID    string
	ClaimID  string
}

WorkLogReference is the parsed identity of one Work Log claim. Its wire spelling stays a single portable string so handoff protocol values do not expose a machine-local Work Log directory layout.

func ExpectedTargetWorkLogReference

func ExpectedTargetWorkLogReference(request Request, requestDigest Digest) (WorkLogReference, error)

ExpectedTargetWorkLogReference keeps the source effort and run while replacing its predecessor claim with the deterministic external target claim. The caller supplies the digest of the exact admitted bytes, which may use any valid JSON whitespace; Store or ExecutionLock owns raw-byte proof.

func ParseWorkLogReference

func ParseWorkLogReference(value string) (WorkLogReference, error)

ParseWorkLogReference accepts only the canonical worklog:<effort>/<run>/<64-lowercase-hex-claim> spelling.

func (WorkLogReference) String

func (reference WorkLogReference) String() string

String returns the canonical portable reference spelling.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL