coord

package
v0.9.3 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package coord is the shared multi-agent coordination DB — the "swarm brain". It lives at <main>/.spectackle/cache/coord.db and is shared by all spectackle processes (one per agent session) via WAL-mode SQLite.

It owns: the agent registry (heartbeats), scope leases, the global ID counters (item AND rule IDs — the only collision-free mint across worktrees), the swarm event log (realtime learnings: rejections, rules, drift), replay bookkeeping (applied event IDs), worktree records and the global integrate lock.

coord.db is unversioned but NOT knowledge: losing it loses only ephemeral coordination state. Counters are floor-seeded on every mint (max(stored, scan-derived floor)+1), so deletion can never regress IDs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenName

func GenName() string

GenName generates an agent name when SPECTACKLE_AGENT is unset.

func Overlaps added in v0.7.0

func Overlaps(a, b string) bool

Overlaps exposes the lease overlap semantics for guards that must agree with them byte-for-byte — the worktree-backed target check (B-01KYKSKMHNE2H) refuses on exactly the overlap a lease would have.

Types

type AgentRow

type AgentRow struct {
	Name string
	Pid  int
	HB   time.Time
	Item string
	WT   string
}

AgentRow is one registered agent.

type DB

type DB struct {
	Agent string
	// contains filtered or unexported fields
}

DB wraps the shared coordination database for one agent.

func Open

func Open(path, agent string, pid int) (*DB, error)

Open opens (creating/rebuilding as needed) the coordination DB and registers the agent.

func (*DB) After

func (d *DB) After(after int64, limit int) ([]Event, error)

After returns up to limit events with seq > after, oldest first, skipping this agent's own events.

func (*DB) Agents

func (d *DB) Agents() ([]AgentRow, error)

Agents returns the registry.

func (*DB) Applied

func (d *DB) Applied(item string) (map[string]bool, error)

func (*DB) Blocked

func (d *DB) Blocked(paths []string, agentTTL time.Duration) (*Lease, error)

Blocked returns the first live foreign lease overlapping any of the paths.

func (*DB) Claim

func (d *DB) Claim(paths []string, item string, ttl, agentTTL time.Duration) (*Lease, error)

Claim reserves the paths for this agent, all-or-nothing. A conflicting live foreign lease is returned instead of an error.

func (*DB) Close

func (d *DB) Close() error

Close closes the handle.

func (*DB) Cursor

func (d *DB) Cursor() (int64, error)

Cursor / SetCursor track this agent's last-delivered event seq.

func (*DB) DelWorktree

func (d *DB) DelWorktree(item string) error

func (*DB) Deregister

func (d *DB) Deregister() error

Deregister removes this agent's leases and registry row — the clean goodbye on server shutdown, so short-lived sessions never linger in the swarm view until the TTL sweep.

func (*DB) Emit

func (d *DB) Emit(ev, ref, msg string) error

Emit appends a swarm event (the realtime learning channel).

func (*DB) GetWorktree

func (d *DB) GetWorktree(item string) (Worktree, bool, error)

func (*DB) Heartbeat

func (d *DB) Heartbeat() error

Heartbeat marks this agent alive; called by the tool gate. It is an upsert: an agent whose row was removed by a sibling's sweep (idle past agent_ttl) silently re-registers on its next call instead of heartbeating into a void.

func (*DB) Leases

func (d *DB) Leases(agentTTL time.Duration) ([]Lease, error)

Leases returns all live leases.

func (*DB) Lock added in v0.2.0

func (d *DB) Lock(name string, ttl time.Duration) (bool, string, error)

Lock acquires a named lock row in the `locks` table. It is the one serialization primitive coord.db offers, generalized from what used to be a single hardcoded 'integrate' row: the schema was already generic (name is the primary key), only the caller ever picked one name. Returns (false, holder) when a live foreign lock blocks it; a lock whose ttl expired counts as free, so a holder that crashed mid-operation can never wedge the name forever — the next caller simply takes it.

Re-acquiring a name this same agent already holds extends its expiry instead of blocking (the WHERE clause only rejects a DIFFERENT agent's live row). That is deliberate, not an oversight: within one process, tool calls are already serialized by Server.mu (see mcpserver's gate), so this agent never actually contends with itself for the same name — the row only ever needs to repel OTHER processes. Treating it as reentrant avoids a self-deadlock if a future caller ever nests two locked calls under the same name from the same agent.

func (*DB) LockIntegrate

func (d *DB) LockIntegrate(ttl time.Duration) (bool, string, error)

LockIntegrate acquires the global integration lock (one submit merges at a time) — a thin, name-fixed caller of Lock, kept so the submit path (and its tests) are untouched by the generalization above. Returns (false, holder) when busy; a lock whose ttl expired counts as free (crashed integrator).

func (*DB) MarkApplied

func (d *DB) MarkApplied(item string, eids []string) error

MarkApplied / Applied track replayed event IDs per worktree item.

func (*DB) MaxSeq

func (d *DB) MaxSeq() (int64, error)

MaxSeq returns the highest event sequence number.

func (*DB) NextID

func (d *DB) NextID(kind string, floor int) (int, error)

NextID atomically mints the next number for a counter kind ("item:P", "rule:CUDA-KRN"), never below floor+1 (floor = caller's file-scan max, so a deleted coord.db cannot regress IDs).

func (*DB) PutWorktree

func (d *DB) PutWorktree(w Worktree) error

PutWorktree / GetWorktree / DelWorktree / Worktrees manage worktree records.

func (*DB) RefreshLeases

func (d *DB) RefreshLeases(ttl time.Duration) error

RefreshLeases extends all own leases; called by the tool gate.

func (*DB) Release

func (d *DB) Release(paths []string) error

Release drops leases: the given paths, or all of this agent's when paths is nil. Only own leases are touched.

func (*DB) ReleaseItem

func (d *DB) ReleaseItem(item string) error

ReleaseItem drops all leases bound to an item (any holder — used when aborting an orphaned worktree of a dead agent).

func (*DB) SearchEvents

func (d *DB) SearchEvents(q string, kinds []string, k int) ([]Event, error)

SearchEvents does a LIKE search over the swarm event log (unioned into find scope=rejection|history so sibling learnings surface pre-merge).

func (*DB) SetActive

func (d *DB) SetActive(item, wtRoot string) error

SetActive records the agent's current item and worktree root.

func (*DB) SetCursor

func (d *DB) SetCursor(c int64) error

func (*DB) Sweep

func (d *DB) Sweep(agentTTL time.Duration) ([]Lease, error)

Sweep expires leases of agents whose heartbeat is older than agentTTL and emits an expire event per lease. Returns the expired leases.

func (*DB) Unlock added in v0.2.0

func (d *DB) Unlock(name string) error

Unlock releases a named lock if held by this agent.

func (*DB) UnlockIntegrate

func (d *DB) UnlockIntegrate() error

UnlockIntegrate releases the integration lock if held by this agent.

func (*DB) WithLock added in v0.2.0

func (d *DB) WithLock(name string, fn func() error) error

WithLock runs fn while holding the named lock, and releases it on every exit path — including a panic in fn — via defer. A bare Lock/Unlock pair invites the missing-defer that reintroduces the exact class of bug this exists to close (an early return or panic between the two leaves the name held until its ttl lapses). Acquisition retries on a short jittered interval until it succeeds or writeLockAcquireTimeout elapses, at which point it returns an error naming the current holder instead of blocking forever — a stuck caller should fail loudly, not hang the agent that called it.

WithLock (via coord.DB) is the concrete implementation of workspace.Locker: item/spec/drift's writers call it through workspace.Root.Lock, a small interface workspace declares so those packages need not import coord directly — they persist bundle files, not swarm coordination.

func (*DB) Worktrees

func (d *DB) Worktrees() ([]Worktree, error)

type Event

type Event struct {
	Seq   int64
	T     time.Time
	Agent string
	Ev    string // reject|rule|drift|claim|release|start|submit|abort|expire|remap
	Ref   string
	Msg   string
}

Event is one swarm learning/coordination notice.

type Lease

type Lease struct {
	Path  string // repo-relative dir/file prefix or item ID
	Agent string
	Item  string
	Exp   time.Time
}

Lease is one scope reservation.

type Worktree

type Worktree struct {
	Item, Agent, Branch, Root, Base, State string
	Created                                time.Time
}

Worktree is the coordination record of an open worktree.

Jump to

Keyboard shortcuts

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