Documentation
¶
Index ¶
- Constants
- Variables
- func AcquirePIDFile(path string) error
- func ExecUpgrade(manifestPath, configFile, clientExecPath string) error
- func HandleConnection(ctx context.Context, conn net.Conn, origin ConnOrigin, sm *SessionManager, ...)
- func IsSystemSession(s *SessionState) bool
- func IsUpgradeCapacityProbeMarker(marker string) bool
- func ListStateBackups(statePath string) []string
- func Listen(sockPath string) (net.Listener, error)
- func ReleasePIDFile(path string)
- func Run(cfg *config.Config, paths config.Paths, configFile, adoptFrom string) (returnErr error)
- func RunAdoptBootstrap(configFile, adoptFrom string, identity AdoptedServiceIdentity) error
- func SaveState(path string, state *State) error
- func StateBackupPath(statePath string, version int) string
- func StopDaemon(pidFile string) error
- func StopDaemonPID(pid int) error
- func ValidateScenarioName(name string) error
- func ValidateSessionName(name string) error
- func WriteManifest(dir string, m *UpgradeManifest) (string, error)
- type AdoptedServiceIdentity
- type CIStatus
- type ConnOrigin
- type CreateOpts
- type CreationConfig
- type GCOrphan
- type IncludedRepoState
- type JailedComment
- type Message
- type MigrationInfo
- type MsgStore
- func (s *MsgStore) Ack(stream, subscriber string, upToSeq int64) error
- func (s *MsgStore) AckLatest(stream, subscriber string) error
- func (s *MsgStore) AckMessages(stream, subscriber string, seqs []int64) error
- func (s *MsgStore) Cleanup(maxAge time.Duration, maxPerStream int) (int64, error)
- func (s *MsgStore) Close() error
- func (s *MsgStore) Conversation(self string, limit int) ([]Message, error)
- func (s *MsgStore) GetJailed(id string) (JailedComment, bool, error)
- func (s *MsgStore) Jail(j JailedComment) (id string, created bool, err error)
- func (s *MsgStore) ListJailed(includeReleased bool) ([]JailedComment, error)
- func (s *MsgStore) ListStreams(subscriber string, includeSystem bool) ([]StreamInfo, error)
- func (s *MsgStore) MarkReleased(id string) (JailedComment, bool, error)
- func (s *MsgStore) Publish(opts PublishOpts) (Message, error)
- func (s *MsgStore) Read(stream, subscriber string, onlyUnread bool, threadID string) ([]Message, error)
- func (s *MsgStore) SetJailListLimit(limit int)
- func (s *MsgStore) Subscribe(stream string) (chan Message, func())
- func (s *MsgStore) TotalUnread(subscriber string) int
- func (s *MsgStore) Unrelease(id string) (bool, error)
- func (s *MsgStore) UnreleasedJailed() ([]JailedComment, error)
- type MsgStoreSettings
- type PRStatus
- type PairedDevice
- type PublishOpts
- type RemoteListener
- type ResourceSample
- type ScenarioCleanupState
- type ScenarioCompletionActionState
- type ScenarioCompletionState
- type ScenarioMemberPolicyState
- type ScenarioPolicyState
- type ScenarioRenderIdentityState
- type ScenarioRenderMemberState
- type ScenarioRenderReferenceState
- type ScenarioRenderState
- type ScenarioResultPublication
- type ScenarioResultPublishRequest
- type ScenarioResultState
- type ScenarioResultStatus
- type ScenarioSession
- type ScenarioState
- type Server
- type SessionDriver
- type SessionManager
- func (sm *SessionManager) AddPendingPairing(label, pubKey string, id TailnetIdentity, now time.Time) (string, chan pairApproval, time.Time, error)
- func (sm *SessionManager) AddToScenario(name string, input protocol.ScenarioSessionInput, rows, cols uint16) (*SessionState, error)
- func (sm *SessionManager) AdoptSessions(manifest *UpgradeManifest) (UpgradeAdoptionResult, error)
- func (sm *SessionManager) ApprovePairing(requestID string, readOnly bool, now time.Time) (deviceID, clientToken string, err error)
- func (sm *SessionManager) ClearAttachedClient(sessionID string, conn net.Conn)
- func (sm *SessionManager) ClearSummary(sessionID string) error
- func (sm *SessionManager) Config() *config.Config
- func (sm *SessionManager) ConvertToInteractive(id string, rows, cols uint16) (SessionState, error)
- func (sm *SessionManager) Create(opts CreateOpts) (SessionState, error)
- func (sm *SessionManager) Delete(id string) error
- func (sm *SessionManager) DeleteScenario(name string) ([]string, error)
- func (sm *SessionManager) DeleteScenarioContext(ctx context.Context, name string) ([]string, error)
- func (sm *SessionManager) DeleteWithChildren(id string, excludeRoot bool) ([]string, error)
- func (sm *SessionManager) DeviceForToken(token string) *PairedDevice
- func (sm *SessionManager) Diagnostics() protocol.DiagnosticsMsg
- func (sm *SessionManager) EnsureHumanToken() error
- func (sm *SessionManager) FindOrphans(now time.Time) []GCOrphan
- func (sm *SessionManager) Fork(name, sourceSessionID string, rows, cols uint16) (SessionState, error)
- func (sm *SessionManager) ForkWithAgent(name, sourceSessionID, targetAgent, targetModel string, rows, cols uint16) (SessionState, error)
- func (sm *SessionManager) Get(id string) (SessionState, bool)
- func (sm *SessionManager) GetPTY(id string) (sessionDriver, bool)
- func (sm *SessionManager) HandleHookReport(sr protocol.StatusReportMsg)
- func (sm *SessionManager) HasAttachedClient(sessionID string) bool
- func (sm *SessionManager) InstanceID() string
- func (sm *SessionManager) InterruptSession(sessionID string) error
- func (sm *SessionManager) IsAttachedClient(sessionID string, conn net.Conn) bool
- func (sm *SessionManager) KickAttachedClient(sessionID string)
- func (sm *SessionManager) List() []SessionState
- func (sm *SessionManager) ListPairings() ([]pendingPairing, []PairedDevice)
- func (sm *SessionManager) ListScenarios() []protocol.ScenarioRecord
- func (sm *SessionManager) LoadState() error
- func (sm *SessionManager) Migrate(id, targetAgent, targetModel string, rows, cols uint16) (SessionState, error)
- func (sm *SessionManager) PrepareUpgrade(listenerFd uintptr, configFile string) (*UpgradeManifest, error)
- func (sm *SessionManager) PublishScenarioResult(auth authContext, request ScenarioResultPublishRequest) (ScenarioResultPublication, error)
- func (sm *SessionManager) RegisterDeviceConn(deviceID string, conn net.Conn)
- func (sm *SessionManager) ReleaseJailed(id string) (JailedComment, error)
- func (sm *SessionManager) ReleaseJailedByAuthor(login string) ([]JailedComment, error)
- func (sm *SessionManager) ReloadConfig() error
- func (sm *SessionManager) RemoteTLSPin() string
- func (sm *SessionManager) Restart(id string, rows, cols uint16) (SessionState, error)
- func (sm *SessionManager) RestartWithChildren(rootID string, excludeRoot bool, rows, cols uint16) ([]string, error)
- func (sm *SessionManager) Restore(id string) (SessionState, error)
- func (sm *SessionManager) RestoreWithChildren(rootID string) ([]SessionState, error)
- func (sm *SessionManager) Resume(id string, rows, cols uint16) (SessionState, error)
- func (sm *SessionManager) ResumeScenario(name string, rows, cols uint16) ([]string, error)
- func (sm *SessionManager) RevokeDevice(deviceID string) (int, error)
- func (sm *SessionManager) RunDetectionLoop(ctx context.Context)
- func (sm *SessionManager) RunFileWatchLoop(ctx context.Context)
- func (sm *SessionManager) RunGC(force bool, now time.Time) []GCOrphan
- func (sm *SessionManager) RunGCXTriggerLoop(ctx context.Context)
- func (sm *SessionManager) RunGitPullLoop(ctx context.Context)
- func (sm *SessionManager) RunMessageCleanupLoop(ctx context.Context)
- func (sm *SessionManager) RunOrchestratorReconcileLoop(ctx context.Context)
- func (sm *SessionManager) RunPRRefWatchLoop(ctx context.Context)
- func (sm *SessionManager) RunPRWatchLoop(ctx context.Context)
- func (sm *SessionManager) RunPurgeLoop(ctx context.Context)
- func (sm *SessionManager) RunResourceMonitorLoop(ctx context.Context)
- func (sm *SessionManager) RunScenarioCompletionLoop(ctx context.Context)
- func (sm *SessionManager) RunScenarioPolicyLoop(ctx context.Context)
- func (sm *SessionManager) RunStartupWatchdogLoop(ctx context.Context)
- func (sm *SessionManager) RunTodoSweepLoop(ctx context.Context)
- func (sm *SessionManager) RunTokenLoop(ctx context.Context)
- func (sm *SessionManager) RunTriggerLoop(ctx context.Context)
- func (sm *SessionManager) RunUpgradeCleanupLoop(ctx context.Context)
- func (sm *SessionManager) ScenarioStatus(name string) (*protocol.ScenarioRecord, error)
- func (sm *SessionManager) SendPushNotification(n pushNotification) (bool, string)
- func (sm *SessionManager) SessionForToken(token string) string
- func (sm *SessionManager) SetAttachedClient(sessionID string, conn net.Conn, kick func(), sendCtrl func(string, any))
- func (sm *SessionManager) SetMsgStore(ms *MsgStore)
- func (sm *SessionManager) SetSummary(sessionID, text string, ttlSeconds int) error
- func (sm *SessionManager) SetTodoStore(ts *TodoStore)
- func (sm *SessionManager) SoftDelete(id string) (SessionState, error)
- func (sm *SessionManager) SoftDeleteWithChildren(rootID string, excludeRoot bool) ([]string, error)
- func (sm *SessionManager) StartScenario(msg protocol.ScenarioStartMsg, rows, cols uint16) (*ScenarioState, error)
- func (sm *SessionManager) Stop(id string) error
- func (sm *SessionManager) StopAll(ctx context.Context)
- func (sm *SessionManager) StopScenario(name string) ([]string, error)
- func (sm *SessionManager) StopScenarioContext(ctx context.Context, name string) ([]string, error)
- func (sm *SessionManager) StopWithChildren(rootID string, excludeRoot bool) ([]string, error)
- func (sm *SessionManager) TodoAddOp(ac authContext, m protocol.TodoAddMsg) (protocol.TodoItemInfo, error)
- func (sm *SessionManager) TodoAssignOp(ac authContext, m protocol.TodoAssignMsg) (protocol.TodoItemInfo, error)
- func (sm *SessionManager) TodoClaimOp(ac authContext, m protocol.TodoClaimMsg) (protocol.TodoClaimResponse, error)
- func (sm *SessionManager) TodoExportOp(ac authContext, m protocol.TodoExportMsg) (string, error)
- func (sm *SessionManager) TodoListOp(ac authContext, m protocol.TodoListMsg) ([]protocol.TodoItemInfo, error)
- func (sm *SessionManager) TodoRemoveOp(ac authContext, m protocol.TodoRemoveMsg) error
- func (sm *SessionManager) TodoTransitionOp(ac authContext, m protocol.TodoTransitionMsg) (protocol.TodoItemInfo, error)
- func (sm *SessionManager) TodoUpdateOp(ac authContext, m protocol.TodoUpdateMsg) (protocol.TodoItemInfo, error)
- func (sm *SessionManager) TriggerList() []protocol.TriggerRecord
- func (sm *SessionManager) TriggerPause(name string, pause bool) error
- func (sm *SessionManager) TriggerRunNow(ctx context.Context, name string) error
- func (sm *SessionManager) TriggerStatus(name string) (protocol.TriggerRecord, error)
- func (sm *SessionManager) UnregisterDeviceConn(deviceID string, conn net.Conn)
- func (sm *SessionManager) Update(id string, name *string, parentID *string, starred *bool) (SessionState, error)
- func (sm *SessionManager) UpdateMetadata(id string, update SessionUpdate) (SessionState, error)
- type SessionState
- type SessionStatus
- type SessionUpdate
- type State
- type StateMigrationBackupError
- type StateVersionError
- type StreamInfo
- type TailnetIdentity
- type TodoAdd
- type TodoBatchAdd
- type TodoFilter
- type TodoItem
- type TodoStore
- func (s *TodoStore) Add(in TodoAdd) (TodoItem, error)
- func (s *TodoStore) AddBatch(entries []TodoBatchAdd) (map[string]TodoItem, error)
- func (s *TodoStore) Assign(id, assignee string) (TodoItem, error)
- func (s *TodoStore) AssigneeProgress(scope string) (map[string][2]int, error)
- func (s *TodoStore) Claim(id, owner string, override bool) (TodoItem, bool, error)
- func (s *TodoStore) ClaimNext(scope, owner string, override bool) (TodoItem, bool, error)
- func (s *TodoStore) Close() error
- func (s *TodoStore) Counts(scope string) (done, total int, err error)
- func (s *TodoStore) Get(id string) (TodoItem, error)
- func (s *TodoStore) List(scope string, f TodoFilter) ([]TodoItem, error)
- func (s *TodoStore) ListAll(f TodoFilter) ([]TodoItem, error)
- func (s *TodoStore) Remove(id string) error
- func (s *TodoStore) ReopenOwnedBy(ownerID string) (int, error)
- func (s *TodoStore) ReopenStale(lease time.Duration) (int, error)
- func (s *TodoStore) ScenarioCurrentSeedItemIDs(scope string) (map[string]string, error)
- func (s *TodoStore) ScenarioSeedItemIDs(scope string) (map[string]string, error)
- func (s *TodoStore) ScenarioSeedItems(scope string) (map[string]TodoItem, error)
- func (s *TodoStore) SetMaxNote(limit int)
- func (s *TodoStore) SetMaxTitle(limit int)
- func (s *TodoStore) SweepDone(maxAge time.Duration) (int, error)
- func (s *TodoStore) SweepDoneExceptScopes(maxAge time.Duration, protectedScopes []string) (int, error)
- func (s *TodoStore) Transition(id, newStatus, actor string, override bool) (TodoItem, error)
- func (s *TodoStore) TransitionCascade(id, newStatus, note, actor string, override bool) (TodoTransitionResult, error)
- func (s *TodoStore) UpdateFields(id string, title, note *string, tags *[]string, position *int64, ...) (TodoItem, error)
- func (s *TodoStore) UpdateFieldsCascade(id string, title, note *string, tags *[]string, position *int64, ...) (TodoUpdateResult, error)
- type TodoStoreSettings
- type TodoTransitionResult
- type TodoUpdateResult
- type TokenStats
- type TriggerRun
- type TriggerRuntimeState
- type UpgradeAdoptionResult
- type UpgradeCapacityProbe
- type UpgradeCleanupState
- type UpgradeConfigSource
- type UpgradeHelper
- type UpgradeManifest
- type UpgradePathDescriptor
- type UpgradeSession
- type UpgradeTargetDescriptor
- type WorktreePort
Constants ¶
const ( DriverPTY = "pty" DriverHeadless = "headless" )
Driver-kind identifiers persisted on SessionState.DriverKind (issue #1075).
const ( GCOrphanWorktree = "worktree" GCOrphanScratch = "scratch" )
GCOrphanType classifies where an orphan directory lives.
const ( StopReasonCrash = "crash" StopReasonIdle = "idle" StopReasonUser = "user" StopReasonShutdown = "shutdown" StopReasonWatchdog = "watchdog" // StopReasonScenarioTimeout attributes the stop half of an automatic // scenario retry to its durable member deadline. StopReasonScenarioTimeout = "scenario-timeout" // StopReasonDelete labels a daemon-initiated kill that is part of a // delete/purge teardown. It is used only for the "stopping session" audit // line (issue #1104); a deleted session is removed from state, so its exit // is ignored and never reaches the "session exited" log path. StopReasonDelete = "delete" // StopReasonConvert labels the headless process stop that // ConvertToInteractive performs before relaunching the session as an // interactive PTY (headless convert-on-attach, issue #1075/#1137). The stop // is caused by graith, not a crash, so it must not be attributed as one. StopReasonConvert = "convert" )
StopReason constants
const ( CompletionActionPending = "pending" CompletionActionRunning = "running" CompletionActionSucceeded = "succeeded" CompletionActionFailed = "failed" ScenarioCleanupPending = "pending" ScenarioCleanupScheduled = "scheduled" ScenarioCleanupRunning = "running" ScenarioCleanupSucceeded = "succeeded" ScenarioCleanupFailed = "failed" ScenarioCleanupCancelled = "cancelled" )
const ( TodoStatusTodo = "todo" TodoStatusInProgress = "in-progress" TodoStatusDone = "done" TodoStatusBlocked = "blocked" )
Item status values.
const CurrentStateVersion = 28
const OrchestratorSessionName = "orchestrator"
const SystemKindOrchestrator = "orchestrator"
Variables ¶
var ErrDaemonRunning = errors.New("daemon already running")
var ErrTodoNotFound = errors.New("todo not found")
ErrTodoNotFound is returned when a todo id does not exist.
Functions ¶
func AcquirePIDFile ¶
func ExecUpgrade ¶
func HandleConnection ¶
func HandleConnection(ctx context.Context, conn net.Conn, origin ConnOrigin, sm *SessionManager, log *slog.Logger)
HandleConnection processes the frame protocol for a single client connection. origin describes where the connection came from (local Unix socket vs remote tailnet listener) and carries the tailnet identity for remote connections; it is threaded to resolveAuth so authorization is origin-aware. The zero ConnOrigin{} is a local connection, preserving the existing trust model.
The control-message dispatch below is a thin router: most cases delegate to a handle* function grouped by concern in handler_lifecycle.go / handler_messaging.go / handler_scenario.go / handler_trigger.go / handler_todo.go / handler_query.go. Cases that mutate connection-local state (attach/detach/resize/handshake), block the read loop, or return from the loop (logs --follow, wait, msg_inbox/sub, upgrade, pair_request) stay inline here because they are coupled to this connection's lifecycle.
func IsSystemSession ¶ added in v0.42.0
func IsSystemSession(s *SessionState) bool
func IsUpgradeCapacityProbeMarker ¶ added in v0.70.0
func ListStateBackups ¶ added in v0.67.4
ListStateBackups returns the sorted paths of every pre-migration backup sitting next to statePath (files named "<base>.v<N>.bak"). It reads the directory rather than globbing so glob metacharacters in statePath can't break the match. Returns nil if the directory can't be read.
func ReleasePIDFile ¶
func ReleasePIDFile(path string)
func Run ¶
Run starts the daemon: acquires PID file, listens on the Unix socket, serves connections, and blocks until SIGTERM/SIGINT or an upgrade signal.
func RunAdoptBootstrap ¶ added in v0.70.0
func RunAdoptBootstrap(configFile, adoptFrom string, identity AdoptedServiceIdentity) error
RunAdoptBootstrap establishes post-exec ownership with an explicit service identity before config loading or path derivation. The hidden CLI adoption path bypasses Cobra's ordinary root pre-run and enters here directly so even a missing or invalid replacement config cannot strand transferred resources. Managed identity validation occurs only after the immutable capsule, ownership header, and manifest body have been bound, and before config loading or state mutation. Supplying either field makes both mandatory and fail-closed.
func StateBackupPath ¶ added in v0.67.4
StateBackupPath returns the pre-migration backup path for a state file at a given on-disk version. Backups sit next to the state file as "<state>.v<version>.bak" so a human recovering a downgrade can see which schema version a backup holds without opening it.
func StopDaemon ¶
func StopDaemonPID ¶ added in v0.70.0
StopDaemonPID stops one previously authenticated daemon peer identity. The caller obtains pid from Unix peer credentials, not from a mutable PID file.
func ValidateScenarioName ¶ added in v0.52.0
func ValidateSessionName ¶ added in v0.29.2
ValidateSessionName checks that a session name is safe for use in git branch names, shell commands, template expansion, and environment variables.
func WriteManifest ¶
func WriteManifest(dir string, m *UpgradeManifest) (string, error)
Types ¶
type AdoptedServiceIdentity ¶ added in v0.70.0
type AdoptedServiceIdentity struct {
// contains filtered or unexported fields
}
AdoptedServiceIdentity records whether an upgrade originated from the managed daemon service or an explicitly unmanaged source build. Its fields are private so callers cannot forge a managed identity or accidentally treat the zero value as unmanaged. Profile is deliberately absent: the only trusted profile comes from the capsule-bound manifest.
func NewManagedAdoptedServiceIdentity ¶ added in v0.70.0
func NewManagedAdoptedServiceIdentity(label, slot string) (AdoptedServiceIdentity, error)
NewManagedAdoptedServiceIdentity binds adoption to a staged service label and slot. Partial or empty service identity is never downgraded to unmanaged.
func NewUnmanagedAdoptedServiceIdentity ¶ added in v0.70.0
func NewUnmanagedAdoptedServiceIdentity() AdoptedServiceIdentity
NewUnmanagedAdoptedServiceIdentity explicitly selects source-build adoption.
type CIStatus ¶ added in v0.59.0
type CIStatus struct {
State string // passing | failing | pending | "" (unknown)
FailingChecks []string
// Passed and Total are the pass-like and total check counts, letting the
// overlay/`gr ls` show progress ("16/22") while CI runs. Total == 0 means no
// count is available.
Passed int
Total int
}
CIStatus is the runtime-only aggregate CI status for a session's linked PR.
type ConnOrigin ¶ added in v0.66.3
type ConnOrigin struct {
// Remote is false for the local Unix socket, true for a tailnet listener.
Remote bool
// Identity is the WhoIs result for remote connections; nil for local.
Identity *TailnetIdentity
// RemoteGeneration identifies the listener generation that accepted this
// connection. Production remote connections must match the daemon's active
// generation on every frame. Zero is reserved for injected handler tests and
// embedders that do not own a remote runtime controller.
RemoteGeneration uint64
// RemoteTLSPin is the SPKI pin of the TLS listener that accepted this
// connection. Proof-of-possession binds to this immutable per-connection
// value so a concurrent listener replacement cannot mix TLS generations.
RemoteTLSPin string
}
ConnOrigin describes where a connection came from. It is threaded into HandleConnection so authorization can distinguish the local Unix socket (the 0700 trust boundary) from a remote tailnet connection, and recover the tailnet identity for the latter.
The zero value (Remote: false, Identity: nil) is a local Unix-socket connection — the existing trust model — so existing callers that pass ConnOrigin{} keep today's behaviour.
type CreateOpts ¶ added in v0.67.0
type CreateOpts struct {
// ID, when non-empty, is the session ID to use instead of generating a
// fresh one. It must match the generated ID format (8 lowercase hex chars)
// and not collide with an existing session — Create validates both and
// fails closed otherwise. Callers that must know the ID before Create
// returns (e.g. scenario reservation, where a placeholder ID would
// otherwise differ from the final session ID) supply it here. When empty,
// Create generates the ID as before.
ID string
Name string
Labels []string
AgentName string
RepoPath string
BaseBranch string
Prompt string
Model string
// Codex carries typed per-session Codex CLI options (issue #1186). Ignored
// (and rejected if non-zero) for non-codex agents.
Codex config.CodexOptions
ParentID string
NoRepo bool
Mirror string
// MirrorSourceID is the internal exact-ID mirror contract. Unlike Mirror,
// it never treats the value as a session name. Scenario startup uses it
// after resolving and reserving an authoritative source identity.
MirrorSourceID string
AgentHooks bool
InPlace bool
AllowConcurrent bool
SkipModelValidation bool
// Headless requests a headless stream-json session instead of an
// interactive PTY (issue #1075). Honoured only when the agent is
// headless_capable and [headless] experimental is enabled; otherwise Create
// fails closed rather than silently downgrading. See resolveDriverKind.
Headless bool
// ForcePTY disables the soft global headless default for lifecycle owners
// that require resumability, such as bounded scenario retries. It is an
// internal option and must not be combined with Headless.
ForcePTY bool
// NoFetch skips the `git fetch origin` that normally runs before the
// worktree is created (issue #1012), so a session can be created from local
// repo state when SSH auth is unavailable (Secretive/biometric, offline).
// It overrides fetch_on_create for this one creation only.
NoFetch bool
Rows uint16
Cols uint16
EnvExtra []map[string]string
// TriggerID / TriggerReactor tag a session spawned by a trigger, applied in
// the same durable reservation as creation so reactor ownership survives a
// crash between Create and a separate tag-and-save.
TriggerID string
TriggerReactor bool
TriggerFingerprint string
// TrackerIssue tags a session spawned by a tracker action with its issue key
// (see SessionState.TrackerIssue), applied in the same durable reservation as
// creation so the reconcile dedup key survives a crash between Create and a
// separate tag-and-save.
TrackerIssue string
// Completion* tags a session spawned by a scenario completion action so a
// daemon restart can adopt it without making it an owned scenario member.
CompletionScenarioID string
CompletionEpoch int
CompletionAction string
CompletionAttempt int
// AutoCleanup marks a trigger-spawned session for soft-deletion when it
// stops (config.CleanupAlways / config.CleanupOnSuccess; empty disables).
AutoCleanup string
// IdleTimeoutSecs overrides the agent-default idle-stop window for this
// session (seconds; 0 = agent default).
IdleTimeoutSecs int
// Includes attaches extra worktrees to the session in addition to any
// configured on the repo's [[repos]] entry. Merged with (and deduplicated
// against) the repo config includes. Used by scenarios (issue #1046).
Includes []string
// Starred creates the session already starred, protecting it from an
// accidental manual `gr delete`. Used by scenarios (issue #1046).
Starred bool
}
CreateOpts holds the parameters for SessionManager.Create. Using a struct keeps call sites self-documenting and lets new options default to their zero value without breaking existing callers.
type CreationConfig ¶ added in v0.27.0
type CreationConfig struct {
Agent config.Agent `json:"agent"`
SandboxConfig config.SandboxConfig `json:"sandbox_config"`
// contains filtered or unexported fields
}
CreationConfig captures the agent and sandbox configuration at session creation time so the overlay can detect when the live config has diverged.
func (*CreationConfig) UnmarshalJSON ¶ added in v0.70.0
func (c *CreationConfig) UnmarshalJSON(data []byte) error
UnmarshalJSON recognizes the removed command_policy creation snapshot only long enough for the state migration to establish a clean process boundary. The removed field is never written by this binary.
type GCOrphan ¶ added in v0.66.16
type GCOrphan struct {
Type string `json:"type"`
Path string `json:"path"`
ID string `json:"id"`
IsGitWorktree bool `json:"is_git_worktree,omitempty"`
HasDirtyFiles bool `json:"has_dirty_files,omitempty"`
Removed bool `json:"removed,omitempty"`
Skipped bool `json:"skipped,omitempty"`
Reason string `json:"reason,omitempty"`
// contains filtered or unexported fields
}
GCOrphan describes a directory under the data dir that has no matching session. When RunGC runs with force=true, Removed/Skipped/Reason record the outcome of the cleanup attempt.
type IncludedRepoState ¶ added in v0.19.0
type JailedComment ¶ added in v0.67.6
type JailedComment struct {
ID string `json:"id"`
CommentID int64 `json:"comment_id"`
Surface string `json:"surface"` // "inline review" | "conversation"
PRNumber int `json:"pr_number"`
RepoSlug string `json:"repo_slug,omitempty"`
Branch string `json:"branch,omitempty"`
Author string `json:"author"`
Association string `json:"association,omitempty"`
IsBot bool `json:"is_bot,omitempty"`
Path string `json:"path,omitempty"`
Line int `json:"line,omitempty"`
Body string `json:"body"`
TargetSession string `json:"target_session"`
TargetName string `json:"target_name,omitempty"`
JailedAt string `json:"jailed_at"`
ReleasedAt string `json:"released_at,omitempty"`
}
JailedComment is a PR comment that pr_watch blocked as untrusted and quarantined instead of discarding (issue #1082). It carries enough metadata for the human/orchestrator to inspect the comment and decide whether to release it (deliver it to the target session) or leave it jailed.
func (JailedComment) Released ¶ added in v0.67.6
func (j JailedComment) Released() bool
Released reports whether this jailed comment has already been released.
type Message ¶
type Message struct {
ID string `json:"id"`
Seq int64 `json:"seq"`
Stream string `json:"stream"`
SenderID string `json:"sender_id"`
SenderName string `json:"sender_name,omitempty"`
Body string `json:"body"`
ThreadID string `json:"thread_id,omitempty"`
ReplyTo string `json:"reply_to,omitempty"`
NoReply bool `json:"no_reply,omitempty"`
CreatedAt string `json:"created_at"`
// System marks a daemon-authored automated notification (PR/CI notices,
// etc.) as distinct from an LLM/session/human message. It is derived from
// the sender ID rather than stored, so it is set when messages are read or
// published, not persisted as a column. See issue #887.
System bool `json:"system,omitempty"`
}
type MigrationInfo ¶ added in v0.58.0
type MigrationInfo struct {
Agent string `json:"agent"`
Model string `json:"model,omitempty"`
AgentSessionID string `json:"agent_session_id,omitempty"`
RenderedPath string `json:"rendered_path,omitempty"`
At time.Time `json:"at"`
}
MigrationInfo records the agent a session's conversation came from. For an in-place migration it enables reverting a failed migrate and migrating back later. It is also set on a CROSS-AGENT FORK (which has a live ParentID), where it records provenance and — via RenderedPath — owns the staged context file so it is cleaned up on delete. Distinguish the two by ParentID.
type MsgStore ¶
type MsgStore struct {
// contains filtered or unexported fields
}
func NewMsgStore ¶
func NewMsgStore(dbPath string, settings ...MsgStoreSettings) (*MsgStore, error)
NewMsgStore opens (creating if needed) the message database at dbPath. An optional MsgStoreSettings tunes the SQLite busy timeout, the per-subscriber channel buffer, and the jail listing cap; omit it (or pass a zero value) to use the built-in defaults. Only the first settings value is used.
func (*MsgStore) AckMessages ¶ added in v0.16.5
func (*MsgStore) Conversation ¶ added in v0.59.0
Conversation returns every direct message involving `self`, both directions: messages delivered to self's inbox (stream = "inbox:"+self) and messages self sent to any peer's inbox (sender_id = self AND an inbox: stream other than self's own). Topic messages are excluded — a "conversation" is direct messages only. Results are ordered by created_at, with id as a deterministic tie-breaker (seq is per-stream, so it is not a usable cross-stream order key).
When limit > 0, the most recent `limit` messages are returned (still in ascending order). The query reads inbox streams the caller may not own; the daemon authorises the target via checkTarget before calling this, and the sender_id filter ensures the outbound branch only returns messages the target session actually authored.
func (*MsgStore) GetJailed ¶ added in v0.67.6
func (s *MsgStore) GetJailed(id string) (JailedComment, bool, error)
GetJailed returns a single quarantined comment by jail ID. Reads don't take the mutex here (mirrors ListJailed), so it shares getJailedLocked's body.
func (*MsgStore) Jail ¶ added in v0.67.6
func (s *MsgStore) Jail(j JailedComment) (id string, created bool, err error)
Jail quarantines a blocked PR comment. It assigns and returns the generated jail ID and is idempotent on (comment_id, surface, target_session): a repeat of the same comment leaves the existing row untouched and returns its existing ID with created=false.
func (*MsgStore) ListJailed ¶ added in v0.67.6
func (s *MsgStore) ListJailed(includeReleased bool) ([]JailedComment, error)
ListJailed returns quarantined comments, newest first, capped at the configured jail list limit (default 2000) so a long-running daemon with retention disabled can't be made to serialize an unbounded result set (mirrors the msg_conversation clamp; newest-first, so the cap drops the oldest). When includeReleased is false, already-released entries are excluded.
func (*MsgStore) ListStreams ¶
func (s *MsgStore) ListStreams(subscriber string, includeSystem bool) ([]StreamInfo, error)
func (*MsgStore) MarkReleased ¶ added in v0.67.6
func (s *MsgStore) MarkReleased(id string) (JailedComment, bool, error)
MarkReleased stamps a jailed comment as released. It returns ok=false if the entry does not exist or was already released (so a double-release can't re-deliver the same comment). The returned entry is the pre-release snapshot, used by the caller to build the delivery.
func (*MsgStore) SetJailListLimit ¶ added in v0.69.1
SetJailListLimit updates the jail listing cap live on config reload (issue #1291) without reopening the database. A non-positive value resolves to the default, mirroring MsgStoreSettings.resolved so a reload matches open-time semantics; a value above the ceiling is already rejected at config load, but is clamped to the default here too so a direct caller can't exceed the cap. Safe to call concurrently with ListJailed (the field is atomic).
func (*MsgStore) TotalUnread ¶ added in v0.3.0
func (*MsgStore) Unrelease ¶ added in v0.67.6
Unrelease reverts a release stamp back to unreleased. Used to un-claim a release whose delivery failed, so it stays retryable rather than stuck released-but-undelivered. Returns ok=true if a row was actually reverted.
func (*MsgStore) UnreleasedJailed ¶ added in v0.67.6
func (s *MsgStore) UnreleasedJailed() ([]JailedComment, error)
UnreleasedJailed returns all not-yet-released quarantined comments. Used by auto-release to re-evaluate trust against a freshly-reloaded config.
type MsgStoreSettings ¶ added in v0.69.1
MsgStoreSettings carries the config-derived operational limits for the message store. A zero value resolves each field to its built-in default, so tests and other callers that don't tune these can pass MsgStoreSettings{} (or nothing).
type PRStatus ¶ added in v0.59.0
type PRStatus struct {
Number int
State string // open | draft | merged | closed
URL string
ReviewDecision string
HeadRefOid string // head commit SHA — keys the per-SHA notify cap
Mergeable string // MERGEABLE | CONFLICTING | UNKNOWN
}
PRStatus is the runtime-only linked-PR state for a session, derived by the PR-watch loop. A zero Number means "no PR resolved". The PR-watch loop always assigns a freshly-built value (never mutates in place), so reads from cloned SessionState off-lock are race-free.
type PairedDevice ¶ added in v0.66.3
type PairedDevice struct {
ID string `json:"id"`
Label string `json:"label"`
PubKey string `json:"pub_key"`
TailnetUser string `json:"tailnet_user"`
TailnetNode string `json:"tailnet_node"`
TokenHash string `json:"token_hash"`
// ReadOnly marks a device paired while require_pairing=false (the unsafe,
// WhoIs-only mode): it maps to roleRemoteGuest and gets a read-only subset.
ReadOnly bool `json:"read_only,omitempty"`
CreatedAt time.Time `json:"created_at"`
LastSeenAt time.Time `json:"last_seen_at,omitempty"`
}
PairedDevice is a remote client device authorized via pairing (design §B.2). It is bound to the tailnet identity observed at pairing time; TokenHash is an HMAC of the client token, never the token itself.
type PublishOpts ¶ added in v0.67.2
type PublishOpts struct {
// Stream is the target stream (topic, inbox:<id>, or system stream).
Stream string
// SenderID is the sender's session ID (or a system sender ID).
SenderID string
// SenderName is the sender's human-readable name.
SenderName string
// Body is the message body.
Body string
// ThreadID groups the message into a conversation thread (optional).
ThreadID string
// ReplyTo is the stream this message replies to (optional).
ReplyTo string
// NoReply declares that the sender does not expect a reply.
NoReply bool
}
PublishOpts describes a message to publish to a stream. It replaces the six consecutive positional string parameters of Publish — same-typed positional strings are the highest-risk transposition case, and the trailing ThreadID / ReplyTo are frequently empty, so a struct with named fields is both safer and less noisy at the call site.
type RemoteListener ¶ added in v0.66.3
type RemoteListener interface {
// Listen begins listening and returns the raw net.Listener (TLS is layered
// on by the caller).
Listen() (net.Listener, error)
// WhoIs resolves the tailnet identity behind remoteAddr.
WhoIs(ctx context.Context, remoteAddr string) (*TailnetIdentity, error)
// Close releases the listener's resources.
Close() error
}
RemoteListener is a tailnet-facing listener plus a way to resolve the tailnet identity behind an accepted connection (Gate 1). Two implementations back the two config modes: tsnet (embedded node) and interface (host tailscaled).
type ResourceSample ¶ added in v0.68.9
type ResourceSample struct {
At time.Time `json:"at"`
RSSMB int64 `json:"rss_mb"`
CPUPercent float64 `json:"cpu_percent"`
OpenFDs int `json:"open_fds"`
FDsPartial bool `json:"fds_partial,omitempty"`
ProcessCount int `json:"process_count"`
TopProcess string `json:"top_process,omitempty"`
ProcessIDs []int `json:"-"`
}
ResourceSample is a process-group aggregate. A sandboxed session's direct child is only the wrapper, so observing the whole group is essential: this captures the agent and every tool it spawned rather than the wrapper's RSS.
type ScenarioCleanupState ¶ added in v0.69.2
type ScenarioCompletionActionState ¶ added in v0.69.2
type ScenarioCompletionActionState struct {
Name string `json:"name"`
State string `json:"state"`
Attempt int `json:"attempt,omitempty"`
StartedAt *time.Time `json:"started_at,omitempty"`
FinishedAt *time.Time `json:"finished_at,omitempty"`
Result string `json:"result,omitempty"`
Error string `json:"error,omitempty"`
SessionID string `json:"session_id,omitempty"`
}
type ScenarioCompletionState ¶ added in v0.69.2
type ScenarioCompletionState struct {
Complete bool `json:"complete,omitempty"`
Epoch int `json:"epoch,omitempty"`
TransitionedAt *time.Time `json:"transitioned_at,omitempty"`
Actions []ScenarioCompletionActionState `json:"actions,omitempty"`
Cleanup *ScenarioCleanupState `json:"cleanup,omitempty"`
}
ScenarioCompletionState is the durable current completion epoch. Complete is the last authoritative todo-derived value observed by the reconciler.
type ScenarioMemberPolicyState ¶ added in v0.69.2
type ScenarioMemberPolicyState struct {
Required bool `json:"required"`
TimeoutNanos int64 `json:"timeout_nanos,omitempty"`
Retries int `json:"retries,omitempty"`
Attempt int `json:"attempt,omitempty"`
AttemptStartedAt *time.Time `json:"attempt_started_at,omitempty"`
Deadline *time.Time `json:"deadline,omitempty"`
RetryPending bool `json:"retry_pending,omitempty"`
RetryDispatched bool `json:"retry_dispatched,omitempty"`
RetryFromGeneration uint64 `json:"retry_from_generation,omitempty"`
SucceededAt *time.Time `json:"succeeded_at,omitempty"`
ExhaustedAt *time.Time `json:"exhausted_at,omitempty"`
ExhaustionReason string `json:"exhaustion_reason,omitempty"`
}
type ScenarioPolicyState ¶ added in v0.69.2
type ScenarioPolicyState struct {
Completion string `json:"completion"`
Quorum int `json:"quorum,omitempty"`
OnExhausted string `json:"on_exhausted"`
Active bool `json:"active"`
Paused bool `json:"paused,omitempty"`
Outcome string `json:"outcome,omitempty"`
OutcomeReason string `json:"outcome_reason,omitempty"`
OutcomeAt *time.Time `json:"outcome_at,omitempty"`
}
type ScenarioRenderIdentityState ¶ added in v0.69.5
type ScenarioRenderMemberState ¶ added in v0.69.5
type ScenarioRenderReferenceState ¶ added in v0.69.5
type ScenarioRenderState ¶ added in v0.69.5
type ScenarioRenderState struct {
AuthoredName string `json:"authored_name"`
ScenarioID string `json:"scenario_id"`
ShortID string `json:"short_id"`
RenderedAt time.Time `json:"rendered_at"`
Caller ScenarioRenderIdentityState `json:"caller"`
Parent ScenarioRenderIdentityState `json:"parent"`
Initiator ScenarioRenderIdentityState `json:"initiator"`
Members []ScenarioRenderMemberState `json:"members"`
References []ScenarioRenderReferenceState `json:"references,omitempty"`
}
ScenarioRenderState persists the one immutable context used to render an authored scenario definition. ScenarioState.Name/Sessions/Triggers contain the rendered runtime graph; this state explains how those names were derived and is never evaluated again after start.
type ScenarioResultPublication ¶ added in v0.70.0
type ScenarioResultPublication struct {
Scenario string
Member string
Result ScenarioResultState
}
ScenarioResultPublication is the application-level result of publishing a result. Its time value remains a time.Time until the wire adapter formats it.
type ScenarioResultPublishRequest ¶ added in v0.70.0
ScenarioResultPublishRequest is the application-level request to publish a result. Wire envelopes are translated to this value by the handler adapter.
type ScenarioResultState ¶ added in v0.69.2
type ScenarioResultState struct {
Name string `json:"name"`
Format string `json:"format"`
StoreTemplate string `json:"store_template"`
Destination string `json:"destination"`
Required bool `json:"required,omitempty"`
Status ScenarioResultStatus `json:"status"`
SizeBytes int `json:"size_bytes,omitempty"`
PublishedAt time.Time `json:"published_at,omitempty"`
Error string `json:"error,omitempty"`
}
ScenarioResultState is the durable declaration and publication metadata for one member result. Content stays in the shared document store.
type ScenarioResultStatus ¶ added in v0.69.2
type ScenarioResultStatus string
const ( ScenarioResultPending ScenarioResultStatus = "pending" ScenarioResultAvailable ScenarioResultStatus = "available" ScenarioResultInvalid ScenarioResultStatus = "invalid" ScenarioResultFailed ScenarioResultStatus = "failed" )
type ScenarioSession ¶ added in v0.52.0
type ScenarioSession struct {
Name string `json:"name"`
Mirror string `json:"mirror,omitempty"`
Role string `json:"role"`
Prompt string `json:"prompt,omitempty"`
Task string `json:"task"`
Repo string `json:"repo"`
Agent string `json:"agent"`
Model string `json:"model,omitempty"`
Results []ScenarioResultState `json:"results,omitempty"`
Policy *ScenarioMemberPolicyState `json:"policy,omitempty"`
}
type ScenarioState ¶ added in v0.52.0
type ScenarioState struct {
ID string `json:"id"`
Name string `json:"name"`
OrchestratorID string `json:"orchestrator_id"`
Goal string `json:"goal"`
SessionIDs []string `json:"session_ids"`
Sessions []ScenarioSession `json:"sessions"`
CreatedAt time.Time `json:"created_at"`
SourceFileHash string `json:"source_file_hash,omitempty"`
// Triggers are the scenario-embedded [[trigger]] blocks (issue #1027). They
// are set only once the two-phase start succeeds, so a rolled-back scenario
// never activates them. SessionManager.allTriggers enumerates namespaced
// schedule/watch definitions while a member runs and completion definitions
// while the record exists. Persistence lets them survive a daemon restart
// without re-reading the TOML.
Triggers []config.TriggerConfig `json:"triggers,omitempty"`
Lifecycle config.ScenarioLifecycleConfig `json:"lifecycle,omitempty"`
Completion ScenarioCompletionState `json:"completion,omitempty"`
Policy *ScenarioPolicyState `json:"policy,omitempty"`
Render *ScenarioRenderState `json:"render,omitempty"`
}
type SessionDriver ¶ added in v0.67.8
type SessionDriver interface {
// contains filtered or unexported methods
}
SessionDriver is the temporary compatibility contract for call sites that have not yet migrated to capability-specific interfaces. New consumers should depend on sessionDriver, sessionOutput, or interactiveDriver instead. Keeping this seam for one migration slice lets PTY and headless call sites be converted independently without changing runtime behavior.
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager orchestrates PTY sessions, state persistence, and git worktrees.
func NewSessionManager ¶
NewSessionManager creates a SessionManager with the given config and paths.
func (*SessionManager) AddPendingPairing ¶ added in v0.66.3
func (sm *SessionManager) AddPendingPairing(label, pubKey string, id TailnetIdentity, now time.Time) (string, chan pairApproval, time.Time, error)
AddPendingPairing records a device pairing request, subject to a per-daemon rate limit and a cap on outstanding requests. now is passed for deterministic testing. It does not persist state — pending pairings are in-memory only. The returned channel is the waiter for this request: it is registered under the same lock that creates the pending entry, so an approval can never race ahead of the waiter and drop the delivery. The caller reads it (with its own timeout / disconnect handling) and must cancelPendingPairing when done. The returned deadline is the request's immutable expiry: the caller must time its waiter out against this exact value (not the live TTL) so the waiter, cleanup, and approval never disagree about when the request expires (#1299).
func (*SessionManager) AddToScenario ¶ added in v0.52.0
func (sm *SessionManager) AddToScenario(name string, input protocol.ScenarioSessionInput, rows, cols uint16) (*SessionState, error)
func (*SessionManager) AdoptSessions ¶
func (sm *SessionManager) AdoptSessions(manifest *UpgradeManifest) (UpgradeAdoptionResult, error)
func (*SessionManager) ApprovePairing ¶ added in v0.66.3
func (sm *SessionManager) ApprovePairing(requestID string, readOnly bool, now time.Time) (deviceID, clientToken string, err error)
ApprovePairing approves a pending pairing, minting and persisting a new paired device. readOnly marks a device paired while require_pairing=false (maps to roleRemoteGuest). It returns the device ID and the one-time client token (only returned here; only its HMAC is stored). now is passed for testability.
func (*SessionManager) ClearAttachedClient ¶
func (sm *SessionManager) ClearAttachedClient(sessionID string, conn net.Conn)
func (*SessionManager) ClearSummary ¶ added in v0.32.0
func (sm *SessionManager) ClearSummary(sessionID string) error
func (*SessionManager) Config ¶ added in v0.47.0
func (sm *SessionManager) Config() *config.Config
Config returns a snapshot of the current config pointer, safe for use outside the lock. The returned *Config must not be modified.
func (*SessionManager) ConvertToInteractive ¶ added in v0.68.7
func (sm *SessionManager) ConvertToInteractive(id string, rows, cols uint16) (SessionState, error)
ConvertToInteractive turns a headless (one-shot stream-json) session into an interactive PTY session, preserving its conversation (Claude reloads it from the transcript on `--resume`), worktree, branch, graith session id, and env. This backs `gr attach` on a headless session (headless phase 5, issue #1137): a headless session has no ptmx to stream, so attach converts instead.
The swap is transactional. Under the manager lock it validates the target and marks it StatusCreating (a busy guard that locks out a concurrent attach/stop/resume/convert) and removes the live driver from the sessions map so its exit watcher goes stale and can't race the relaunch. It then stops the headless process outside the lock (interrupt → settle → SIGTERM → SIGKILL fallback), flips the persisted DriverKind to "pty", and relaunches through the ordinary resume path — which already knows how to spawn `claude --resume <agent_session_id>` in a real PTY. If the relaunch fails, the session is left stopped-and-interactive (resumable), not wedged.
A headless session that has already exited (StatusStopped/Errored) is converted the same way, minus the process stop: DriverKind flips and the resume path relaunches it interactively. Converting an already-interactive session is a no-op that returns the current state.
func (*SessionManager) Create ¶
func (sm *SessionManager) Create(opts CreateOpts) (SessionState, error)
Create starts a new agent session, either in a git worktree, in-place in an existing repo, or as a standalone scratch session (when noRepo is true).
The method uses three-phase locking to avoid holding the daemon mutex during potentially blocking git/network operations (fetch, GitHub API calls, PTY spawn):
- Lock: validate, reserve session as StatusCreating, unlock
- Git setup and PTY spawn (no lock held)
- Lock: commit to StatusRunning, unlock
func (*SessionManager) Delete ¶
func (sm *SessionManager) Delete(id string) error
Delete stops a session, removes its worktree/branch, and deletes state. Git teardown is attempted before removing the session from state; if teardown fails the session is kept for retry and the error is returned.
func (*SessionManager) DeleteScenario ¶ added in v0.52.0
func (sm *SessionManager) DeleteScenario(name string) ([]string, error)
func (*SessionManager) DeleteScenarioContext ¶ added in v0.69.2
func (*SessionManager) DeleteWithChildren ¶ added in v0.20.0
func (sm *SessionManager) DeleteWithChildren(id string, excludeRoot bool) ([]string, error)
DeleteWithChildren deletes a session and all its transitive descendants. Git teardown is attempted before removing each session from state; sessions whose teardown fails are kept for retry. Returns the list of deleted session IDs and an error if any teardowns failed.
func (*SessionManager) DeviceForToken ¶ added in v0.66.3
func (sm *SessionManager) DeviceForToken(token string) *PairedDevice
DeviceForToken resolves a client token to its paired device, or nil. Must be called under at least RLock.
func (*SessionManager) Diagnostics ¶ added in v0.28.0
func (sm *SessionManager) Diagnostics() protocol.DiagnosticsMsg
Diagnostics collects runtime health data for gr doctor.
func (*SessionManager) EnsureHumanToken ¶ added in v0.67.1
func (sm *SessionManager) EnsureHumanToken() error
EnsureHumanToken loads or creates the local human credential. It is exported for tests and embedders that construct a SessionManager without going through Run (which calls loadOrCreateHumanToken during startup).
func (*SessionManager) FindOrphans ¶ added in v0.66.16
func (sm *SessionManager) FindOrphans(now time.Time) []GCOrphan
FindOrphans scans the data dir for worktree and scratch directories with no matching session that are older than the configured orphan minimum age. It reads state under the lock to build the known-session set, then walks the filesystem lock-free.
func (*SessionManager) Fork ¶ added in v0.10.0
func (sm *SessionManager) Fork(name, sourceSessionID string, rows, cols uint16) (SessionState, error)
Fork creates a new session/worktree that natively continues the source agent's conversation (same agent type), using the agent's fork_args to carry over the history. It is a thin wrapper over ForkWithAgent with no override.
func (*SessionManager) ForkWithAgent ¶ added in v0.68.3
func (sm *SessionManager) ForkWithAgent(name, sourceSessionID, targetAgent, targetModel string, rows, cols uint16) (SessionState, error)
ForkWithAgent forks a session into a new worktree. When targetAgent is empty or equal to the source's agent, this is a native same-agent fork (the source agent's conversation is resumed via fork_args). When targetAgent differs, it is a CROSS-AGENT fork: the source's on-disk conversation is rendered to a neutral Markdown file and the new agent is seeded with it (reusing the migration reader/renderer), while the source session keeps running.
Git state: like any fork, the new worktree branches from the base branch, so the source's uncommitted edits are dropped. For a cross-agent fork the seed prompt says so explicitly (BuildForkSeedPrompt).
Uses three-phase locking like Create to avoid holding the mutex during git fetch and PTY spawn.
See docs/design/2026-06-24-cross-agent-conversation-migration-design.md ("Future: cross-agent fork").
func (*SessionManager) Get ¶
func (sm *SessionManager) Get(id string) (SessionState, bool)
Get returns a copy of a session state by ID.
func (*SessionManager) GetPTY ¶
func (sm *SessionManager) GetPTY(id string) (sessionDriver, bool)
GetPTY returns the live session driver by ID. Named for its historic PTY-only past; today it may return any SessionDriver implementation.
func (*SessionManager) HandleHookReport ¶ added in v0.11.0
func (sm *SessionManager) HandleHookReport(sr protocol.StatusReportMsg)
HandleHookReport processes a status report from an agent hook, updating the in-memory hookReports map and the session's AgentStatus. This is the authoritative source of agent status when hooks are active.
func (*SessionManager) HasAttachedClient ¶ added in v0.52.0
func (sm *SessionManager) HasAttachedClient(sessionID string) bool
func (*SessionManager) InstanceID ¶ added in v0.69.1
func (sm *SessionManager) InstanceID() string
InstanceID returns this daemon process's boot nonce (see the instanceID field).
func (*SessionManager) InterruptSession ¶ added in v0.66.2
func (sm *SessionManager) InterruptSession(sessionID string) error
InterruptSession delivers an interrupt (Ctrl-C) to a session's live PTY using the agent's configured interrupt count and delay. Different agent CLIs need different sequences — e.g. Claude's TUI ignores a single Ctrl-C and needs two rapid presses — so delivery is agent-aware rather than a single 0x03 (issue #620). Returns an error if the session has no live PTY.
func (*SessionManager) IsAttachedClient ¶ added in v0.16.5
func (sm *SessionManager) IsAttachedClient(sessionID string, conn net.Conn) bool
func (*SessionManager) KickAttachedClient ¶
func (sm *SessionManager) KickAttachedClient(sessionID string)
func (*SessionManager) List ¶
func (sm *SessionManager) List() []SessionState
List returns copies of all known session states.
func (*SessionManager) ListPairings ¶ added in v0.66.3
func (sm *SessionManager) ListPairings() ([]pendingPairing, []PairedDevice)
ListPairings returns snapshots of the pending pairing requests and the persisted paired devices. Must be called without holding sm.mu.
func (*SessionManager) ListScenarios ¶ added in v0.52.0
func (sm *SessionManager) ListScenarios() []protocol.ScenarioRecord
func (*SessionManager) LoadState ¶
func (sm *SessionManager) LoadState() error
LoadState reads persisted state from disk and reconciles dead processes.
func (*SessionManager) Migrate ¶ added in v0.58.0
func (sm *SessionManager) Migrate(id, targetAgent, targetModel string, rows, cols uint16) (SessionState, error)
Migrate swaps the agent on an existing session in place: it renders the current agent's conversation to a neutral Markdown file, stops the current agent, changes the session's agent type, and restarts it in the *same* worktree seeded with that file. The session keeps its id, name, worktree and branch — only the agent type changes — so all code state (commits and uncommitted edits) carries over with no branching.
Ordering is chosen so a doomed migration aborts before the running agent is touched (read+render happen first and fail fast), and so the context file exists before the new agent starts. If the target agent fails to start, the original agent is restored.
See docs/design/2026-06-24-cross-agent-conversation-migration-design.md.
func (*SessionManager) PrepareUpgrade ¶
func (sm *SessionManager) PrepareUpgrade(listenerFd uintptr, configFile string) (*UpgradeManifest, error)
func (*SessionManager) PublishScenarioResult ¶ added in v0.69.2
func (sm *SessionManager) PublishScenarioResult(auth authContext, request ScenarioResultPublishRequest) (ScenarioResultPublication, error)
PublishScenarioResult validates and stores one authenticated member result. Store I/O runs without sm.mu; scenarioResultMu serializes the write+metadata commit pair so concurrent attempts cannot leave mismatched content/status.
func (*SessionManager) RegisterDeviceConn ¶ added in v0.66.3
func (sm *SessionManager) RegisterDeviceConn(deviceID string, conn net.Conn)
RegisterDeviceConn records a live connection for a device so revocation can force-close it. Called once per connection after successful authentication.
func (*SessionManager) ReleaseJailed ¶ added in v0.67.6
func (sm *SessionManager) ReleaseJailed(id string) (JailedComment, error)
ReleaseJailed releases a single jailed comment by ID: marks it released and delivers its content to the target session's inbox (auto-resuming a stopped agent). It returns the released entry. Authorization (human/orchestrator only) is enforced by the caller — this is the mechanism, not the gate.
func (*SessionManager) ReleaseJailedByAuthor ¶ added in v0.67.6
func (sm *SessionManager) ReleaseJailedByAuthor(login string) ([]JailedComment, error)
ReleaseJailedByAuthor releases every not-yet-released jailed comment whose author login matches (case-insensitive). Used by `gr msg jail release --all --author <login>` after a newly-trusted author is allowlisted. It is best-effort per comment: a failure on one (claim or delivery) is logged and that comment is left jailed (un-claimed) for retry, but the loop continues, so the returned slice reflects exactly what was delivered — a mid-batch error never hides the comments that did go out. It returns an error only when the initial listing fails (nothing could be attempted).
func (*SessionManager) ReloadConfig ¶ added in v0.3.0
func (sm *SessionManager) ReloadConfig() error
ReloadConfig loads the config from disk and swaps it in, logging what changed.
func (*SessionManager) RemoteTLSPin ¶ added in v0.69.2
func (sm *SessionManager) RemoteTLSPin() string
RemoteTLSPin returns the active remote generation's SPKI pin.
func (*SessionManager) Restart ¶ added in v0.26.0
func (sm *SessionManager) Restart(id string, rows, cols uint16) (SessionState, error)
Restart stops a running session (or no-ops if already stopped) and resumes it, picking up the current agent and sandbox configuration. A plain user restart attributes the teardown to StopReasonUser; internal callers use restartWithReason to preserve the true subsystem (e.g. the startup watchdog).
func (*SessionManager) RestartWithChildren ¶ added in v0.53.0
func (*SessionManager) Restore ¶ added in v0.66.16
func (sm *SessionManager) Restore(id string) (SessionState, error)
Restore un-deletes a soft-deleted session, clearing its deletion marker and leaving it in the stopped state so it can be resumed. Returns an error if the session does not exist, is not soft-deleted, or its recovery window has already elapsed (in which case it is scheduled for purge and must not be resurrected past its advertised deadline).
func (*SessionManager) RestoreWithChildren ¶ added in v0.66.16
func (sm *SessionManager) RestoreWithChildren(rootID string) ([]SessionState, error)
RestoreWithChildren restores a soft-deleted session and every soft-deleted descendant, bringing a subtree hidden by a `--children` delete back at once. Non-deleted or expired descendants are skipped. Returns the restored IDs.
func (*SessionManager) Resume ¶
func (sm *SessionManager) Resume(id string, rows, cols uint16) (SessionState, error)
Resume restarts a stopped session using the agent's resume_args.
Uses two-phase locking: the GitHub username discovery happens before the lock, and the PTY spawn happens after releasing the lock to avoid blocking the daemon.
func (*SessionManager) ResumeScenario ¶ added in v0.52.0
func (sm *SessionManager) ResumeScenario(name string, rows, cols uint16) ([]string, error)
func (*SessionManager) RevokeDevice ¶ added in v0.66.3
func (sm *SessionManager) RevokeDevice(deviceID string) (int, error)
RevokeDevice removes a paired device and force-closes all of its live connections, so a revoked (e.g. lost/stolen) device loses control immediately rather than at next-connection (design §B.5). It returns the number of connections closed.
func (*SessionManager) RunDetectionLoop ¶
func (sm *SessionManager) RunDetectionLoop(ctx context.Context)
RunDetectionLoop periodically scans PTY scrollback to detect low-risk agent status (active/ready) for all running sessions. Permission prompts are reported as runtime errors by hooks, never inferred from PTY text.
func (*SessionManager) RunFileWatchLoop ¶ added in v0.67.0
func (sm *SessionManager) RunFileWatchLoop(ctx context.Context)
RunFileWatchLoop is the daemon-owned file-watch (#593) trigger source. It reconciles bindings (watch trigger × matching live session) against live fsnotify watchers each tick, and feeds debounced, filtered events into the shared trigger action executor.
func (*SessionManager) RunGC ¶ added in v0.66.16
func (sm *SessionManager) RunGC(force bool, now time.Time) []GCOrphan
RunGC finds orphaned directories and, when force is true, removes those that are safe to delete. A worktree with uncommitted changes is never removed (its unreachable work is preserved for manual recovery) and is reported as skipped. When force is false the returned orphans are a dry-run listing with no filesystem changes.
func (*SessionManager) RunGCXTriggerLoop ¶ added in v0.69.2
func (sm *SessionManager) RunGCXTriggerLoop(ctx context.Context)
RunGCXTriggerLoop reconciles gcx source definitions and polls due bindings. Poll I/O always happens outside both the manager and trigger-state locks.
func (*SessionManager) RunGitPullLoop ¶ added in v0.42.0
func (sm *SessionManager) RunGitPullLoop(ctx context.Context)
func (*SessionManager) RunMessageCleanupLoop ¶ added in v0.3.0
func (sm *SessionManager) RunMessageCleanupLoop(ctx context.Context)
func (*SessionManager) RunOrchestratorReconcileLoop ¶ added in v0.69.1
func (sm *SessionManager) RunOrchestratorReconcileLoop(ctx context.Context)
RunOrchestratorReconcileLoop restores the config-managed orchestrator after a successful delete emits a presence kick. Crash restarts remain in orchestratorSupervisor so their backoff cannot delay a deliberate reset.
func (*SessionManager) RunPRRefWatchLoop ¶ added in v0.68.2
func (sm *SessionManager) RunPRRefWatchLoop(ctx context.Context)
RunPRRefWatchLoop reconciles session memberships in shared repository watchers each tick. Started from RunPRWatchLoop and sharing its lifecycle + gh gate; the loop's own poll is the fallback if this degrades.
func (*SessionManager) RunPRWatchLoop ¶ added in v0.59.0
func (sm *SessionManager) RunPRWatchLoop(ctx context.Context)
RunPRWatchLoop is the daemon-owned PR/CI watcher. Modeled on RunGitPullLoop: config-gated, tolerant of errors, off the request path.
func (*SessionManager) RunPurgeLoop ¶ added in v0.66.16
func (sm *SessionManager) RunPurgeLoop(ctx context.Context)
RunPurgeLoop periodically hard-deletes soft-deleted sessions whose retention window has elapsed. Modeled on RunGitPullLoop: one sweep shortly after startup (to catch windows that elapsed while the daemon was down), then a coarse ticker whose interval is re-read from config each tick. Stops cleanly on context cancel.
func (*SessionManager) RunResourceMonitorLoop ¶ added in v0.68.9
func (sm *SessionManager) RunResourceMonitorLoop(ctx context.Context)
RunResourceMonitorLoop periodically snapshots every live session. Sampling failures are debug-only and never affect session operation.
func (*SessionManager) RunScenarioCompletionLoop ¶ added in v0.69.2
func (sm *SessionManager) RunScenarioCompletionLoop(ctx context.Context)
RunScenarioCompletionLoop reconciles authoritative todo-derived state, dispatches durable actions, adopts session actions after restart, and runs due cleanup. The first pass happens immediately for startup recovery.
func (*SessionManager) RunScenarioPolicyLoop ¶ added in v0.69.2
func (sm *SessionManager) RunScenarioPolicyLoop(ctx context.Context)
RunScenarioPolicyLoop reconciles durable scenario timeout, retry, and quorum state. It runs once immediately so daemon downtime consumes wall-clock deadlines, then at the documented one-second resolution.
func (*SessionManager) RunStartupWatchdogLoop ¶ added in v0.67.7
func (sm *SessionManager) RunStartupWatchdogLoop(ctx context.Context)
RunStartupWatchdogLoop periodically scans for sessions that are stuck in startup — running, but never having produced output, sitting at agent_status "unknown" past the configured startup_timeout — and restarts them fresh (#1092). The timeout is re-read each tick so config reloads take effect.
func (*SessionManager) RunTodoSweepLoop ¶ added in v0.69.0
func (sm *SessionManager) RunTodoSweepLoop(ctx context.Context)
RunTodoSweepLoop periodically reclaims stranded claims (the lease) and sweeps aged-out done items (retention). Both windows come from [todo] config; a zero window disables that sweep. The sweep cadence ([todo] sweep_interval) is read once here, so a change to it takes effect on the next daemon (re)start; the lease/retention windows it applies are re-read each tick, so they are reloadable. Runs until ctx is cancelled.
func (*SessionManager) RunTokenLoop ¶ added in v0.67.6
func (sm *SessionManager) RunTokenLoop(ctx context.Context)
RunTokenLoop periodically re-derives per-session token usage from each supported session's on-disk transcript, writing runtime-only TokenStats onto SessionState (never persisted, repopulated within a tick after restart).
func (*SessionManager) RunTriggerLoop ¶ added in v0.67.0
func (sm *SessionManager) RunTriggerLoop(ctx context.Context)
RunTriggerLoop is the daemon-owned schedule (#592) trigger loop. Modeled on RunPRWatchLoop: config-gated, off the request path, independent mutex. The scheduler tick (coarse; cron granularity is 1 minute) is read once at loop start from [triggers.advanced] scheduler_tick, so changing it needs a daemon restart.
func (*SessionManager) RunUpgradeCleanupLoop ¶ added in v0.70.0
func (sm *SessionManager) RunUpgradeCleanupLoop(ctx context.Context)
func (*SessionManager) ScenarioStatus ¶ added in v0.52.0
func (sm *SessionManager) ScenarioStatus(name string) (*protocol.ScenarioRecord, error)
func (*SessionManager) SendPushNotification ¶ added in v0.67.2
func (sm *SessionManager) SendPushNotification(n pushNotification) (bool, string)
SendPushNotification applies gating (enabled, coalescing, quiet hours, rate limit) then dispatches to the configured backend. It returns whether the notification was delivered and a human-readable reason when suppressed. A backend dispatch error is logged and reported (delivered=false, reason=err) but is not returned as a Go error — callers treat suppression and failure the same way (the notification did not reach the user).
func (*SessionManager) SessionForToken ¶ added in v0.52.0
func (sm *SessionManager) SessionForToken(token string) string
SessionForToken returns the session ID that owns the given token, or empty string if the token is not recognized. Must be called under at least RLock.
func (*SessionManager) SetAttachedClient ¶
func (*SessionManager) SetMsgStore ¶
func (sm *SessionManager) SetMsgStore(ms *MsgStore)
func (*SessionManager) SetSummary ¶ added in v0.32.0
func (sm *SessionManager) SetSummary(sessionID, text string, ttlSeconds int) error
func (*SessionManager) SetTodoStore ¶ added in v0.70.0
func (sm *SessionManager) SetTodoStore(ts *TodoStore)
func (*SessionManager) SoftDelete ¶ added in v0.66.16
func (sm *SessionManager) SoftDelete(id string) (SessionState, error)
SoftDelete marks a session as deleted without removing its worktree or state. The agent process is stopped and the session moves to the stopped state, but everything is preserved so `gr restore` can recover it within the configured retention window. The daemon's purge loop hard-deletes it once the window elapses. System and starred sessions are protected, matching Delete. Returns a snapshot of the soft-deleted session so the caller can report the expiry.
func (*SessionManager) SoftDeleteWithChildren ¶ added in v0.66.16
func (sm *SessionManager) SoftDeleteWithChildren(rootID string, excludeRoot bool) ([]string, error)
SoftDeleteWithChildren soft-deletes a session and all of its transitive descendants. If excludeRoot is true, the root session itself is left alone. Sessions that are already soft-deleted, starred, system, or mid-creation are skipped. A lightweight sweep re-marks descendants that appear mid-operation (a child agent spawning a new session) so the subtree stays coherent — it only re-marks, never tears down, since deferring teardown is the whole point. Returns the list of session IDs that were soft-deleted.
func (*SessionManager) StartScenario ¶ added in v0.52.0
func (sm *SessionManager) StartScenario(msg protocol.ScenarioStartMsg, rows, cols uint16) (*ScenarioState, error)
func (*SessionManager) Stop ¶
func (sm *SessionManager) Stop(id string) error
Stop sends SIGTERM to a session's process without removing the session or worktree.
func (*SessionManager) StopAll ¶
func (sm *SessionManager) StopAll(ctx context.Context)
StopAll gracefully terminates all running sessions concurrently. Each session gets up to 5 seconds to exit after SIGTERM before being force-killed. Sessions are waited on in parallel so the total wait time is bounded by the slowest session, not the sum.
func (*SessionManager) StopScenario ¶ added in v0.52.0
func (sm *SessionManager) StopScenario(name string) ([]string, error)
func (*SessionManager) StopScenarioContext ¶ added in v0.69.2
func (*SessionManager) StopWithChildren ¶ added in v0.30.0
func (sm *SessionManager) StopWithChildren(rootID string, excludeRoot bool) ([]string, error)
StopWithChildren stops all descendants of rootID. If excludeRoot is true, the root session itself is not stopped. Already-stopped sessions are skipped. Returns the list of session IDs that were actually stopped.
func (*SessionManager) TodoAddOp ¶ added in v0.69.0
func (sm *SessionManager) TodoAddOp(ac authContext, m protocol.TodoAddMsg) (protocol.TodoItemInfo, error)
TodoAddOp creates an item in the resolved scope.
func (*SessionManager) TodoAssignOp ¶ added in v0.69.0
func (sm *SessionManager) TodoAssignOp(ac authContext, m protocol.TodoAssignMsg) (protocol.TodoItemInfo, error)
TodoAssignOp sets an item's assignee (override authority / human only).
func (*SessionManager) TodoClaimOp ¶ added in v0.69.0
func (sm *SessionManager) TodoClaimOp(ac authContext, m protocol.TodoClaimMsg) (protocol.TodoClaimResponse, error)
TodoClaimOp claims a specific item (m.ID) or the next eligible item in scope (m.ID empty). The owner is always the calling session, server-derived.
func (*SessionManager) TodoExportOp ¶ added in v0.69.0
func (sm *SessionManager) TodoExportOp(ac authContext, m protocol.TodoExportMsg) (string, error)
TodoExportOp writes the scope's items to the document store and returns the key.
func (*SessionManager) TodoListOp ¶ added in v0.69.0
func (sm *SessionManager) TodoListOp(ac authContext, m protocol.TodoListMsg) ([]protocol.TodoItemInfo, error)
TodoListOp returns items in the resolved scope (or all scopes when m.Scope.All is set by a human/orchestrator).
func (*SessionManager) TodoRemoveOp ¶ added in v0.69.0
func (sm *SessionManager) TodoRemoveOp(ac authContext, m protocol.TodoRemoveMsg) error
TodoRemoveOp deletes an item (and its sub-items).
func (*SessionManager) TodoTransitionOp ¶ added in v0.69.0
func (sm *SessionManager) TodoTransitionOp(ac authContext, m protocol.TodoTransitionMsg) (protocol.TodoItemInfo, error)
TodoTransitionOp performs a guarded status change (done / blocked / todo).
func (*SessionManager) TodoUpdateOp ¶ added in v0.69.0
func (sm *SessionManager) TodoUpdateOp(ac authContext, m protocol.TodoUpdateMsg) (protocol.TodoItemInfo, error)
TodoUpdateOp edits mutable presentation fields.
func (*SessionManager) TriggerList ¶ added in v0.67.0
func (sm *SessionManager) TriggerList() []protocol.TriggerRecord
TriggerList returns records for all configured triggers.
func (*SessionManager) TriggerPause ¶ added in v0.67.0
func (sm *SessionManager) TriggerPause(name string, pause bool) error
TriggerPause pauses/resumes a trigger. A config-disabled trigger cannot be resumed.
func (*SessionManager) TriggerRunNow ¶ added in v0.67.0
func (sm *SessionManager) TriggerRunNow(ctx context.Context, name string) error
TriggerRunNow fires a trigger out-of-band (cause "manual"), respecting the overlap guard but not shifting the schedule cursor.
func (*SessionManager) TriggerStatus ¶ added in v0.67.0
func (sm *SessionManager) TriggerStatus(name string) (protocol.TriggerRecord, error)
TriggerStatus returns one trigger's record, or an error if unknown.
func (*SessionManager) UnregisterDeviceConn ¶ added in v0.66.3
func (sm *SessionManager) UnregisterDeviceConn(deviceID string, conn net.Conn)
UnregisterDeviceConn removes a connection from a device's live set (on connection close).
func (*SessionManager) Update ¶ added in v0.52.0
func (sm *SessionManager) Update(id string, name *string, parentID *string, starred *bool) (SessionState, error)
Update preserves the pre-label call shape for internal lifecycle callers.
func (*SessionManager) UpdateMetadata ¶ added in v0.70.0
func (sm *SessionManager) UpdateMetadata(id string, update SessionUpdate) (SessionState, error)
UpdateMetadata atomically validates, applies, and persists the requested session metadata fields. A failed save restores the complete in-memory snapshot, so callers never observe a mutation that exists only in RAM.
type SessionState ¶
type SessionState struct {
ID string `json:"id"`
ParentID string `json:"parent_id,omitempty"`
Name string `json:"name"`
Labels []string `json:"labels"`
RepoPath string `json:"repo_path"`
RepoName string `json:"repo_name"`
WorktreePath string `json:"worktree_path"`
// CWD is the authoritative working directory assigned to the agent process.
// It is deliberately independent of WorktreePath: mirrors own a writable
// scratch cwd while WorktreePath continues to identify their read-only source.
CWD string `json:"cwd"`
Branch string `json:"branch"`
BaseBranch string `json:"base_branch"`
Agent string `json:"agent"`
AgentSessionID string `json:"agent_session_id,omitempty"`
// NativeStateRoot and NativeCaptureStartedAt make an interrupted
// self-minted session-ID capture reconstructible after exec. They are
// cleared once AgentSessionID is durably recorded.
NativeStateRoot string `json:"native_state_root,omitempty"`
NativeCaptureStartedAt *time.Time `json:"native_capture_started_at,omitempty"`
// DriverKind is the session's transport: DriverPTY (interactive PTY) or
// DriverHeadless (headless stream-json, issue #1075). Resolved once at
// creation and never re-derived from config. Empty is treated as DriverPTY.
DriverKind string `json:"driver_kind,omitempty"`
Model string `json:"model,omitempty"`
// Codex holds typed per-session Codex CLI options (issue #1186), persisted so
// a resume/fork replays the same flags. Nil for non-codex sessions or when no
// option was set. No migration needed: an older state simply has nil here.
Codex *config.CodexOptions `json:"codex,omitempty"`
Status SessionStatus `json:"status"`
AgentStatus string `json:"agent_status,omitempty"`
StatusChangedAt time.Time `json:"status_changed_at"`
IdleSince *time.Time `json:"-"`
GitDirty bool `json:"-"`
GitUnpushed int `json:"-"`
PullRequest PRStatus `json:"-"`
CI CIStatus `json:"-"`
// Tokens is the runtime-derived token usage for the session's current agent,
// re-derived from the on-disk transcript by RunTokenLoop. Like PR/CI it is
// NOT persisted (repopulates within one tick after a restart) and is always
// replaced with a freshly-built pointer under the lock, never mutated in
// place, so an off-lock cloneSessionState is race-free. Nil = never observed.
Tokens *TokenStats `json:"-"`
HookToolName string `json:"-"`
// ContextPressure / ContextPressureAt track Claude's compaction signal:
// PreCompact sets the flag + timestamp, PostCompact clears the flag. Runtime
// only (json:"-"), so a daemon restart forgets them and the next Pre/PostCompact
// re-establishes the picture. Cleared on SessionStart and on resume/restart.
ContextPressure bool `json:"-"`
ContextPressureAt time.Time `json:"-"`
// SubAgents maps a Claude sub-agent's agent_id -> agent_type; len() is the
// live count. A map (not a counter) so a duplicate or missing SubagentStop
// can't underflow or strand a count — a stop is an idempotent delete. Runtime
// only, cleared on SessionStart and resume/restart. Never mutated in place:
// each SubagentStart/Stop replaces it with a fresh map so an off-lock
// cloneSessionState is race-free (mirrors the Tokens discipline above).
SubAgents map[string]string `json:"-"`
// SessionEndReason is Claude's raw SessionEnd reason (clear/resume/logout/
// prompt_input_exit/other). Runtime-only (never persisted): a daemon restart
// forgets it and hooks re-establish the picture. It is distinct from
// StopReason — the process-exit path maps only process-ending reasons onto a
// StopReason (see mapSessionEndReason). Cleared on SessionStart and on
// resume/restart so a stale reason can't outlive its turn.
SessionEndReason string `json:"-"`
// SessionEndReasonGen binds SessionEndReason to the process generation
// (PIDStartTime) that produced it, so the exit path consumes it only for the
// same process — a reason recorded against an older generation is ignored.
SessionEndReasonGen int64 `json:"-"`
// LastMessage is the truncated last_assistant_message from the most recent
// Stop event. Runtime-only; kept off the guest-visible SessionInfo unredacted.
LastMessage string `json:"-"`
ExitCode *int `json:"exit_code,omitempty"`
ExitSignal string `json:"exit_signal,omitempty"`
PID int `json:"pid,omitempty"`
PIDStartTime int64 `json:"pid_start_time,omitempty"`
Sandboxed bool `json:"sandboxed,omitempty"`
SandboxConfig *config.SandboxConfig `json:"sandbox_config,omitempty"`
Mirror bool `json:"mirror,omitempty"`
MirrorSourceID string `json:"mirror_source_id,omitempty"`
// LegacyMirror / LegacyMirrorSourceID hold the pre-v15 persisted keys for
// Mirror / MirrorSourceID (issue #1021 renamed --share-worktree to
// --mirror). They exist only so migrateV14ToV15 can copy old state forward;
// they are cleared after migration and never written under the new binary.
LegacyMirror bool `json:"shared_worktree,omitempty"` // deprecated: migrated to Mirror in v15
LegacyMirrorSourceID string `json:"shared_worktree_source_id,omitempty"` // deprecated: migrated to MirrorSourceID in v15
InPlace bool `json:"in_place,omitempty"`
Includes []IncludedRepoState `json:"includes,omitempty"`
AgentHooks bool `json:"agent_hooks,omitempty"`
// RemovedHookCleanupPending is a one-way migration marker. It prevents a
// policy-enabled process from being adopted and remains durable until exact
// process cleanup and Graith-owned generated-hook cleanup have completed.
RemovedHookCleanupPending bool `json:"removed_hook_cleanup_pending,omitempty"`
Starred bool `json:"starred,omitempty"`
SystemKind string `json:"system_kind,omitempty"`
StopReason string `json:"stop_reason,omitempty"`
BackoffLevel int `json:"backoff_level,omitempty"`
FreshStart bool `json:"fresh_start,omitempty"`
// StuckRestarts counts consecutive startup-watchdog restarts for this session
// (#1092). It caps restart storms for a permanently-broken session and is
// reset to 0 once the session produces output. Runtime-recovery state, but
// persisted so the cap survives a daemon restart mid-storm.
StuckRestarts int `json:"stuck_restarts,omitempty"`
LastStartedAt time.Time `json:"last_started_at,omitempty"`
// LaunchGeneration advances after every successfully committed process
// launch. Scenario retry recovery uses it to distinguish a completed restart
// from a pending action after daemon restart.
LaunchGeneration uint64 `json:"launch_generation,omitempty"`
SummaryText string `json:"summary_text,omitempty"`
SummarySetAt *time.Time `json:"summary_set_at,omitempty"`
SummaryTTL int `json:"summary_ttl,omitempty"`
LastOutputAt *time.Time `json:"last_output_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
LastAttachedAt *time.Time `json:"last_attached_at,omitempty"`
CreationCfg *CreationConfig `json:"creation_config,omitempty"`
Token string `json:"token,omitempty"`
ScenarioID string `json:"scenario_id,omitempty"`
ScenarioName string `json:"scenario_name,omitempty"`
ScenarioRole string `json:"scenario_role,omitempty"`
ScenarioGoal string `json:"scenario_goal,omitempty"`
// TriggerID / TriggerReactor mark a session spawned by a trigger's
// ensure/session action, so the trigger can find and reuse it idempotently
// (mirroring the ScenarioID markers).
TriggerID string `json:"trigger_id,omitempty"`
TriggerReactor bool `json:"trigger_reactor,omitempty"`
// TriggerFingerprint prevents a changed trigger definition from adopting an
// incompatible old reactor. Empty for legacy watch reactors.
TriggerFingerprint string `json:"trigger_fingerprint,omitempty"`
// TrackerIssue is the stable key of the tracker issue a tracker action spawned
// this session for (e.g. "gh:owner/repo#643"). It is the reconcile dedup key:
// a tracker action never respawns a session while a live (running/stopped)
// one with the same TriggerID+TrackerIssue exists. Empty for every non-tracker
// session. See docs/design/2026-07-16-tracker-poll-action.md.
TrackerIssue string `json:"tracker_issue,omitempty"`
// CompletionScenarioID/Epoch/Action/Attempt identify a session spawned as a durable
// scenario-completion action. They let a restarted daemon adopt the action
// instead of spawning a duplicate. They do not make the session a scenario
// member or a lifecycle-cleanup target.
CompletionScenarioID string `json:"completion_scenario_id,omitempty"`
CompletionEpoch int `json:"completion_epoch,omitempty"`
CompletionAction string `json:"completion_action,omitempty"`
CompletionAttempt int `json:"completion_attempt,omitempty"`
// AutoCleanup, when non-empty, soft-deletes this trigger-spawned session
// when it stops: config.CleanupAlways on any stop, config.CleanupOnSuccess
// only on a clean (exit 0) stop. Empty disables it. Set only on
// trigger-spawned sessions, so cleanup never touches a manually created one.
AutoCleanup string `json:"auto_cleanup,omitempty"`
// IdleTimeoutSecs overrides the agent-default idle-stop window for this
// session (seconds; 0 = use the agent default). Set on trigger-spawned
// sessions so an auto_cleanup briefing reaps itself promptly.
IdleTimeoutSecs int `json:"idle_timeout_secs,omitempty"`
MigratedFrom *MigrationInfo `json:"migrated_from,omitempty"`
// DeletedAt marks a session as soft-deleted. When set, the session is
// hidden from the default `gr list` and overlay, its worktree and state are
// preserved until ExpiresAt, and the daemon purges it (hard delete) once the
// window elapses. `gr restore` clears this field.
DeletedAt *time.Time `json:"deleted_at,omitempty"`
// ExpiresAt is the purge deadline, frozen to DeletedAt + retention at delete
// time. It is NOT recomputed from current config on each sweep, so a config
// change only affects future deletes and the "Recoverable until <time>" the
// user was promised never shifts under them. `gr restore` clears this too.
ExpiresAt *time.Time `json:"expires_at,omitempty"`
}
func (*SessionState) IsSoftDeleted ¶ added in v0.66.16
func (s *SessionState) IsSoftDeleted() bool
IsSoftDeleted reports whether the session has been soft-deleted and is awaiting restore or purge.
type SessionStatus ¶
type SessionStatus string
const ( StatusRunning SessionStatus = "running" StatusStopped SessionStatus = "stopped" StatusErrored SessionStatus = "errored" StatusDeleting SessionStatus = "deleting" StatusCreating SessionStatus = "creating" )
type SessionUpdate ¶ added in v0.70.0
type SessionUpdate struct {
Name *string
ParentID *string
Starred *bool
AddLabels []string
RemoveLabels []string
}
SessionUpdate is an atomic delta over mutable session metadata. Nil scalar fields are left unchanged; labels are individual add/remove operations so a stale client never replaces another client's complete set.
type State ¶
type State struct {
Version int `json:"version"`
Sessions map[string]*SessionState `json:"sessions"`
Scenarios map[string]*ScenarioState `json:"scenarios,omitempty"`
// UpgradeCleanup is durable ownership of agent process generations which
// could not be adopted or synchronously reaped across an exec upgrade. More
// than one generation can exist for an ID after state/manifest mismatch, so
// the exact identity key is independent of Sessions.
UpgradeCleanup map[string]UpgradeCleanupState `json:"upgrade_cleanup,omitempty"`
// PairedDevices holds remote client devices authorized via pairing for the
// optional network control surface (design §B.2), keyed by device ID.
PairedDevices map[string]*PairedDevice `json:"paired_devices,omitempty"`
// PairingHMACKey is the key used to HMAC client tokens at rest. Generated
// lazily on first pairing via EnsurePairingHMACKey; never the token itself.
PairingHMACKey string `json:"pairing_hmac_key,omitempty"`
// TriggerRuntime holds per-trigger-definition runtime facts that must survive
// a daemon restart (at-most-once fire anchor, pause state, history). Keyed by
// the namespaced trigger name. The trigger *definition* lives in config and is
// not persisted here. Per-binding watch state is in-memory (rebuilt from live
// sessions) and is not persisted.
TriggerRuntime map[string]*TriggerRuntimeState `json:"trigger_runtime,omitempty"`
// PRWatchPromptedAuthors is the set of untrusted PR-comment author logins the
// PR-watch loop has already surfaced to the orchestrator (the trust prompt),
// so a given author is surfaced at most once ever. Keyed by lower-cased login,
// global (matching the global comment allowlist). Persisted so the once-only
// guarantee survives a daemon restart. Bounded (see PRWatchConfig.MaxPromptedAuthors)
// so it can't grow without limit on a busy public repo.
PRWatchPromptedAuthors map[string]bool `json:"pr_watch_prompted_authors,omitempty"`
}
func LoadStateForAdoption ¶ added in v0.70.0
LoadStateForAdoption is the fail-closed variant used after an exec handoff. Missing, malformed, or unmigratable durable state is an ownership error: the daemon must not substitute NewState and then classify every transferred session as unknown. Unlike ordinary cold-start recovery, this function makes no backup or repair writes before the full file has been validated.
func LoadStateSnapshotForAdoption ¶ added in v0.70.0
LoadStateSnapshotForAdoption validates and migrates an exact pre-exec state snapshot without performing backup, repair, or persistence writes. The caller commits the migrated state only after transferred ownership is live.
func (*State) EnsurePairingHMACKey ¶ added in v0.66.3
EnsurePairingHMACKey returns the key used to HMAC client tokens at rest, generating and storing it on first use. The caller must hold the state write lock and persist the state afterward.
type StateMigrationBackupError ¶ added in v0.70.0
StateMigrationBackupError is returned when an older state file cannot be backed up before migration. Migration must fail closed in this case: without the exact old bytes, an interrupted migration or binary downgrade would have no safe recovery path.
func (*StateMigrationBackupError) Error ¶ added in v0.70.0
func (e *StateMigrationBackupError) Error() string
func (*StateMigrationBackupError) Unwrap ¶ added in v0.70.0
func (e *StateMigrationBackupError) Unwrap() error
type StateVersionError ¶ added in v0.66.16
StateVersionError is returned by LoadState when the on-disk state file is newer than this binary understands. The daemon treats this as fatal (refuses to start) rather than starting with empty state, which would orphan running agents and operate against the wrong picture — see Run.
func (*StateVersionError) Error ¶ added in v0.66.16
func (e *StateVersionError) Error() string
type StreamInfo ¶
type TailnetIdentity ¶ added in v0.66.3
TailnetIdentity is the resolved Tailscale identity behind a remote connection, obtained via the tailnet LocalClient's WhoIs at accept time. User and Node are stable Tailscale identifiers (not display names). For a tagged node WhoIs returns no user, so User is empty and Tags carries the node's tags.
type TodoAdd ¶ added in v0.69.0
type TodoAdd struct {
Scope string
Title string
Note string
Tags []string
ParentID string
Assignee string
DependsOn []string
CreatedBy string
}
TodoAdd carries the inputs for creating a todo item.
type TodoBatchAdd ¶ added in v0.69.2
TodoBatchAdd is one keyed item in an atomic graph insertion. DependsOnKeys names other entries in the same batch; TodoAdd.DependsOn may additionally reference existing todo IDs. Scenario seeding uses member names as keys.
type TodoFilter ¶ added in v0.69.0
TodoFilter narrows a List query. Empty fields are ignored.
type TodoItem ¶ added in v0.69.0
type TodoItem struct {
ID string `json:"id"`
Title string `json:"title"`
Status string `json:"status"`
Scope string `json:"scope"`
Owner string `json:"owner,omitempty"`
Assignee string `json:"assignee,omitempty"`
ParentID string `json:"parent_id,omitempty"`
Note string `json:"note,omitempty"`
Tags []string `json:"tags,omitempty"`
DependsOn []string `json:"depends_on,omitempty"`
BlockedBy []string `json:"blocked_by,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Revision int64 `json:"revision"`
Position int64 `json:"position"`
}
TodoItem is a single todo list entry. It is the daemon-internal shape; the wire type (protocol.TodoItemInfo) mirrors it.
type TodoStore ¶ added in v0.69.0
type TodoStore struct {
// contains filtered or unexported fields
}
TodoStore is a SQLite-backed store for todo items. It is deliberately a separate database (todos.sqlite) from the message log so the higher-churn item write stream and its retention are isolated. A single daemon owns it, so the mutex fully serializes writers; the conditional UPDATEs are additionally race-free at the SQL layer (compare-and-set claim).
func NewTodoStore ¶ added in v0.69.0
func NewTodoStore(dbPath string, settings ...TodoStoreSettings) (*TodoStore, error)
NewTodoStore opens (creating if needed) the todo database at dbPath. An optional TodoStoreSettings tunes the SQLite busy timeout and the title/note/ list operational limits; omit it (or pass a zero value) to use the built-in defaults. Only the first settings value is used.
func (*TodoStore) Add ¶ added in v0.69.0
Add creates a new todo item. It validates the title, note, and parent (one-level only, same scope), assigns a position after the current maximum in the scope, and returns the created item.
func (*TodoStore) AddBatch ¶ added in v0.69.2
func (s *TodoStore) AddBatch(entries []TodoBatchAdd) (map[string]TodoItem, error)
AddBatch atomically inserts a keyed collection of todo items and all of its dependency edges. It is intentionally graph-focused: scenario seed items are top-level, so parented batch entries are rejected.
func (*TodoStore) Assign ¶ added in v0.69.0
Assign sets or clears the assignee (responsible member) of an item.
func (*TodoStore) AssigneeProgress ¶ added in v0.69.0
AssigneeProgress reports, per assignee in a scope, how many assigned items are done vs total. Only items with a non-empty assignee are counted. Used to derive scenario member completion.
func (*TodoStore) Claim ¶ added in v0.69.0
Claim atomically claims a specific eligible unclaimed item for owner. An ordinary caller is eligible for unassigned work and work assigned to itself; an override caller may also take assigned work. It reports whether the claim succeeded (false = already claimed / not claimable). owner must be non-empty and is set server-side by the caller, never trusted from a client payload.
func (*TodoStore) ClaimNext ¶ added in v0.69.0
ClaimNext atomically claims the lowest-position eligible unclaimed item in scope and returns that exact item. An ordinary caller is eligible for unassigned work and work assigned to itself; an override caller may also take assigned work. It selects a candidate, then flips it with a guarded UPDATE keyed by that id; if a (hypothetical, given the store mutex) concurrent claimant took it the UPDATE affects zero rows and we advance to the next candidate. This returns the precise row claimed — not one inferred by recency — so it is correct even when the same owner claims repeatedly under a coarse or mocked clock. Only genuine emptiness returns ok=false.
func (*TodoStore) Counts ¶ added in v0.69.0
Counts returns (done, total) for a scope, counting only top-level items (sub-items roll up under their parent in the UI, but for the session badge we count every item so progress reflects real work).
func (*TodoStore) List ¶ added in v0.69.0
func (s *TodoStore) List(scope string, f TodoFilter) ([]TodoItem, error)
List returns items in a scope, ordered by position then id, filtered by the (optional) filter fields.
func (*TodoStore) ListAll ¶ added in v0.69.0
func (s *TodoStore) ListAll(f TodoFilter) ([]TodoItem, error)
ListAll returns items across every scope (human/orchestrator "--all" view), ordered by scope then position.
func (*TodoStore) Remove ¶ added in v0.69.0
Remove deletes an item (and, via ON DELETE CASCADE, its sub-items and tags).
func (*TodoStore) ReopenOwnedBy ¶ added in v0.69.0
ReopenOwnedBy reopens (status=todo, owner cleared) every in-progress item owned by ownerID. Used when the owning session stops so it retains no active claims. Assignment is deliberately preserved for session resume/retry and must be changed explicitly for takeover. Returns the number of items reopened.
func (*TodoStore) ReopenStale ¶ added in v0.69.0
ReopenStale reopens in-progress items whose updated_at is older than the lease window (a claimant that went quiet). It clears ownership but preserves assignment. lease <= 0 disables the sweep.
func (*TodoStore) ScenarioCurrentSeedItemIDs ¶ added in v0.70.3
ScenarioCurrentSeedItemIDs returns the scenario-seeded top-level todo ID for each member's current assignee. Unlike ScenarioSeedItemIDs, this uses mutable assignment because it is used to validate contracts whose progress is tracked by AssigneeProgress.
func (*TodoStore) ScenarioSeedItemIDs ¶ added in v0.69.2
ScenarioSeedItemIDs returns the original scenario-seeded top-level todo ID for each member session. The immutable seed association survives later assignee changes.
func (*TodoStore) ScenarioSeedItems ¶ added in v0.69.2
ScenarioSeedItems returns the original scenario-seeded top-level todo for each member session, including its effective dependency state. The immutable seed association is independent of the item's mutable current assignee.
func (*TodoStore) SetMaxNote ¶ added in v0.69.1
SetMaxNote updates the todo note length limit live on config reload, with the same clamp-to-default semantics as SetMaxTitle (issue #1291).
func (*TodoStore) SetMaxTitle ¶ added in v0.69.1
SetMaxTitle updates the todo title length limit live on config reload (issue #1291) without reopening the database. A non-positive value or one above the database CHECK ceiling resolves to the default, mirroring TodoStoreSettings.resolved so a reload matches open-time semantics and can never accept a title the database would reject. Safe to call concurrently with Add/UpdateFields (the field is atomic).
func (*TodoStore) SweepDone ¶ added in v0.69.0
SweepDone deletes done items older than maxAge. maxAge <= 0 disables it. A done parent is retained while a child is unfinished or dependency-referenced, because its cascade would otherwise delete protected work. Referenced chains drain safely over later sweeps after their outgoing edges disappear.
func (*TodoStore) SweepDoneExceptScopes ¶ added in v0.69.2
func (s *TodoStore) SweepDoneExceptScopes(maxAge time.Duration, protectedScopes []string) (int, error)
SweepDoneExceptScopes is SweepDone with a set of scopes whose completed items must remain available to a higher-level durable observer.
func (*TodoStore) Transition ¶ added in v0.69.0
Transition applies a guarded status change. actor is the caller; override is true when the caller is the scope's override authority or the human (allowing them to transition an item they do not own). The conditional WHERE enforces the pre-state so an out-of-order or unauthorized transition affects no rows.
func (*TodoStore) TransitionCascade ¶ added in v0.69.2
func (s *TodoStore) TransitionCascade(id, newStatus, note, actor string, override bool) (TodoTransitionResult, error)
TransitionCascade applies a guarded status mutation and any direct dependency-readiness changes in one transaction. A block note is persisted by the same transaction, so note failure cannot leave a half-transition.
func (*TodoStore) UpdateFields ¶ added in v0.69.0
func (s *TodoStore) UpdateFields(id string, title, note *string, tags *[]string, position *int64, dependsOn *[]string) (TodoItem, error)
UpdateFields edits mutable presentation fields. It never touches status, scope, or owner. A nil pointer leaves that field unchanged.
func (*TodoStore) UpdateFieldsCascade ¶ added in v0.69.2
func (s *TodoStore) UpdateFieldsCascade(id string, title, note *string, tags *[]string, position *int64, dependsOn *[]string) (TodoUpdateResult, error)
UpdateFieldsCascade edits mutable fields and reports dependency-readiness changes derived from pre/post snapshots in the same transaction.
type TodoStoreSettings ¶ added in v0.69.1
TodoStoreSettings carries the config-derived operational limits for the todo store. A zero value resolves each field to its built-in default, so tests and callers that don't tune these can pass TodoStoreSettings{} (or nothing).
type TodoTransitionResult ¶ added in v0.69.2
type TodoTransitionResult struct {
Item TodoItem
Unblocked []TodoItem
DependencyBlocked []TodoItem
}
TodoTransitionResult is the atomic result of a status mutation. Unblocked and DependencyBlocked contain unclaimed direct dependents whose effective readiness changed in the same transaction.
type TodoUpdateResult ¶ added in v0.69.2
TodoUpdateResult reports an item's readiness change using snapshots taken inside the same transaction that replaced its dependency edges.
type TokenStats ¶ added in v0.67.6
type TokenStats struct {
Input int64
Output int64
CacheCreation int64
CacheRead int64
Unclassified int64
Total int64
// Degraded reports that the count was parsed but with conflicts or
// un-deduplicatable records, so it is approximate.
Degraded bool
// CountedAt is the time of the last successful observation, for staleness.
CountedAt time.Time
}
TokenStats is the runtime-only token usage for a session's current agent, aggregated from its on-disk transcript. The four categories plus Unclassified are mutually exclusive, so Total is a real total. Built fresh each poll and assigned whole (never mutated in place) so off-lock clones are race-free.
type TriggerRun ¶ added in v0.67.0
type TriggerRun struct {
ScheduledAt time.Time `json:"scheduled_at"`
SourceSessionID string `json:"source_session_id,omitempty"`
Cause string `json:"cause"` // schedule | catch_up | manual | file | gcx | scenario_complete
Result string `json:"result"` // per action type
}
TriggerRun is one entry in a trigger's bounded run history.
type TriggerRuntimeState ¶ added in v0.67.0
type TriggerRuntimeState struct {
Name string `json:"name"`
Fingerprint string `json:"fingerprint"`
Paused bool `json:"paused,omitempty"`
ActivatedAt *time.Time `json:"activated_at,omitempty"`
LastScheduledFireAt *time.Time `json:"last_scheduled_fire_at,omitempty"`
NextScheduledFireAt *time.Time `json:"next_scheduled_fire_at,omitempty"`
LastError string `json:"last_error,omitempty"`
RunCount int `json:"run_count,omitempty"`
History []TriggerRun `json:"history,omitempty"`
// GCXSeen stores the bounded event cursor for a gcx source, keyed by stable
// event ID with the last complete-snapshot observation time. It is committed
// before dispatch so a daemon restart cannot duplicate an event.
GCXSeen map[string]time.Time `json:"gcx_seen,omitempty"`
LastGCXPollAt *time.Time `json:"last_gcx_poll_at,omitempty"`
}
TriggerRuntimeState is the persisted, per-definition runtime state for a trigger. See docs/design/2026-07-11-triggers-design.md §State model.
type UpgradeAdoptionResult ¶ added in v0.70.0
type UpgradeAdoptionResult struct {
ResolvedSessions []UpgradeSession
UnresolvedSessions []UpgradeSession
// contains filtered or unexported fields
}
type UpgradeCapacityProbe ¶ added in v0.70.0
type UpgradeCapacityProbe struct {
Version int `json:"version"`
Backend string `json:"backend"`
MaxSessions int `json:"max_sessions"`
HelperHandoffVersion int `json:"helper_handoff_version"`
StateVersion int `json:"state_version"`
ManifestVersion int `json:"manifest_version"`
AdoptionVersion int `json:"adoption_version"`
Profile string `json:"profile,omitempty"`
Paths UpgradePathDescriptor `json:"paths,omitempty"`
ConfigSource UpgradeConfigSource `json:"config_source"`
}
func CurrentUpgradeCapacityProbe ¶ added in v0.70.0
func CurrentUpgradeCapacityProbe() UpgradeCapacityProbe
func CurrentUpgradeCapacityProbeForConfig ¶ added in v0.70.0
func CurrentUpgradeCapacityProbeForConfig(configFile string) (UpgradeCapacityProbe, error)
type UpgradeCleanupState ¶ added in v0.70.0
type UpgradeConfigSource ¶ added in v0.70.0
type UpgradeHelper ¶ added in v0.70.0
type UpgradeManifest ¶
type UpgradeManifest struct {
Version int `json:"version,omitempty"`
ListenerFd int `json:"listener_fd"`
ConfigFile string `json:"config_file"`
Profile string `json:"profile,omitempty"`
Sessions []UpgradeSession `json:"sessions"`
Helpers []UpgradeHelper `json:"helpers,omitempty"`
Target UpgradeTargetDescriptor `json:"target,omitempty"`
Paths UpgradePathDescriptor `json:"paths,omitempty"`
StateSnapshot []byte `json:"state_snapshot,omitempty"`
ConfigSnapshot []byte `json:"config_snapshot,omitempty"`
ConfigPresent bool `json:"config_present,omitempty"`
JournalID string `json:"journal_id,omitempty"`
// contains filtered or unexported fields
}
func ReadManifest ¶
func ReadManifest(path string) (*UpgradeManifest, error)
type UpgradePathDescriptor ¶ added in v0.70.0
type UpgradeSession ¶
type UpgradeTargetDescriptor ¶ added in v0.70.0
type UpgradeTargetDescriptor struct {
Version string `json:"version,omitempty"`
CommitSHA string `json:"commit_sha,omitempty"`
ResolvedPath string `json:"resolved_path"`
ExecPath string `json:"exec_path,omitempty"`
Size int64 `json:"size"`
Mode uint32 `json:"mode"`
ModTimeNanos int64 `json:"mod_time_nanos"`
SHA256 string `json:"sha256"`
}
type WorktreePort ¶ added in v0.70.0
type WorktreePort interface {
IsInsideRepo(path string) bool
RepoRoot(path string) (string, error)
DiscoverGitHubUsername(ctx context.Context, repoPath string) (string, error)
DiscoverDefaultBranch(repoPath string) (string, error)
DiscoverDefaultBranchOrHEAD(repoPath string) (string, error)
Setup(ctx context.Context, repoPath, worktreePath, branchName, baseBranch string, fetch bool) error
Teardown(repoPath, worktreePath, branchName string) error
}
WorktreePort is the Git lifecycle surface owned by the daemon's session creation path. Keeping this contract here lets lifecycle rollback tests use a deterministic provider without invoking a process-level Git command.
Source Files
¶
- agent_prompt.go
- auth.go
- authmatrix.go
- daemon.go
- driver.go
- filewatch.go
- gc.go
- gcxtrigger.go
- ghpr.go
- gitpull.go
- handler.go
- handler_lifecycle.go
- handler_messaging.go
- handler_query.go
- handler_scenario.go
- handler_todo.go
- handler_trigger.go
- hooks.go
- jail.go
- jailstore.go
- launch.go
- lifecycle.go
- loop_clock.go
- migrate.go
- msg_stream_read.go
- msgstore.go
- notify.go
- orchestrator.go
- origin.go
- pairing.go
- pathrewrite.go
- pid.go
- prpush.go
- prrefwatch.go
- prwatch.go
- pushnotify.go
- remote.go
- remote_runtime.go
- resource_fds_linux.go
- resource_monitor.go
- run.go
- scenario.go
- scenario_policy.go
- scenario_result.go
- scenario_result_store.go
- scenario_template.go
- scenariocompletion.go
- scenariotrigger.go
- server.go
- session_config.go
- session_control.go
- session_create.go
- session_delete.go
- session_detection.go
- session_fork.go
- session_metadata.go
- session_resume.go
- session_softdelete.go
- session_watch.go
- state.go
- storebrowse.go
- taskgroup.go
- tls.go
- todo.go
- tododeps.go
- todostore.go
- tokens.go
- tombstone.go
- tracker.go
- trigger.go
- trigger_actions.go
- triggerstate.go
- upgrade.go
- upgrade_target_pin.go
- validate.go
- validate_model.go
- wait.go
- worktree_port.go