registry

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 29, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// StorePathEnv overrides the exact registry store path.
	StorePathEnv = "AHT_STORE"
	// StateDirEnv overrides the registry state directory.
	StateDirEnv = "AHT_STATE_DIR"
)
View Source
const IntegrationActivityLease = 30 * time.Second

IntegrationActivityLease is the maximum age of a matching integration transition before multiplexer screen evidence becomes authoritative again.

Variables

View Source
var (
	ErrUnknownHarness     = errors.New("unknown harness")
	ErrUnknownPresence    = errors.New("unknown presence")
	ErrUnknownActivity    = errors.New("unknown activity")
	ErrUnknownSource      = errors.New("unknown observation source")
	ErrUnknownEvidence    = errors.New("unknown observation evidence")
	ErrInvalidObservation = errors.New("invalid observation")
)
View Source
var (
	ErrSessionNotFound     = errors.New("session not found")
	ErrHarnessRequired     = errors.New("harness is required")
	ErrObservationIdentity = errors.New("observation requires identity")
	ErrObservationConflict = errors.New("observation conflicts with accepted evidence")
	ErrCorruptStore        = errors.New("corrupt registry store")
)

Functions

func DefaultStateDir

func DefaultStateDir() string

func DefaultStorePath

func DefaultStorePath() string

func ValidateObservation

func ValidateObservation(observation Observation) error

Types

type Activity

type Activity string
const (
	ActivityRunning     Activity = "running"
	ActivityWaiting     Activity = "waiting"
	ActivityIdle        Activity = "idle"
	ActivityFailed      Activity = "failed"
	ActivityInterrupted Activity = "interrupted"
	ActivityUnknown     Activity = "unknown"
)

func NormalizeActivity

func NormalizeActivity(value string) (Activity, error)

type ActivityDecision

type ActivityDecision struct {
	Authority       string          `json:"authority"`
	Reason          string          `json:"reason"`
	RuleID          string          `json:"rule_id,omitempty"`
	ManifestSource  string          `json:"manifest_source,omitempty"`
	ManifestVersion int             `json:"manifest_version,omitempty"`
	FallbackReason  string          `json:"fallback_reason,omitempty"`
	Process         ProcessIdentity `json:"process,omitzero"`
	ObservedAt      time.Time       `json:"observed_at"`
}

type CatalogMetadata

type CatalogMetadata struct {
	ResumeCommand []string `json:"resume_command,omitempty"`
	CWD           string   `json:"cwd,omitempty"`
	ProjectRoot   string   `json:"project_root,omitempty"`
	ProcessPID    int      `json:"process_pid,omitempty"`
	Current       bool     `json:"-"`
}

type CatalogObservation

type CatalogObservation struct {
	SessionID     string    `json:"session_id,omitempty"`
	SessionPath   string    `json:"session_path,omitempty"`
	ResumeCommand []string  `json:"resume_command,omitempty"`
	CWD           string    `json:"cwd,omitempty"`
	ProjectRoot   string    `json:"project_root,omitempty"`
	ProcessPID    int       `json:"process_pid,omitempty"`
	ObservedAt    time.Time `json:"observed_at"`
}

type FileStore

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

func NewFileStore

func NewFileStore(path string) *FileStore

func (*FileStore) GC

func (s *FileStore) GC(ctx context.Context, deleteAfter time.Duration) (GCResult, error)

func (*FileStore) Get

func (s *FileStore) Get(ctx context.Context, id string) (Session, error)

func (*FileStore) List

func (s *FileStore) List(ctx context.Context, filter Filter) ([]Session, error)

func (*FileStore) Observe

func (s *FileStore) Observe(ctx context.Context, observation Observation) (Session, error)

func (*FileStore) ObserveBatch

func (s *FileStore) ObserveBatch(ctx context.Context, observations []Observation) ([]Session, error)

func (*FileStore) Path

func (s *FileStore) Path() string

func (*FileStore) Reset

func (s *FileStore) Reset(ctx context.Context) (ResetResult, error)

func (*FileStore) SetNowForTest

func (s *FileStore) SetNowForTest(now func() time.Time)

func (*FileStore) SummaryByTmuxSession

func (s *FileStore) SummaryByTmuxSession(ctx context.Context, filter Filter) ([]Summary, error)

func (*FileStore) SummaryByTmuxSessionWithOptions

func (s *FileStore) SummaryByTmuxSessionWithOptions(ctx context.Context, options SummaryOptions) ([]Summary, error)

func (*FileStore) Watch

func (s *FileStore) Watch(ctx context.Context, options WatchOptions, yield func(WatchResult) error) error

Watch yields serialized snapshots until ctx is canceled or yield returns an error. It observes the store directory before the initial scan and keeps its parent watched so atomic replacement and directory recreation remain visible.

type Filter

type Filter struct {
	Harness            Harness
	Presence           Presence
	Activity           Activity
	TmuxSession        string
	MultiplexerSession string
}

type GCResult

type GCResult struct {
	Deleted   int `json:"deleted"`
	Remaining int `json:"remaining"`
}

type Harness

type Harness string
const (
	HarnessClaude   Harness = harnessmeta.IDClaude
	HarnessCodex    Harness = harnessmeta.IDCodex
	HarnessCursor   Harness = harnessmeta.IDCursor
	HarnessCopilot  Harness = harnessmeta.IDCopilot
	HarnessCline    Harness = harnessmeta.IDCline
	HarnessKimiCode Harness = harnessmeta.IDKimiCode
	HarnessGrok     Harness = harnessmeta.IDGrok
	HarnessGoose    Harness = harnessmeta.IDGoose
	HarnessPi       Harness = harnessmeta.IDPi
	HarnessOmp      Harness = harnessmeta.IDOmp
	HarnessOhMyPi   Harness = HarnessOmp
	HarnessOpenCode Harness = harnessmeta.IDOpenCode
	HarnessAgy      Harness = harnessmeta.IDAgy
	HarnessKilo     Harness = harnessmeta.IDKilo
	HarnessDroid    Harness = harnessmeta.IDDroid
	HarnessOpenClaw Harness = harnessmeta.IDOpenClaw
	HarnessHermes   Harness = harnessmeta.IDHermes
)

func NormalizeHarness

func NormalizeHarness(value string) (Harness, error)

type MemoryStore

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

MemoryStore keeps the authoritative registry in memory while retaining the same evidence reducer and query contract as FileStore.

func OpenMemoryStore

func OpenMemoryStore(path string) (*MemoryStore, error)

OpenMemoryStore loads path once and returns an in-memory authoritative store.

func (*MemoryStore) Flush

func (s *MemoryStore) Flush(ctx context.Context) error

Flush atomically persists the latest in-memory snapshot.

func (*MemoryStore) GC

func (s *MemoryStore) GC(ctx context.Context, deleteAfter time.Duration) (GCResult, error)

GC removes expired gone-session tombstones from memory.

func (*MemoryStore) Get

func (s *MemoryStore) Get(ctx context.Context, id string) (Session, error)

Get returns a defensive copy of one session.

func (*MemoryStore) List

func (s *MemoryStore) List(ctx context.Context, filter Filter) ([]Session, error)

List returns a defensive copy of all sessions matching filter.

func (*MemoryStore) Observe

func (s *MemoryStore) Observe(ctx context.Context, observation Observation) (Session, error)

Observe records one observation atomically.

func (*MemoryStore) ObserveBatch

func (s *MemoryStore) ObserveBatch(ctx context.Context, observations []Observation) ([]Session, error)

ObserveBatch atomically reduces observations into memory and notifies state subscribers only when the effective consumer-visible state changes.

func (*MemoryStore) Path

func (s *MemoryStore) Path() string

Path returns the durable snapshot path associated with the store.

func (*MemoryStore) RunPersistence

func (s *MemoryStore) RunPersistence(ctx context.Context, settle, maximumDelay time.Duration) error

RunPersistence coalesces bursts of observations into durable atomic snapshots. The caller owns this loop and must cancel ctx before discarding the store.

func (*MemoryStore) SetNowForTest

func (s *MemoryStore) SetNowForTest(now func() time.Time)

SetNowForTest replaces the receipt clock. It is intended for deterministic tests.

func (*MemoryStore) State

func (s *MemoryStore) State(ctx context.Context, filter Filter) (StateSnapshot, error)

State returns the latest effective state and its monotonic revision.

func (*MemoryStore) SummaryByTmuxSession

func (s *MemoryStore) SummaryByTmuxSession(ctx context.Context, filter Filter) ([]Summary, error)

SummaryByTmuxSession returns summaries computed from one in-memory snapshot.

func (*MemoryStore) SummaryByTmuxSessionWithOptions

func (s *MemoryStore) SummaryByTmuxSessionWithOptions(
	ctx context.Context,
	options SummaryOptions,
) ([]Summary, error)

SummaryByTmuxSessionWithOptions returns summaries for the supplied filter.

func (*MemoryStore) WaitForRevision

func (s *MemoryStore) WaitForRevision(ctx context.Context, after uint64, filter Filter) (StateSnapshot, error)

WaitForRevision blocks until a state revision newer than after is available.

type MultiplexerContext

type MultiplexerContext struct {
	Kind            MultiplexerKind `json:"kind"`
	ServerID        string          `json:"server_id,omitempty"`
	SessionID       string          `json:"session_id,omitempty"`
	SessionName     string          `json:"session_name,omitempty"`
	WorkspaceID     string          `json:"workspace_id,omitempty"`
	WorkspaceName   string          `json:"workspace_name,omitempty"`
	TabID           string          `json:"tab_id,omitempty"`
	TabIndex        string          `json:"tab_index,omitempty"`
	TabName         string          `json:"tab_name,omitempty"`
	WindowID        string          `json:"window_id,omitempty"`
	WindowIndex     string          `json:"window_index,omitempty"`
	WindowName      string          `json:"window_name,omitempty"`
	PaneID          string          `json:"pane_id,omitempty"`
	PaneIndex       string          `json:"pane_index,omitempty"`
	PaneCurrentPath string          `json:"pane_current_path,omitempty"`
	PanePID         int             `json:"pane_pid,omitempty"`
	PaneTTY         string          `json:"pane_tty,omitempty"`
	ClientTTY       string          `json:"client_tty,omitempty"`
}

MultiplexerContext identifies an addressable terminal pane. Window fields represent tmux windows, while workspace and tab fields represent native Zellij and Herdr containers.

func MultiplexerFromTmux

func MultiplexerFromTmux(c TmuxContext) MultiplexerContext

func (MultiplexerContext) Empty

func (c MultiplexerContext) Empty() bool

func (MultiplexerContext) TmuxContext

func (c MultiplexerContext) TmuxContext() TmuxContext

type MultiplexerKind

type MultiplexerKind string
const (
	MultiplexerTmux   MultiplexerKind = "tmux"
	MultiplexerZellij MultiplexerKind = "zellij"
	MultiplexerHerdr  MultiplexerKind = "herdr"
)

type MultiplexerObservation

type MultiplexerObservation struct {
	Process    ProcessIdentity    `json:"process"`
	Context    MultiplexerContext `json:"context"`
	ObservedAt time.Time          `json:"observed_at"`
}

type NativeLifecycle

type NativeLifecycle string
const (
	NativeLifecycleStart  NativeLifecycle = "start"
	NativeLifecycleResume NativeLifecycle = "resume"
	NativeLifecycleEnd    NativeLifecycle = "end"
)

func NormalizeLifecycle

func NormalizeLifecycle(value string) (NativeLifecycle, error)

type NativeObservation

type NativeObservation struct {
	Event                 string            `json:"event,omitempty"`
	Lifecycle             *NativeLifecycle  `json:"lifecycle,omitempty"`
	Presence              *Presence         `json:"presence,omitempty"`
	Activity              *Activity         `json:"activity,omitempty"`
	ActivityAuthoritative *bool             `json:"activity_authoritative,omitempty"`
	Sequence              *uint64           `json:"sequence,omitempty"`
	SessionID             string            `json:"session_id,omitempty"`
	SessionPath           string            `json:"session_path,omitempty"`
	ObservedAt            time.Time         `json:"observed_at"`
	Attributes            map[string]string `json:"attributes,omitempty"`
	RawPayload            json.RawMessage   `json:"raw_payload,omitempty"`
	Process               ProcessIdentity   `json:"process,omitzero"`
}

type Observation

type Observation struct {
	Source                ObservationSource   `json:"source"`
	Evidence              ObservationEvidence `json:"evidence"`
	Harness               Harness             `json:"harness"`
	Identity              ObservationIdentity `json:"identity"`
	Lifecycle             *NativeLifecycle    `json:"lifecycle,omitempty"`
	Presence              *Presence           `json:"presence,omitempty"`
	Activity              *Activity           `json:"activity,omitempty"`
	ActivityAuthoritative *bool               `json:"activity_authoritative,omitempty"`
	Sequence              *uint64             `json:"sequence,omitempty"`
	NativeEvent           string              `json:"native_event,omitempty"`
	ProcessPresent        *bool               `json:"process_present,omitempty"`
	Process               *ProcessIdentity    `json:"process,omitempty"`
	Tmux                  *TmuxContext        `json:"tmux,omitempty"`
	Multiplexer           *MultiplexerContext `json:"multiplexer,omitempty"`
	Catalog               *CatalogMetadata    `json:"catalog,omitempty"`
	Attributes            map[string]string   `json:"attributes,omitempty"`
	RawPayload            json.RawMessage     `json:"raw_payload,omitempty"`
	Screen                *ScreenObservation  `json:"screen,omitempty"`
	ObservedAt            time.Time           `json:"observed_at"`
}

type ObservationEvidence

type ObservationEvidence string
const (
	ObservationEvidenceNativeEvent         ObservationEvidence = "native_event"
	ObservationEvidenceProcessPresence     ObservationEvidence = "process_presence"
	ObservationEvidenceTmuxLocation        ObservationEvidence = "tmux_location"
	ObservationEvidenceMultiplexerLocation ObservationEvidence = "multiplexer_location"
	ObservationEvidenceCatalogMetadata     ObservationEvidence = "catalog_metadata"
	ObservationEvidenceScreenState         ObservationEvidence = "screen_state"
)

func NormalizeEvidence

func NormalizeEvidence(value string) (ObservationEvidence, error)

type ObservationIdentity

type ObservationIdentity struct {
	SessionID   string `json:"session_id,omitempty"`
	SessionPath string `json:"session_path,omitempty"`
}

type ObservationSource

type ObservationSource string
const (
	ObservationSourceNative      ObservationSource = "native"
	ObservationSourceProcess     ObservationSource = "process"
	ObservationSourceTmux        ObservationSource = "tmux"
	ObservationSourceMultiplexer ObservationSource = "multiplexer"
	ObservationSourceCatalog     ObservationSource = "catalog"
	ObservationSourceScreen      ObservationSource = "screen"
)

func NormalizeSource

func NormalizeSource(value string) (ObservationSource, error)

type Observations

type Observations struct {
	Native      *NativeObservation      `json:"native,omitempty"`
	Process     *ProcessObservation     `json:"process,omitempty"`
	Tmux        *TmuxObservation        `json:"tmux,omitempty"`
	Multiplexer *MultiplexerObservation `json:"multiplexer,omitempty"`
	Catalog     *CatalogObservation     `json:"catalog,omitempty"`
	Screen      *ScreenObservation      `json:"screen,omitempty"`
}

type Presence

type Presence string
const (
	PresenceLive    Presence = "live"
	PresenceGone    Presence = "gone"
	PresenceUnknown Presence = "unknown"
)

func NormalizePresence

func NormalizePresence(value string) (Presence, error)

type ProcessIdentity

type ProcessIdentity struct {
	PID            int    `json:"pid"`
	PPID           int    `json:"ppid"`
	ProcessGroupID int    `json:"process_group_id"`
	Foreground     bool   `json:"foreground"`
	StartIdentity  string `json:"start_identity"`
	Executable     string `json:"executable"`
	CWD            string `json:"cwd"`
	TTY            string `json:"tty"`
}

func (ProcessIdentity) Complete

func (p ProcessIdentity) Complete() bool

func (ProcessIdentity) Equal

func (p ProcessIdentity) Equal(other ProcessIdentity) bool

type ProcessObservation

type ProcessObservation struct {
	Present    bool            `json:"present"`
	Process    ProcessIdentity `json:"process"`
	ObservedAt time.Time       `json:"observed_at"`
}

type ResetResult

type ResetResult struct {
	Cleared   int `json:"cleared"`
	Remaining int `json:"remaining"`
}

type ScreenObservation

type ScreenObservation struct {
	Activity               Activity        `json:"activity"`
	Authority              string          `json:"authority"`
	Reason                 string          `json:"reason"`
	RuleID                 string          `json:"rule_id,omitempty"`
	ManifestSource         string          `json:"manifest_source,omitempty"`
	ManifestVersion        int             `json:"manifest_version,omitempty"`
	FallbackForIntegration string          `json:"fallback_for_integration,omitempty"`
	FallbackReason         string          `json:"fallback_reason,omitempty"`
	Process                ProcessIdentity `json:"process"`
	ObservedAt             time.Time       `json:"observed_at"`
}

type Session

type Session struct {
	SchemaVersion     int                `json:"schema_version"`
	ID                string             `json:"id"`
	Harness           Harness            `json:"harness"`
	Presence          Presence           `json:"presence"`
	Activity          *Activity          `json:"activity"`
	SessionID         string             `json:"session_id,omitempty"`
	SessionPath       string             `json:"session_path,omitempty"`
	ResumeCommand     []string           `json:"resume_command,omitempty"`
	CWD               string             `json:"cwd,omitempty"`
	ProjectRoot       string             `json:"project_root,omitempty"`
	Process           *ProcessIdentity   `json:"process,omitempty"`
	Tmux              TmuxContext        `json:"tmux,omitzero"`
	Multiplexer       MultiplexerContext `json:"multiplexer,omitzero"`
	Observations      Observations       `json:"observations"`
	CreatedAt         time.Time          `json:"created_at"`
	UpdatedAt         time.Time          `json:"updated_at"`
	PresenceChangedAt time.Time          `json:"presence_changed_at"`
	ActivityChangedAt time.Time          `json:"activity_changed_at"`
	ActivityDecision  *ActivityDecision  `json:"activity_decision,omitempty"`
}

type StateSnapshot

type StateSnapshot struct {
	Revision  uint64    `json:"revision"`
	UpdatedAt time.Time `json:"updated_at"`
	Sessions  []Session `json:"sessions"`
}

StateSnapshot is an immutable, filtered view of the effective registry state. Revision advances only when state visible to consumers changes; observation heartbeats that merely refresh evidence timestamps do not advance it.

type Store

type Store interface {
	Observe(ctx context.Context, observation Observation) (Session, error)
	ObserveBatch(ctx context.Context, observations []Observation) ([]Session, error)
	List(ctx context.Context, filter Filter) ([]Session, error)
	Get(ctx context.Context, id string) (Session, error)
	SummaryByTmuxSession(ctx context.Context, filter Filter) ([]Summary, error)
	SummaryByTmuxSessionWithOptions(ctx context.Context, options SummaryOptions) ([]Summary, error)
	GC(ctx context.Context, deleteAfter time.Duration) (GCResult, error)
}

func OpenDefaultStore

func OpenDefaultStore() Store

type Summary

type Summary struct {
	MultiplexerKind        MultiplexerKind `json:"multiplexer_kind,omitempty"`
	MultiplexerSessionID   string          `json:"multiplexer_session_id,omitempty"`
	MultiplexerSessionName string          `json:"multiplexer_session_name,omitempty"`
	TmuxSessionID          string          `json:"tmux_session_id,omitempty"`
	TmuxSessionName        string          `json:"tmux_session_name,omitempty"`
	Total                  int             `json:"total"`
	Live                   int             `json:"live"`
	Gone                   int             `json:"gone"`
	PresenceUnknown        int             `json:"presence_unknown"`
	Running                int             `json:"running"`
	Waiting                int             `json:"waiting"`
	Idle                   int             `json:"idle"`
	ActivityUnknown        int             `json:"activity_unknown"`
}

func SummaryByTmuxSession

func SummaryByTmuxSession(ctx context.Context, filter Filter) ([]Summary, error)

func SummaryByTmuxSessionWithOptions

func SummaryByTmuxSessionWithOptions(ctx context.Context, options SummaryOptions) ([]Summary, error)

type SummaryOptions

type SummaryOptions struct{ Filter Filter }

type TmuxContext

type TmuxContext struct {
	Inside          bool   `json:"inside"`
	ServerSocket    string `json:"server_socket,omitempty"`
	SessionID       string `json:"session_id,omitempty"`
	SessionName     string `json:"session_name,omitempty"`
	WindowID        string `json:"window_id,omitempty"`
	WindowIndex     string `json:"window_index,omitempty"`
	WindowName      string `json:"window_name,omitempty"`
	PaneID          string `json:"pane_id,omitempty"`
	PaneIndex       string `json:"pane_index,omitempty"`
	PaneCurrentPath string `json:"pane_current_path,omitempty"`
	PanePID         int    `json:"pane_pid,omitempty"`
	PaneTTY         string `json:"pane_tty,omitempty"`
	ClientTTY       string `json:"client_tty,omitempty"`
}

func (TmuxContext) Empty

func (c TmuxContext) Empty() bool

type TmuxObservation

type TmuxObservation struct {
	Process    ProcessIdentity `json:"process"`
	Context    TmuxContext     `json:"context"`
	ObservedAt time.Time       `json:"observed_at"`
}

type UnsupportedSchemaError

type UnsupportedSchemaError struct {
	Path    string
	Version int
}

func (*UnsupportedSchemaError) Error

func (e *UnsupportedSchemaError) Error() string

type WatchOptions

type WatchOptions struct {
	Filter            Filter
	Debounce          time.Duration
	ReconcileInterval time.Duration
}

WatchOptions controls filtering and filesystem event coalescing. Non-positive durations use package defaults.

type WatchResult

type WatchResult struct {
	Sessions  []Session
	UpdatedAt time.Time
	Initial   bool
	Err       error
}

WatchResult is an authoritative filtered snapshot or a transient watch/read error. Error results retain the most recent successful snapshot, when one is available. Initial is true only for the first successful snapshot.

Jump to

Keyboard shortcuts

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