Documentation
¶
Overview ¶
Package registry models and stores coding-agent harness state.
Observations from native harness events, process discovery, terminal locations, catalogs, and screen state are reduced into a stable Session view. FileStore provides atomic durable storage, while MemoryStore provides a realtime in-memory authority with explicit persistence.
Programs that only need to inspect the current user's running AHT instance should generally use package client instead of opening the registry directly.
Index ¶
- Constants
- Variables
- func DefaultStateDir() string
- func DefaultStorePath() string
- func ValidateObservation(observation Observation) error
- type Activity
- type ActivityDecision
- type CatalogMetadata
- type CatalogObservation
- type FileStore
- func (s *FileStore) GC(ctx context.Context, deleteAfter time.Duration) (GCResult, error)
- func (s *FileStore) Get(ctx context.Context, id string) (Session, error)
- func (s *FileStore) List(ctx context.Context, filter Filter) ([]Session, error)
- func (s *FileStore) Observe(ctx context.Context, observation Observation) (Session, error)
- func (s *FileStore) ObserveBatch(ctx context.Context, observations []Observation) ([]Session, error)
- func (s *FileStore) Path() string
- func (s *FileStore) Reset(ctx context.Context) (ResetResult, error)
- func (s *FileStore) SummaryByTmuxSession(ctx context.Context, filter Filter) ([]Summary, error)
- func (s *FileStore) SummaryByTmuxSessionWithOptions(ctx context.Context, options SummaryOptions) ([]Summary, error)
- func (s *FileStore) Watch(ctx context.Context, options WatchOptions, yield func(WatchResult) error) error
- type Filter
- type GCResult
- type Harness
- type MemoryStore
- func (s *MemoryStore) Flush(ctx context.Context) error
- func (s *MemoryStore) GC(ctx context.Context, deleteAfter time.Duration) (GCResult, error)
- func (s *MemoryStore) Get(ctx context.Context, id string) (Session, error)
- func (s *MemoryStore) List(ctx context.Context, filter Filter) ([]Session, error)
- func (s *MemoryStore) Observe(ctx context.Context, observation Observation) (Session, error)
- func (s *MemoryStore) ObserveBatch(ctx context.Context, observations []Observation) ([]Session, error)
- func (s *MemoryStore) Path() string
- func (s *MemoryStore) RunPersistence(ctx context.Context, settle, maximumDelay time.Duration) error
- func (s *MemoryStore) State(ctx context.Context, filter Filter) (StateSnapshot, error)
- func (s *MemoryStore) SummaryByTmuxSession(ctx context.Context, filter Filter) ([]Summary, error)
- func (s *MemoryStore) SummaryByTmuxSessionWithOptions(ctx context.Context, options SummaryOptions) ([]Summary, error)
- func (s *MemoryStore) WaitForRevision(ctx context.Context, after uint64, filter Filter) (StateSnapshot, error)
- type MultiplexerContext
- type MultiplexerKind
- type MultiplexerObservation
- type NativeLifecycle
- type NativeObservation
- type Observation
- type ObservationEvidence
- type ObservationIdentity
- type ObservationSource
- type Observations
- type Presence
- type ProcessIdentity
- type ProcessObservation
- type ResetResult
- type ScreenObservation
- type Session
- type StateSnapshot
- type Store
- type Summary
- type SummaryOptions
- type TmuxContext
- type TmuxObservation
- type UnsupportedSchemaError
- type WatchOptions
- type WatchResult
Examples ¶
Constants ¶
const ( // StorePathEnv overrides the exact registry store path. StorePathEnv = "AHT_STORE" // StateDirEnv overrides the registry state directory. StateDirEnv = "AHT_STATE_DIR" )
const IntegrationActivityLease = 30 * time.Second
IntegrationActivityLease is the maximum age of a matching integration transition before multiplexer screen evidence becomes authoritative again.
Variables ¶
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") )
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 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 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 (*FileStore) ObserveBatch ¶
func (*FileStore) SummaryByTmuxSession ¶
func (*FileStore) SummaryByTmuxSessionWithOptions ¶
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 Harness ¶
type Harness string
const ( HarnessClaude Harness = "claude" HarnessCodex Harness = "codex" HarnessCursor Harness = "cursor" HarnessCopilot Harness = "copilot" HarnessCline Harness = "cline" HarnessKimiCode Harness = "kimi-code" HarnessGrok Harness = "grok" HarnessGoose Harness = "goose" HarnessPi Harness = "pi" HarnessOmp Harness = "omp" HarnessOhMyPi Harness = HarnessOmp HarnessOpenCode Harness = "opencode" HarnessAgy Harness = "agy" HarnessKilo Harness = "kilo" HarnessDroid Harness = "droid" HarnessOpenClaw Harness = "openclaw" HarnessHermes Harness = "hermes" )
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) 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 ¶
RunPersistence coalesces bursts of observations into durable atomic snapshots. The caller owns this loop and must cancel ctx before discarding the store.
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 ¶
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 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 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 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 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 ¶
func (*UnsupportedSchemaError) Error ¶
func (e *UnsupportedSchemaError) Error() string
type WatchOptions ¶
WatchOptions controls filtering and filesystem event coalescing. Non-positive durations use package defaults.
type WatchResult ¶
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.