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
- Variables
- func EncodeMessage(message Message) ([]byte, error)
- func EncodeMessageReceipt(receipt MessageReceipt) ([]byte, error)
- func EncodeReceipt(receipt Receipt) ([]byte, error)
- func EncodeRequest(request Request) ([]byte, error)
- func ExternalHandoffClaimID(requestDigest Digest, successorWBSessionID string) (string, error)
- func NewHandoffID() (string, error)
- func NewMessageID() (string, error)
- func NormalizeSourceOfferContent(message, nextAction string) (string, string)
- func ValidateMessageForRequest(message Message, request Request) error
- func ValidateMessageReceipt(receipt MessageReceipt, message Message, digest Digest, tmuxName string, ...) error
- func ValidateReceiptForRequest(receipt Receipt, request Request, digest Digest) error
- type Admission
- type Config
- type Courier
- type Digest
- type ExecutionLock
- func (lock *ExecutionLock) Close() error
- func (lock *ExecutionLock) HeldForSession(expectedRoot, aggregateID, digest string) bool
- func (lock *ExecutionLock) HeldForStore(expectedRoot string, request Request, digest Digest) bool
- func (lock *ExecutionLock) RetainHandoffForStore(expectedRoot string, request Request, digest Digest) (*os.File, error)
- func (lock *ExecutionLock) RetainSessionDir(expectedRoot, aggregateID, digest string) (*os.File, error)
- func (lock *ExecutionLock) RetainStoreRootForStore(expectedRoot string, request Request, digest Digest) (*os.File, error)
- type HandoffEvent
- type Message
- type MessageDirection
- type MessageKind
- type MessagePasteIntent
- type MessageReceipt
- type MessageRecord
- type MessageState
- type MessageSynchestraDispatch
- type Phase
- type Receipt
- type Request
- type Route
- type SSHConfig
- type State
- type Store
- func (s Store) AcquireExecutionLock(ctx context.Context, handoffID string, digest Digest) (*ExecutionLock, error)
- func (s Store) Admit(raw []byte, digest Digest) (Admission, error)
- func (s Store) AdmitIncomingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, raw []byte, ...) (MessageState, error)
- func (s Store) AdmitOutgoingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, raw []byte, ...) (MessageState, error)
- func (s Store) AppendEvent(handoffID string, digest Digest, event HandoffEvent) (HandoffEvent, error)
- func (s Store) AppendEventUnderLock(lock *ExecutionLock, handoffID string, digest Digest, event HandoffEvent) (HandoffEvent, error)
- func (s Store) Load(handoffID string) (State, error)
- func (s Store) LoadIncomingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageState, error)
- func (s Store) LoadOutgoingMessageSynchestraDispatchUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageSynchestraDispatch, error)
- func (s Store) LoadOutgoingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageState, error)
- func (s Store) LoadRoute(handoffID string) (Route, error)
- func (s Store) LoadRouteUnderLock(lock *ExecutionLock, handoffID string, digest Digest) (Route, error)
- func (s Store) LoadSuccessorAddress(successorWBSessionID string) (SuccessorAddress, error)
- func (s Store) LoadSuccessorAddressUnderLock(lock *ExecutionLock, handoffID string, digest Digest) (SuccessorAddress, error)
- func (s Store) LoadSynchestraDispatch(handoffID string) (SynchestraDispatch, error)
- func (s Store) LoadUnderLock(lock *ExecutionLock, handoffID string, digest Digest) (State, error)
- func (s Store) ReadmitUnderLock(lock *ExecutionLock, handoffID string, digest Digest, raw []byte) (Admission, error)
- func (s Store) RequestBytes(handoffID string) (Request, Digest, []byte, error)
- func (s Store) ResumeOutgoingMessageUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, messageID string) (MessageState, error)
- func (s Store) SaveIncomingMessageReceiptUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, ...) (MessageReceipt, bool, error)
- func (s Store) SaveIncomingPasteIntentUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, ...) (MessagePasteIntent, bool, error)
- func (s Store) SaveOutgoingMessageReceiptUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, ...) (MessageReceipt, bool, error)
- func (s Store) SaveOutgoingMessageSynchestraDispatchUnderLock(lock *ExecutionLock, handoffID string, requestDigest Digest, ...) (MessageSynchestraDispatch, bool, error)
- func (s Store) SaveReceipt(handoffID string, digest Digest, receipt Receipt) (Receipt, bool, error)
- func (s Store) SaveReceiptUnderLock(lock *ExecutionLock, handoffID string, digest Digest, receipt Receipt) (Receipt, bool, error)
- func (s Store) SaveRoute(route Route) (Route, bool, error)
- func (s Store) SaveSuccessorAddressUnderLock(lock *ExecutionLock, handoffID string, digest Digest, receipt Receipt) (SuccessorAddress, bool, error)
- func (s Store) SaveSynchestraDispatch(identity SynchestraDispatch) (SynchestraDispatch, bool, error)
- type SuccessorAddress
- type SynchestraConfig
- type SynchestraDispatch
- type TargetConfig
- type UnconfiguredError
- type WorkLogReference
Constants ¶
const ( SynchestraDispatchSchemaVersion = 1 SynchestraSessionAcceptHandler = "wb.session.accept.v1" SynchestraSessionMessageHandler = "wb.session.message.v1" MessageSynchestraDispatchSchemaVersion = 1 )
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 )
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.
const RouteSchemaVersion = 1
const SuccessorAddressSchemaVersion = 1
Variables ¶
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 EncodeMessageReceipt ¶
func EncodeMessageReceipt(receipt MessageReceipt) ([]byte, error)
func EncodeReceipt ¶
func EncodeRequest ¶
EncodeRequest validates and renders the canonical JSON spelling used by a source. A receiver still preserves whichever exact valid bytes it receives.
func ExternalHandoffClaimID ¶
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 ¶
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 ¶
NewMessageID returns a caller-owned identity that can be persisted before courier use and supplied to the explicit retry path after ambiguity.
func NormalizeSourceOfferContent ¶
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 ValidateMessageForRequest ¶
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.
Types ¶
type Admission ¶
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 ¶
LoadConfig reads and validates only session_move while tolerating unrelated top-level WB configuration sections.
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.
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 ¶
DigestBytes returns the sha256 digest of exact bytes.
func DigestSourceOffer ¶
DigestSourceOffer derives the authenticated content digest for an immutable source Work Log offer. Length-prefixing the domain and both normalized fields prevents boundary ambiguity.
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 ¶
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.
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 ¶
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 string `json:"handover_path"`
HandoverDigest Digest `json:"handover_digest"`
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"`
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 ¶
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 ¶
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
}
Store persists handoff state at Root, normally <WB_HOME>/handoffs.
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 ¶
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) 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) 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 ¶
LoadUnderLock reads request, events, and receipt from the exact admitted aggregate retained by a held execution fence.
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 (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 ¶
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) 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 ¶
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.