Documentation
¶
Overview ¶
Package worktreecollab owns the opt-in current owner, participants, and private local inbox for one corroborated worktree. It never changes a Work Log claim or interprets historical owner events as simultaneous owners.
Index ¶
- Constants
- Variables
- type Checkout
- type CheckoutRebind
- type InboxView
- type Member
- type Message
- type ObservedOwner
- type OwnerChange
- type Participant
- type SendReceipt
- type SendRequest
- type Service
- func (service Service) Ack(ctx context.Context, idOrPath, messageID string) (uint64, error)
- func (service Service) Inbox(ctx context.Context, idOrPath string) (InboxView, error)
- func (service Service) Inspect(ctx context.Context, idOrPath string) (View, error)
- func (service Service) Join(ctx context.Context, idOrPath string) (State, error)
- func (service Service) Leave(ctx context.Context, idOrPath string) (State, error)
- func (service Service) Rebind(ctx context.Context, idOrPath, expectedRoot string) (State, error)
- func (service Service) Send(ctx context.Context, idOrPath, key string, recipients []string, body string) (SendReceipt, bool, error)
- func (service Service) Take(ctx context.Context, idOrPath, expected string, force bool, reason string) (State, error)
- func (service Service) Transfer(ctx context.Context, idOrPath, successor string) (State, error)
- type ServicePorts
- type State
- func (state *State) Ack(recipient, messageID, messageDigest string, at time.Time) (uint64, error)
- func (state *State) Inbox(recipient string) ([]Message, error)
- func (state *State) Join(caller string, at time.Time) error
- func (state *State) Leave(caller string) error
- func (state *State) Send(request SendRequest) (SendReceipt, bool, error)
- func (state *State) Take(request TakeRequest) error
- func (state *State) Transfer(caller, successor string, successorLive bool, at time.Time) error
- func (state State) Validate(checkout Checkout) error
- func (state State) ValidateRebind(checkout Checkout, expectedRoot string) error
- type Store
- func (store Store) Load(checkout Checkout) (State, bool, error)
- func (store Store) Rebind(ctx context.Context, checkout Checkout, expectedRoot, actor string, ...) (State, error)
- func (store Store) WithLocked(ctx context.Context, checkout Checkout, change func(*State, bool) error) (result State, returnErr error)
- type StorePorts
- type TakeRequest
- type View
Constants ¶
const ( SchemaVersion = 1 MaxMessageBodyBytes = 64 << 10 MaxPendingPerPeer = 128 MaxStoredMessages = 4096 NoOwner = "none" )
Variables ¶
var ErrConflict = errors.New("worktree coordination conflict")
Functions ¶
This section is empty.
Types ¶
type Checkout ¶
type Checkout struct {
ID string `json:"id"`
Root string `json:"root"`
GitDir string `json:"git_dir"`
CommonDir string `json:"common_dir"`
}
Checkout binds coordination state to Git's registered worktree identity. Root is presentation/relocation evidence; GitDir and CommonDir identify the linked checkout and canonical repository independently of path aliases.
type CheckoutRebind ¶
type CheckoutRebind struct {
PreviousRoot string `json:"previous_root"`
CurrentRoot string `json:"current_root"`
Actor string `json:"actor"`
At time.Time `json:"at"`
}
CheckoutRebind records an explicit recovery when Git reuses a linked worktree's administrative directory after the former checkout root has been retired. It changes only the presentation root; the checkout ID, GitDir, and CommonDir remain identical.
type InboxView ¶
type InboxView struct {
Messages []Message `json:"messages"`
Notice *OwnerChange `json:"owner_notice,omitempty"`
}
type Message ¶
type Message struct {
ID string `json:"id"`
Sequence uint64 `json:"sequence"`
Sender string `json:"sender"`
Recipient string `json:"recipient"`
Kind string `json:"kind"`
Body string `json:"body"`
Digest string `json:"digest"`
OwnerEpoch uint64 `json:"owner_epoch"`
RecordedAt time.Time `json:"recorded_at"`
ConsumedAt time.Time `json:"consumed_at,omitempty"`
}
type ObservedOwner ¶
type ObservedOwner struct {
ID string
SessionID string
Status string // live, inactive, or unknown
}
ObservedOwner is an exact observation of legacy custody before the first coordination state is published. ID is opaque when WB cannot bind a live registered session to the historical event.
type OwnerChange ¶
type Participant ¶
type SendReceipt ¶
type SendRequest ¶
type Service ¶
type Service struct {
Store Store
Ports ServicePorts
}
func (Service) Rebind ¶
Rebind repairs only a stale checkout root after a caller explicitly names the prior path. Caller() binds the operation to a live registered WB session, and Store.Rebind additionally requires that session to be the current owner.
type ServicePorts ¶
type ServicePorts struct {
Resolve func(context.Context, string) (Checkout, error)
Caller func() (string, error)
Live func(string) (bool, error)
OwnerStatus func(string) (string, error) // live, inactive, or unknown
ObserveLegacy func(Checkout) (ObservedOwner, error)
ObserveLegacyForInspection func(Checkout) (ObservedOwner, error)
Now func() time.Time
NewMessageID func() (string, error)
}
ServicePorts bind one CLI invocation to a corroborated checkout, its registered ancestor, recipient liveness, and the historical custody store. None of these observations is supplied by an untrusted command argument.
type State ¶
type State struct {
Version int `json:"version"`
Checkout Checkout `json:"checkout"`
Revision uint64 `json:"revision"`
Owner string `json:"owner"`
OwnerEpoch uint64 `json:"owner_epoch"`
Members map[string]Member `json:"members"`
OwnerChanges []OwnerChange `json:"owner_changes"`
CheckoutRebinds []CheckoutRebind `json:"checkout_rebinds,omitempty"`
Notices map[string]OwnerChange `json:"notices"`
Inboxes map[string][]Message `json:"inboxes"`
Requests map[string]SendReceipt `json:"requests"`
Cursors map[string]uint64 `json:"cursors"`
}
State is one atomically published private snapshot. Owner notices and audit are separate from ordinary inbox capacity, so a full user inbox cannot prevent a transfer or recovery.
func (*State) Send ¶
func (state *State) Send(request SendRequest) (SendReceipt, bool, error)
func (*State) Take ¶
func (state *State) Take(request TakeRequest) error
func (State) ValidateRebind ¶
ValidateRebind permits only an exact root-path correction for the same checkout identity, after the caller supplies the root observed before the worktree path changed. All other checkout fields remain strictly bound.
type Store ¶
type Store struct {
Home string
Ports StorePorts
}
Store keeps one checkout's snapshot under WB's private state directory. A stable per-checkout lock serializes all changes; the lock file is retained so another process cannot acquire a different inode for the same identity.
func (Store) Load ¶
Load reads an atomically published snapshot through held private directories. It never creates the home, coordination directory, lock file, or snapshot. Mutations must still use WithLocked and recheck all authority under its lock.
func (Store) Rebind ¶
func (store Store) Rebind(ctx context.Context, checkout Checkout, expectedRoot, actor string, at time.Time) (State, error)
Rebind changes a stale snapshot's root only after an explicit expected-root comparison. The caller must be the current owner, the previous root must already be absent, and every Git identity field must match. The snapshot write remains under the normal per-checkout lock.
func (Store) WithLocked ¶
func (store Store) WithLocked(ctx context.Context, checkout Checkout, change func(*State, bool) error) (result State, returnErr error)
WithLocked loads, validates, and optionally publishes a snapshot while one cross-process lock is held. The callback must not mutate external authority before it returns: a failed callback never writes coordination state. A missing snapshot is distinct from an initialized but unowned state.
type StorePorts ¶
type StorePorts struct {
OpenHome func(string, bool) (*os.File, error)
OpenChild func(*os.File, string, bool, worktreesecure.ValidSegment) (*os.File, error)
Read func(*os.File, string, any) error
Write func(*os.File, string, any, os.FileMode) error
Lock func(string) lockFile
}
StorePorts are one store invocation's durable boundaries. Callers normally use NewStore; tests can fail a specific boundary without global hooks.