Documentation
¶
Overview ¶
Package server is the API adapter for mecatl: it exposes the agent loop over two network surfaces that share one domain Event taxonomy.
- gRPC (primary): HarnessServer implements the generated mecatlv1.HarnessServiceServer. The bidi Converse stream carries a whole run: a mandatory first Prompt or Retry frame, then zero or more ResumeApproval, Cancel, CancelChild, Steer, or SteerCancel control frames, while the server streams Event envelopes until the terminal result.
- HTTP/SSE (pragmatic): HTTPHandler mirrors the service over REST and SSE — among others POST /v1/sessions, GET /v1/sessions/{id}, POST /v1/sessions/{id}/prompt (text/event-stream), POST /v1/sessions/{id}/controls/resolve-ask and POST /v1/sessions/{id}/controls/cancel — over the same *agent.Engine and the same session.Event; every control names its exact run.
Both surfaces translate session.Event into the proto Event with the pure toProto mapper; neither surface ever sees an OpenAI type. As an adapter this package MAY import engine/agent, engine/session, engine/tool, engine/port and the generated contracts/gen/go.
Required-field validation is enforced here in Go (the proto carries buf.validate annotations for documentation and future runtime enforcement; wiring the protovalidate runtime is a deferred follow-up).
Index ¶
- Constants
- Variables
- func AgentDefSessionRootFromContext(ctx context.Context) string
- func ClampInt32(v int) int32
- func ClassifyAllBoundaries() []error
- func ClassifyCallerStoreBoundaries() []error
- func ClassifyServiceBoundaries() []error
- func ClassifySystemBoundaries() []error
- func ContextWithAgentDefSessionRoot(ctx context.Context, root string) context.Context
- func DeriveTitle(sess *session.Session) string
- func NewPlacementReadinessError(stage, category, cause string) error
- func NewProtectedResourceHandler(profile ProtectedResourceProfile) http.Handler
- func NewScheduleManager(cfg ScheduleManagerConfig) *scheduleManager
- func PlacementGovernanceRoot(binding PlacementBinding) (string, error)
- func PlanManualRetention(rows []port.SessionDiscoveryMeta, policy RetentionPolicy, ...) sessionretention.Result
- func PresentScheduleName(sched port.Schedule) string
- func ValidateClassifiedNames(surface string, table map[string]ClassificationEntry, boundaries []string) []error
- func WellKnownProtectedResourceURL(resource string) string
- func WithProtectedResourceMetadata(profile ProtectedResourceProfile, next http.Handler) http.Handler
- type ACPEnvironmentOverlay
- type AccessKind
- type ActivityGapError
- type ActivityReplayStatus
- type AgentDefSessionEngineFactory
- type AgentDefSessionSelection
- type Authenticator
- type AuthorizationTimer
- type AuthorizationTimerFactory
- type CORSPolicy
- type CapabilityReason
- type ClassificationEntry
- type CleanupCandidate
- type CleanupCounts
- type CleanupItemError
- type CleanupJob
- type CleanupPlan
- type CleanupScope
- type ClientMCPGrant
- type Clock
- type Command
- type CommandSourceBinding
- type CommandSourceResolver
- type Config
- type CreateSessionOption
- func WithAgentDefinitionName(name string) CreateSessionOption
- func WithClientMCP(grant ClientMCPGrant) CreateSessionOption
- func WithDebugMCP(names []string) CreateSessionOption
- func WithDebugTarget(id session.SessionID) CreateSessionOption
- func WithExecutionSelection(e ExecutionSelection) CreateSessionOption
- func WithOwner(p *session.Principal) CreateSessionOption
- func WithPlacementBinding(binding PlacementBinding) CreateSessionOption
- func WithScheduledRelationship(scheduleName string, origin session.SessionID) CreateSessionOption
- func WithSessionID(id session.SessionID) CreateSessionOption
- func WithSourceSession(id session.SessionID) CreateSessionOption
- type DebugSessionEngineFactory
- type DreamCapabilities
- type DreamDecision
- type DreamOperation
- type DreamParticipant
- type DreamReceipt
- type DreamReplacement
- type DreamReview
- type DreamReviewer
- type DreamTarget
- type DreamTargetCapability
- type ExecutionAccess
- type ExecutionRunHandle
- type ExecutionRunRequest
- type ExecutionSelection
- type ExecutionTemplateCatalog
- type ExecutionTemplateInfo
- type ExecutionWorkspaceAcquirer
- type ExplicitReflector
- type FeatureScope
- type ForkSuccessorRequest
- type GuardrailCoverage
- type GuardrailCoverageEntry
- type GuardrailReviewDetail
- type HTTPHandler
- type HarnessServer
- func (h *HarnessServer) AbandonLearningAttempt(ctx context.Context, req *mecatlv1.MutateLearningAttemptRequest) (*mecatlv1.MutateLearningAttemptResponse, error)
- func (h *HarnessServer) ActivateLearnedSkill(ctx context.Context, req *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (h *HarnessServer) ApplySessionCleanup(ctx context.Context, req *mecatlv1.ApplySessionCleanupRequest) (*mecatlv1.CleanupJob, error)
- func (h *HarnessServer) ApprovePlan(req *mecatlv1.ApprovePlanRequest, ...) error
- func (h *HarnessServer) ArchiveLearnedSkill(ctx context.Context, req *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (h *HarnessServer) CancelMcpAuthorization(...) error
- func (h *HarnessServer) CancelRun(ctx context.Context, req *mecatlv1.CancelRunRequest) (*mecatlv1.CancelRunResponse, error)
- func (h *HarnessServer) CancelRunSteer(ctx context.Context, req *mecatlv1.CancelRunSteerRequest) (*mecatlv1.CancelRunSteerResponse, error)
- func (h *HarnessServer) CancelSessionCleanup(ctx context.Context, req *mecatlv1.CancelSessionCleanupRequest) (*mecatlv1.CleanupJob, error)
- func (h *HarnessServer) CancelTeammate(ctx context.Context, req *mecatlv1.CancelTeammateRequest) (*mecatlv1.CancelTeammateResponse, error)
- func (h *HarnessServer) CancelWorkspaceEnrollment(ctx context.Context, req *mecatlv1.WorkspaceEnrollmentControlRequest) (*mecatlv1.WorkspaceEnrollment, error)
- func (h *HarnessServer) CleanupTeam(ctx context.Context, req *mecatlv1.CleanupTeamRequest) (*mecatlv1.CleanupTeamResponse, error)
- func (h *HarnessServer) ClearSession(ctx context.Context, req *mecatlv1.ClearSessionRequest) (*mecatlv1.ClearSessionResponse, error)
- func (h *HarnessServer) CloseSession(ctx context.Context, req *mecatlv1.CloseSessionRequest) (*mecatlv1.CloseSessionResponse, error)
- func (h *HarnessServer) CompactSession(ctx context.Context, req *mecatlv1.CompactSessionRequest) (*mecatlv1.CompactSessionResponse, error)
- func (h *HarnessServer) ConnectWorkspaceServices(ctx context.Context, req *mecatlv1.WorkspaceEnrollmentConnectRequest) (*mecatlv1.WorkspaceEnrollment, error)
- func (h *HarnessServer) Converse(stream mecatlv1.HarnessService_ConverseServer) error
- func (h *HarnessServer) CreateSession(ctx context.Context, req *mecatlv1.CreateSessionRequest) (*mecatlv1.CreateSessionResponse, error)
- func (h *HarnessServer) CreateTeam(ctx context.Context, req *mecatlv1.CreateTeamRequest) (*mecatlv1.CreateTeamResponse, error)
- func (h *HarnessServer) DecideDreamPlan(ctx context.Context, req *mecatlv1.DecideDreamPlanRequest) (*mecatlv1.DecideDreamPlanResponse, error)
- func (h *HarnessServer) DecideLearningProposal(ctx context.Context, req *mecatlv1.DecideLearningProposalRequest) (*mecatlv1.DecideLearningProposalResponse, error)
- func (h *HarnessServer) DeleteSession(ctx context.Context, req *mecatlv1.DeleteSessionRequest) (*mecatlv1.DeleteSessionResponse, error)
- func (h *HarnessServer) DiffLearnedSkillVersions(ctx context.Context, req *mecatlv1.DiffLearnedSkillVersionsRequest) (*mecatlv1.DiffLearnedSkillVersionsResponse, error)
- func (h *HarnessServer) ForkSession(ctx context.Context, req *mecatlv1.ForkSessionRequest) (*mecatlv1.ForkSessionResponse, error)
- func (h *HarnessServer) GenerateDreamPlan(ctx context.Context, req *mecatlv1.GenerateDreamPlanRequest) (*mecatlv1.GenerateDreamPlanResponse, error)
- func (h *HarnessServer) GetCompatibilityInfo(ctx context.Context, _ *mecatlv1.GetCompatibilityInfoRequest) (*mecatlv1.GetCompatibilityInfoResponse, error)
- func (h *HarnessServer) GetGuardrailReviewDetail(ctx context.Context, req *mecatlv1.GetGuardrailReviewDetailRequest) (*mecatlv1.GetGuardrailReviewDetailResponse, error)
- func (h *HarnessServer) GetLearnedSkill(ctx context.Context, req *mecatlv1.GetLearnedSkillRequest) (*mecatlv1.GetLearnedSkillResponse, error)
- func (h *HarnessServer) GetLearningAttempt(ctx context.Context, req *mecatlv1.GetLearningAttemptRequest) (*mecatlv1.GetLearningAttemptResponse, error)
- func (h *HarnessServer) GetLearningProposal(ctx context.Context, req *mecatlv1.GetLearningProposalRequest) (*mecatlv1.GetLearningProposalResponse, error)
- func (h *HarnessServer) GetMcpAuthorizationPresentation(ctx context.Context, req *mecatlv1.GetMcpAuthorizationPresentationRequest) (*mecatlv1.GetMcpAuthorizationPresentationResponse, error)
- func (h *HarnessServer) GetMcpPrompt(ctx context.Context, req *mecatlv1.GetMcpPromptRequest) (*mecatlv1.GetMcpPromptResponse, error)
- func (h *HarnessServer) GetServerInfo(_ context.Context, req *mecatlv1.GetServerInfoRequest) (*mecatlv1.GetServerInfoResponse, error)
- func (h *HarnessServer) GetSession(ctx context.Context, req *mecatlv1.GetSessionRequest) (*mecatlv1.GetSessionResponse, error)
- func (h *HarnessServer) GetSessionCleanupJob(ctx context.Context, req *mecatlv1.GetSessionCleanupJobRequest) (*mecatlv1.CleanupJob, error)
- func (h *HarnessServer) GetSessionTranscript(ctx context.Context, req *mecatlv1.GetSessionTranscriptRequest) (*mecatlv1.GetSessionTranscriptResponse, error)
- func (h *HarnessServer) GetSoul(ctx context.Context, _ *mecatlv1.GetSoulRequest) (*mecatlv1.GetSoulResponse, error)
- func (h *HarnessServer) GetStorageHealth(ctx context.Context, _ *mecatlv1.GetStorageHealthRequest) (*mecatlv1.GetStorageHealthResponse, error)
- func (h *HarnessServer) GetUserModel(ctx context.Context, req *mecatlv1.GetUserModelRequest) (*mecatlv1.GetUserModelResponse, error)
- func (h *HarnessServer) ListAgents(ctx context.Context, _ *mecatlv1.ListAgentsRequest) (*mecatlv1.ListAgentsResponse, error)
- func (h *HarnessServer) ListCommands(ctx context.Context, req *mecatlv1.ListCommandsRequest) (*mecatlv1.ListCommandsResponse, error)
- func (h *HarnessServer) ListExecutionTemplates(ctx context.Context, _ *mecatlv1.ListExecutionTemplatesRequest) (*mecatlv1.ListExecutionTemplatesResponse, error)
- func (h *HarnessServer) ListGuardrailCoverage(ctx context.Context, req *mecatlv1.ListGuardrailCoverageRequest) (*mecatlv1.ListGuardrailCoverageResponse, error)
- func (h *HarnessServer) ListLearnedSkills(ctx context.Context, req *mecatlv1.ListLearnedSkillsRequest) (*mecatlv1.ListLearnedSkillsResponse, error)
- func (h *HarnessServer) ListLearningAttempts(ctx context.Context, req *mecatlv1.ListLearningAttemptsRequest) (*mecatlv1.ListLearningAttemptsResponse, error)
- func (h *HarnessServer) ListLearningProposals(ctx context.Context, req *mecatlv1.ListLearningProposalsRequest) (*mecatlv1.ListLearningProposalsResponse, error)
- func (h *HarnessServer) ListMcpPrompts(ctx context.Context, req *mecatlv1.ListMcpPromptsRequest) (*mecatlv1.ListMcpPromptsResponse, error)
- func (h *HarnessServer) ListMcpResources(ctx context.Context, req *mecatlv1.ListMcpResourcesRequest) (*mecatlv1.ListMcpResourcesResponse, error)
- func (h *HarnessServer) ListMcpSources(ctx context.Context, _ *mecatlv1.ListMcpSourcesRequest) (*mecatlv1.ListMcpSourcesResponse, error)
- func (h *HarnessServer) ListModels(ctx context.Context, _ *mecatlv1.ListModelsRequest) (*mecatlv1.ListModelsResponse, error)
- func (h *HarnessServer) ListSessionMcpConnectors(ctx context.Context, req *mecatlv1.ListSessionMcpConnectorsRequest) (*mecatlv1.ListSessionMcpConnectorsResponse, error)
- func (h *HarnessServer) ListSessions(ctx context.Context, req *mecatlv1.ListSessionsRequest) (*mecatlv1.ListSessionsResponse, error)
- func (h *HarnessServer) ListSkillChanges(ctx context.Context, req *mecatlv1.ListSkillChangesRequest) (*mecatlv1.ListSkillChangesResponse, error)
- func (h *HarnessServer) ListSkillFiles(ctx context.Context, req *mecatlv1.ListSkillFilesRequest) (*mecatlv1.ListSkillFilesResponse, error)
- func (h *HarnessServer) ListSkills(ctx context.Context, _ *mecatlv1.ListSkillsRequest) (*mecatlv1.ListSkillsResponse, error)
- func (h *HarnessServer) ListTeam(ctx context.Context, req *mecatlv1.ListTeamRequest) (*mecatlv1.ListTeamResponse, error)
- func (h *HarnessServer) ListToolHiveGroups(ctx context.Context, _ *mecatlv1.ListToolHiveGroupsRequest) (*mecatlv1.ListToolHiveGroupsResponse, error)
- func (h *HarnessServer) ListWorktrees(ctx context.Context, req *mecatlv1.ListWorktreesRequest) (*mecatlv1.ListWorktreesResponse, error)
- func (h *HarnessServer) PlanSessionCleanup(ctx context.Context, req *mecatlv1.PlanSessionCleanupRequest) (*mecatlv1.PlanSessionCleanupResponse, error)
- func (h *HarnessServer) ReadMcpResource(ctx context.Context, req *mecatlv1.ReadMcpResourceRequest) (*mecatlv1.ReadMcpResourceResponse, error)
- func (h *HarnessServer) ReadSkillFile(ctx context.Context, req *mecatlv1.ReadSkillFileRequest) (*mecatlv1.ReadSkillFileResponse, error)
- func (h *HarnessServer) RecheckMcpAuthorization(...) error
- func (h *HarnessServer) ReflectSession(ctx context.Context, req *mecatlv1.ReflectSessionRequest) (*mecatlv1.ReflectSessionResponse, error)
- func (h *HarnessServer) RefreshMcpSources(ctx context.Context, req *mecatlv1.RefreshMcpSourcesRequest) (*mecatlv1.RefreshMcpSourcesResponse, error)
- func (h *HarnessServer) RejectLearnedSkill(ctx context.Context, req *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (h *HarnessServer) RenameSession(ctx context.Context, req *mecatlv1.RenameSessionRequest) (*mecatlv1.RenameSessionResponse, error)
- func (h *HarnessServer) ResolvePlanAsk(ctx context.Context, req *mecatlv1.ResolvePlanAskRequest) (*mecatlv1.ResolvePlanAskResponse, error)
- func (h *HarnessServer) ResolveRunAsk(ctx context.Context, req *mecatlv1.ResolveRunAskRequest) (*mecatlv1.ResolveRunAskResponse, error)
- func (h *HarnessServer) RetryLearningAttempt(ctx context.Context, req *mecatlv1.MutateLearningAttemptRequest) (*mecatlv1.MutateLearningAttemptResponse, error)
- func (h *HarnessServer) RetryWorkspaceEnrollment(ctx context.Context, req *mecatlv1.WorkspaceEnrollmentControlRequest) (*mecatlv1.WorkspaceEnrollment, error)
- func (h *HarnessServer) RollbackLearnedSkill(ctx context.Context, req *mecatlv1.RollbackLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (h *HarnessServer) RunTeam(req *mecatlv1.RunTeamRequest, stream mecatlv1.HarnessService_RunTeamServer) error
- func (h *HarnessServer) SendTeammateMessage(ctx context.Context, req *mecatlv1.SendTeammateMessageRequest) (*mecatlv1.SendTeammateMessageResponse, error)
- func (h *HarnessServer) SetMode(ctx context.Context, req *mecatlv1.SetModeRequest) (*mecatlv1.SetModeResponse, error)
- func (h *HarnessServer) SpawnTeammate(ctx context.Context, req *mecatlv1.SpawnTeammateRequest) (*mecatlv1.SpawnTeammateResponse, error)
- func (h *HarnessServer) SteerRun(ctx context.Context, req *mecatlv1.SteerRunRequest) (*mecatlv1.SteerRunResponse, error)
- func (h *HarnessServer) StreamSessionEvents(req *mecatlv1.StreamSessionEventsRequest, ...) error
- func (h *HarnessServer) StreamSessionLive(req *mecatlv1.StreamSessionLiveRequest, ...) error
- func (h *HarnessServer) UndoLearningPromotion(ctx context.Context, req *mecatlv1.UndoLearningPromotionRequest) (*mecatlv1.UndoLearningPromotionResponse, error)
- func (h *HarnessServer) WatchSessionEvents(req *mecatlv1.WatchSessionEventsRequest, ...) error
- type HealthHandler
- type IDGenerator
- type ListSessionsPage
- type ListSessionsPageRequest
- type LocalSessionContextServer
- type MCPAuthorizationControl
- type MCPAuthorizationResult
- type MCPRefreshResult
- type MCPRefreshSnapshot
- type MCPSourceStatus
- type MemberEngineFactory
- type ModeScopedWorkspace
- type ModelInventory
- type ModelSnapshot
- type OwnerlessCutoverInventory
- type PlacementBindRequest
- type PlacementBinder
- type PlacementBinding
- type PlacementDeleteRequest
- type PlacementDeleteResult
- type PlacementDeleter
- type PlacementDiscoverer
- type PlacementDiscoveryRequest
- type PlacementMetadata
- type PlacementOperation
- type PlacementProvider
- type PlacementReattachRequest
- type PlacementReattacher
- type PlacementScope
- type PlacementSelector
- type PlacementSelectorKind
- type PlacementSuccessorRequest
- type PlacementSuccessorReservoir
- type PlacementValidator
- type PrincipalValidator
- type ProposalManifestLoader
- type ProposalPromoter
- type ProposalUndoer
- type ProtectedResourceProfile
- type ProviderSelector
- type ReadyFunc
- type ReferenceDeleteHandle
- type ReferenceIntent
- type ReferenceIntentLifecycle
- type ReferenceLifecycle
- type ReflectionReceipt
- type ResolvedModel
- type RetentionPolicy
- type ReviewDetailRegistry
- type RunAskAcknowledgement
- type RunControlAcknowledgement
- type RunEventRecorder
- type RunSteerAcknowledgement
- type ScheduleManagerConfig
- type ScheduleManagerImpl
- type ScheduleServer
- func (h *ScheduleServer) CreateSchedule(ctx context.Context, req *mecatlv1.CreateScheduleRequest) (*mecatlv1.CreateScheduleResponse, error)
- func (h *ScheduleServer) DeleteSchedule(ctx context.Context, req *mecatlv1.DeleteScheduleRequest) (*mecatlv1.DeleteScheduleResponse, error)
- func (h *ScheduleServer) FireNow(ctx context.Context, req *mecatlv1.FireNowRequest) (*mecatlv1.FireNowResponse, error)
- func (h *ScheduleServer) GetFire(ctx context.Context, req *mecatlv1.GetFireRequest) (*mecatlv1.GetFireResponse, error)
- func (h *ScheduleServer) GetSchedule(ctx context.Context, req *mecatlv1.GetScheduleRequest) (*mecatlv1.GetScheduleResponse, error)
- func (h *ScheduleServer) ListFires(ctx context.Context, req *mecatlv1.ListFiresRequest) (*mecatlv1.ListFiresResponse, error)
- func (h *ScheduleServer) ListSchedules(ctx context.Context, _ *mecatlv1.ListSchedulesRequest) (*mecatlv1.ListSchedulesResponse, error)
- func (h *ScheduleServer) PauseSchedule(ctx context.Context, req *mecatlv1.PauseScheduleRequest) (*mecatlv1.PauseScheduleResponse, error)
- func (h *ScheduleServer) ResumeSchedule(ctx context.Context, req *mecatlv1.ResumeScheduleRequest) (*mecatlv1.ResumeScheduleResponse, error)
- func (h *ScheduleServer) UpdateSchedule(ctx context.Context, req *mecatlv1.UpdateScheduleRequest) (*mecatlv1.UpdateScheduleResponse, error)
- type ScopedWorktree
- type SecurityConfig
- type Service
- func (s *Service) AbandonLearningAttempt(ctx context.Context, id, expectedVersion string) (*mecatlv1.LearningAttempt, error)
- func (s *Service) ActivateLearnedSkill(ctx context.Context, r *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (s *Service) ActiveRuns() int
- func (s *Service) AdmittedModes() []session.PermissionMode
- func (s *Service) ApplySessionCleanup(ctx context.Context, token string) (CleanupJob, error)
- func (s *Service) Approve(ctx context.Context, id session.SessionID, askID string, ...) error
- func (s *Service) ApprovePlan(ctx context.Context, id session.SessionID, targetMode session.PermissionMode, ...) (<-chan session.Event, error)
- func (s *Service) ApproveRun(ctx context.Context, id session.SessionID, askID string, ...) (*agent.Run, error)
- func (s *Service) ArchiveLearnedSkill(ctx context.Context, r *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (s *Service) BindPlacement(ctx context.Context, selector PlacementSelector, operation PlacementOperation) (PlacementBinding, error)
- func (s *Service) CanProcessSchedule(sched port.Schedule) bool
- func (s *Service) Cancel(ctx context.Context, id session.SessionID, expectedRunID string) error
- func (s *Service) CancelChild(ctx context.Context, id session.SessionID, childID string) error
- func (s *Service) CancelMCPAuthorization(ctx context.Context, id session.SessionID, control MCPAuthorizationControl) (MCPAuthorizationResult, error)
- func (s *Service) CancelRun(ctx context.Context, id session.SessionID, expectedRunID string) (RunControlAcknowledgement, error)
- func (s *Service) CancelRunSteer(ctx context.Context, id session.SessionID, expectedRunID, messageID string) (RunSteerAcknowledgement, error)
- func (s *Service) CancelSessionCleanup(ctx context.Context, id string) (CleanupJob, error)
- func (s *Service) CancelSteer(ctx context.Context, id session.SessionID, expectedRunID string) (agent.SteerOutcome, error)
- func (s *Service) CancelTeammate(ctx context.Context, teamID, member string) error
- func (s *Service) CancelWorkspaceEnrollment(ctx context.Context, id session.SessionID, ...) (WorkspaceEnrollmentProjection, error)
- func (s *Service) CleanupTeam(ctx context.Context, teamID string) error
- func (s *Service) ClearSessionSuccessor(ctx context.Context, source session.SessionID, placement SuccessorPlacement) (session.SessionID, error)
- func (s *Service) ClientMCPFromWire(servers []mcp.ClientServer) (ClientMCPGrant, error)
- func (s *Service) Close()
- func (s *Service) CloseSession(id session.SessionID)
- func (s *Service) CompactSession(ctx context.Context, id session.SessionID, caller *session.Principal) (agent.ManualCompactionResult, error)
- func (s *Service) CompatibilityInfo(ctx context.Context) *mecatlv1.GetCompatibilityInfoResponse
- func (s *Service) ConnectWorkspaceServices(ctx context.Context, id session.SessionID) (WorkspaceEnrollmentProjection, error)
- func (s *Service) CreateACPSession(ctx context.Context, cwd string, mode session.PermissionMode, ...) (*session.Session, error)
- func (s *Service) CreateSchedule(ctx context.Context, spec port.ScheduleSpec) (port.Schedule, error)
- func (s *Service) CreateSession(ctx context.Context, mode session.PermissionMode, limits session.Limits) (*session.Session, error)
- func (s *Service) CreateSessionWithMCP(ctx context.Context, mode session.PermissionMode, limits session.Limits, ...) (*session.Session, error)
- func (s *Service) CreateSessionWithProfile(ctx context.Context, mode session.PermissionMode, limits session.Limits, ...) (*session.Session, error)
- func (s *Service) CreateSessionWithProvider(ctx context.Context, mode session.PermissionMode, limits session.Limits, ...) (*session.Session, error)
- func (s *Service) CreateTeamForSession(ctx context.Context, source session.SessionID, name, goal string, ...) (string, []team.Member, error)
- func (s *Service) CreateTeamOnDefaultPlacement(ctx context.Context, name, goal string, maxTeamTokens int, ...) (string, []team.Member, error)
- func (s *Service) DecideDream(ctx context.Context, id string, decision DreamDecision) (DreamReceipt, error)
- func (s *Service) DecideLearningProposal(ctx context.Context, id, expected, decision, reason, project string) (*mecatlv1.LearningProposal, error)
- func (s *Service) DeleteSchedule(ctx context.Context, name string) error
- func (s *Service) DeleteSession(ctx context.Context, id session.SessionID) error
- func (s *Service) DeleteSessionForRetention(ctx context.Context, id session.SessionID) error
- func (s *Service) DeleteSessionForRetentionCandidate(ctx context.Context, candidate port.SessionDiscoveryMeta) error
- func (s *Service) Diagnostics() port.Diagnostics
- func (s *Service) DiffLearnedSkillVersions(ctx context.Context, request *mecatlv1.DiffLearnedSkillVersionsRequest) (*mecatlv1.DiffLearnedSkillVersionsResponse, error)
- func (s *Service) Drain()
- func (s *Service) EmitScheduleEvent(ctx context.Context, payload session.SchedulePayload)
- func (s *Service) EndScheduledRun(ctx context.Context, sess *session.Session)
- func (s *Service) EndSession(ctx context.Context, id session.SessionID) error
- func (s *Service) FinishRun(id session.SessionID, run *agent.Run)
- func (s *Service) FireNow(ctx context.Context, name string) (port.ScheduleFire, error)
- func (s *Service) ForkSessionSuccessor(ctx context.Context, req ForkSuccessorRequest) (session.SessionID, error)
- func (s *Service) GenerateDream(ctx context.Context, target DreamTarget) (DreamReview, error)
- func (s *Service) GetFire(ctx context.Context, fireID string) (port.ScheduleFire, error)
- func (s *Service) GetGuardrailReviewDetail(ctx context.Context, ref session.SessionID, reviewID string) (GuardrailReviewDetail, error)
- func (s *Service) GetLearnedSkill(ctx context.Context, request *mecatlv1.GetLearnedSkillRequest) (*mecatlv1.GetLearnedSkillResponse, error)
- func (s *Service) GetLearningAttempt(ctx context.Context, id string) (*mecatlv1.LearningAttempt, error)
- func (s *Service) GetLearningProposal(ctx context.Context, id, project string) (*mecatlv1.LearningProposal, error)
- func (s *Service) GetMcpPrompt(ctx context.Context, server, name string, args map[string]string) (mcp.PromptResult, error)
- func (s *Service) GetSchedule(ctx context.Context, name string) (port.Schedule, error)
- func (s *Service) GetSession(ctx context.Context, id session.SessionID) (*session.Session, error)
- func (s *Service) GetSoul(_ context.Context) *mecatlv1.SoulInfo
- func (s *Service) GetTranscript(ctx context.Context, id session.SessionID) (*SessionTranscript, error)
- func (s *Service) GetUserModel(ctx context.Context) (*mecatlv1.GetUserModelResponse, error)
- func (s *Service) GetUserModelDetail(ctx context.Context, key string) (*mecatlv1.UserModelDetail, error)
- func (s *Service) GracefulDrain(ctx context.Context) error
- func (s *Service) HasScheduler() bool
- func (s *Service) IsDraining() bool
- func (s *Service) IsLive(id session.SessionID) bool
- func (s *Service) LeaseSweepDisabled() bool
- func (s *Service) ListAgents(_ context.Context) []*mecatlv1.AgentInfo
- func (s *Service) ListCommandsForSession(ctx context.Context, id session.SessionID) ([]Command, error)
- func (s *Service) ListExecutionTemplates(ctx context.Context) ([]ExecutionTemplateInfo, string, error)
- func (s *Service) ListFires(ctx context.Context, scheduleName string) ([]port.ScheduleFire, error)
- func (s *Service) ListGuardrailCoverage(ctx context.Context, id session.SessionID) (GuardrailCoverage, error)
- func (s *Service) ListLearnedSkills(ctx context.Context, request *mecatlv1.ListLearnedSkillsRequest) (*mecatlv1.ListLearnedSkillsResponse, error)
- func (s *Service) ListLearningAttempts(ctx context.Context, stateValue, cursor string, limit int) (*mecatlv1.ListLearningAttemptsResponse, error)
- func (s *Service) ListLearningProposals(ctx context.Context, statusValue, cursor string, limit int, project string) (*mecatlv1.ListLearningProposalsResponse, error)
- func (s *Service) ListMcpPrompts(ctx context.Context, server string) ([]mcp.Prompt, error)
- func (s *Service) ListMcpResources(ctx context.Context, server string) ([]mcp.Resource, error)
- func (s *Service) ListMcpSources(_ context.Context) MCPSourceStatus
- func (s *Service) ListModelSnapshot(ctx context.Context) ModelSnapshot
- func (s *Service) ListModels(ctx context.Context) []*mecatlv1.ModelInfo
- func (s *Service) ListSchedules(ctx context.Context) ([]port.Schedule, error)
- func (s *Service) ListSessionMcpConnectors(ctx context.Context, id session.SessionID) (brokercontract.ConnectorInventory, error)
- func (s *Service) ListSessionPage(ctx context.Context, request ListSessionsPageRequest) (ListSessionsPage, error)
- func (s *Service) ListSessions(ctx context.Context) ([]SessionSummary, error)
- func (s *Service) ListSkillChanges(ctx context.Context, r *mecatlv1.ListSkillChangesRequest) (*mecatlv1.ListSkillChangesResponse, error)
- func (s *Service) ListSkillFiles(ctx context.Context, name string) ([]*mecatlv1.SkillFileInfo, error)
- func (s *Service) ListSkills(ctx context.Context) []*mecatlv1.SkillInfo
- func (s *Service) ListTeam(ctx context.Context, teamID string) ([]team.Member, []team.Task, bool, error)
- func (s *Service) ListToolHiveGroups(ctx context.Context) []string
- func (s *Service) ListWorktreesForSession(ctx context.Context, id session.SessionID) ([]ScopedWorktree, error)
- func (s *Service) LoadACPSession(ctx context.Context, id session.SessionID, cwd string, ...) (*session.Session, error)
- func (s *Service) LoadSession(ctx context.Context, id session.SessionID) (*session.Session, error)
- func (s *Service) LoadSessionWithMCP(ctx context.Context, id session.SessionID, specs []mcp.ServerConfig) (*session.Session, error)
- func (s *Service) LookupRun(id session.SessionID) (*agent.Run, bool)
- func (s *Service) LostOwnershipCandidates(ctx context.Context) ([]session.SessionID, error)
- func (s *Service) MCPAuthorizationPresentation(ctx context.Context, id session.SessionID, control MCPAuthorizationControl) (string, error)
- func (s *Service) MaintenanceMutationAvailable() bool
- func (s *Service) ManualDreamCapabilities() DreamCapabilities
- func (s *Service) MaybeAutoApprovePlan(ctx context.Context, id session.SessionID, ev session.Event)
- func (s *Service) OwnershipEnforced() bool
- func (s *Service) PauseSchedule(ctx context.Context, name string) error
- func (s *Service) Persist(ctx context.Context, id session.SessionID)
- func (s *Service) PlanSessionCleanup(ctx context.Context, scope CleanupScope) (CleanupPlan, error)
- func (s *Service) ProviderCapabilities() port.ProviderCapabilities
- func (s *Service) ProviderStatuses() []*mecatlv1.ProviderStatus
- func (s *Service) PublishSessionEvent(id session.SessionID, ev session.Event)
- func (s *Service) ReadMcpResource(ctx context.Context, server, uri string) (mcp.ResourceContents, error)
- func (s *Service) ReadSkillFile(ctx context.Context, name, file string) (string, error)
- func (s *Service) ReattachPlacement(ctx context.Context, ref session.EnvironmentRef) (PlacementBinding, error)
- func (s *Service) ReattachPlacementForBinding(ctx context.Context, ref session.EnvironmentRef, bindingID session.SessionID) (PlacementBinding, error)
- func (s *Service) ReattachPlacementInScope(ctx context.Context, ref session.EnvironmentRef, scope string) (PlacementBinding, error)
- func (s *Service) RecheckMCPAuthorization(ctx context.Context, id session.SessionID, control MCPAuthorizationControl) (MCPAuthorizationResult, error)
- func (s *Service) ReconcileLeaseLossTombstone(ctx context.Context, id session.SessionID) (bool, error)
- func (s *Service) ReconcileReferenceIntents(ctx context.Context)
- func (s *Service) RecoverNotice(id session.SessionID) string
- func (s *Service) ReflectSession(ctx context.Context, id session.SessionID) (*mecatlv1.ReflectionReceipt, error)
- func (s *Service) RefreshMcpSources(ctx context.Context, id session.SessionID) (MCPRefreshResult, error)
- func (s *Service) RejectLearnedSkill(ctx context.Context, r *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (s *Service) RenameSession(ctx context.Context, id session.SessionID, title string) (*session.Session, error)
- func (s *Service) ResolveApprovalRun(ctx context.Context, id session.SessionID, resolution agent.ApprovalResolution, ...) (*agent.Run, error)
- func (s *Service) ResolvePlanAsk(ctx context.Context, id session.SessionID, expectedRunID, askID string, ...) (RunAskAcknowledgement, error)
- func (s *Service) ResolveRunAsk(ctx context.Context, id session.SessionID, expectedRunID, askID string, ...) (RunAskAcknowledgement, error)
- func (s *Service) ResolveScopedRunAsk(ctx context.Context, id session.SessionID, expectedRunID string, ...) (RunAskAcknowledgement, error)
- func (s *Service) ResolvedModel(id session.SessionID) ResolvedModel
- func (s *Service) ResumeSchedule(ctx context.Context, name string) error
- func (s *Service) RetryFailedRun(ctx context.Context, id session.SessionID) (*agent.Run, error)
- func (s *Service) RetryLearningAttempt(ctx context.Context, id, expectedVersion string) (*mecatlv1.LearningAttempt, error)
- func (s *Service) RetryWorkspaceEnrollment(ctx context.Context, id session.SessionID, ...) (WorkspaceEnrollmentProjection, error)
- func (s *Service) RollbackLearnedSkill(ctx context.Context, r *mecatlv1.RollbackLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
- func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.TeamEvent)) (agent.TeamOutcome, error)
- func (s *Service) ScheduleFirePlacement(ctx context.Context, spec port.ScheduleSpec, fireID session.SessionID) (PlacementBinding, error)
- func (s *Service) ScheduleManager() port.ScheduleManager
- func (s *Service) SendTeammateMessage(ctx context.Context, teamID, from, to, body string) error
- func (s *Service) SessionCapabilities(id session.SessionID) port.ProviderCapabilities
- func (s *Service) SessionCleanupJob(ctx context.Context, id string) (CleanupJob, error)
- func (s *Service) SessionStale(ctx context.Context, meta port.SessionMeta) bool
- func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode session.PermissionMode) (*session.Session, error)
- func (s *Service) SetModels(models []*mecatlv1.ModelInfo)
- func (s *Service) SetModelsRefresher(fn func(context.Context))
- func (s *Service) SetProviderStatus(status []*mecatlv1.ProviderStatus)
- func (s *Service) SetScheduleMinInterval(d time.Duration)
- func (s *Service) SetScheduler(sch *scheduler.Scheduler)
- func (s *Service) SetSessionEnvironment(id session.SessionID, env tool.Environment)
- func (s *Service) SettleIfStale(ctx context.Context, id session.SessionID) (bool, error)
- func (s *Service) SpawnTeammate(ctx context.Context, teamID string, spec agent.MemberSpec) (team.Member, error)
- func (s *Service) StaleRunningCandidates(ctx context.Context) ([]port.SessionMeta, error)
- func (s *Service) StartInteractiveRunContent(ctx context.Context, id session.SessionID, text string, ...) (*agent.Run, error)
- func (s *Service) StartInteractiveRunContentWithPlanContinuation(ctx context.Context, id session.SessionID, text string, ...) (*agent.Run, error)
- func (s *Service) StartRun(ctx context.Context, id session.SessionID, text string) (*agent.Run, error)
- func (s *Service) StartRunContent(ctx context.Context, id session.SessionID, text string, ...) (*agent.Run, error)
- func (s *Service) StartScheduledRunContent(ctx context.Context, id session.SessionID, text string, ...) (*agent.Run, error)
- func (s *Service) Steer(ctx context.Context, id session.SessionID, text string, ...) (agent.SteerOutcome, bool, *agent.Run, error)
- func (s *Service) SteerRun(ctx context.Context, id session.SessionID, expectedRunID, text string, ...) (RunSteerAcknowledgement, error)
- func (s *Service) StorageHealth(ctx context.Context) (StorageHealth, error)
- func (s *Service) StorageReady(ctx context.Context) bool
- func (s *Service) StreamSessionEvents(ctx context.Context, id session.SessionID) (iter.Seq2[session.Event, error], error)
- func (s *Service) Subscribe(ctx context.Context, id session.SessionID) (<-chan session.Event, func(), error)
- func (s *Service) UndoLearningPromotion(ctx context.Context, id, expected, project string) (*mecatlv1.LearningProposal, error)
- func (s *Service) UpdateSchedule(ctx context.Context, spec port.ScheduleSpec) (port.Schedule, error)
- func (s *Service) WatchSessionEvents(ctx context.Context, id session.SessionID, after port.Cursor, runID string) (iter.Seq2[WatchEnvelope, error], error)
- func (s *Service) WithAuthorizedSession(ctx context.Context, id session.SessionID, effect func(*session.Session) error) (*session.Session, error)
- type SessionContextEngineFactory
- type SessionEngineFactory
- type SessionEngineResult
- type SessionEngineWithToolsFactory
- type SessionInventoryActionReasons
- type SessionInventoryCapabilities
- type SessionMutationCapability
- func (c *SessionMutationCapability) Disable()
- func (c *SessionMutationCapability) Grant(id session.SessionID)
- func (c *SessionMutationCapability) GuardStore(next port.SessionStore) port.SessionStore
- func (c *SessionMutationCapability) GuardToolCallRecorder(next port.ToolCallRecorder) port.ToolCallRecorder
- func (c *SessionMutationCapability) Invalidate(id session.SessionID)
- func (c *SessionMutationCapability) Remove(id session.SessionID)
- type SessionMutationClass
- type SessionMutationEntry
- type SessionProfile
- type SessionSummary
- type SessionTitleGenerator
- type SessionTranscript
- type StorageHealth
- type StorageMaintenanceEvent
- type StorageMaintenanceState
- type StorageMaintenanceStatus
- type SuccessorPlacement
- type TitleGenerationResult
- type UserModelEntry
- type UserModelInspector
- type UserModelLister
- type WatchEnvelope
- type WorkspaceEnrollmentCollisionError
- type WorkspaceEnrollmentProjection
- type WorkspaceFactory
- type Worktree
- type WorktreeLister
- type WorktreeSelectorIssuer
Constants ¶
const ( // FeatureExecutionTemplates gates the authenticated public template catalog. FeatureExecutionTemplates = "execution_templates" // FeatureExactPlanAskControl reports both strict ResolvePlanAsk transports // when the deployment can durably record a known continuation failure. FeatureExactPlanAskControl = "exact_plan_ask_control" // FeatureHTTPSteer is the unary HTTP steer and cancel-steer control pair // (issue #873). The engine-level steer capability remains a // separate runtime fact; this identifier reports that the HTTP transport // implements the routes the TypeScript SDK can drive. FeatureHTTPSteer = "http_steer" // FeatureSkillFiles is the read-only skill-file pair: the ListSkillFiles and // ReadSkillFile RPCs and their GET /v1/skills/files routes. Against a daemon // that lacks it, the routes answer a generic 404 that looks like skill_not_found, // so a client checks this identifier before offering a skill's files. FeatureSkillFiles = "skill_files" // FeatureServerInfo is this RPC itself. It is degenerate over the wire — a // client that received a response already knows the server implements it — // but it is load-bearing as the registry's self-test: the feature set is // never empty, so "empty means something went wrong" stays a usable // assertion for every other consumer. FeatureServerInfo = "server_info" // FeatureWatchSessionEvents is the durable replay-then-follow watch — the // WatchSessionEvents RPC and its SSE peer (issue #821). // // It answers "does this BUILD implement the watch?", which is the question a // client needs before it decides between one watch and the older // replay-then-subscribe dance. It deliberately does NOT answer "will a watch // succeed here": that additionally depends on the wired event log implementing // the cursor seam, which is a DEPLOYMENT fact and is reported by the // watch_unsupported error instead. // // The DISAMBIGUATOR is the stable `code` string, not the gRPC status. // watch_unsupported is registered as Unimplemented — exactly what grpc-go // returns for a method the server does not have — so a client switching on the // status alone still cannot separate a cursor-less store from version skew; it // has to read the code. That is the contract's design rather than a compromise: // the sibling no_event_log refusal ships the same status for the same class of // fact one level up, and moving this one to FailedPrecondition would make two // sibling refusals disagree while breaking clients whose Unimplemented handling // already covers it. What the feature flag buys is that a client never has to // reach the error at all to know whether the build has the RPC. FeatureWatchSessionEvents = "watch_session_events" // FeatureMCPServersOnCreate is client-provided MCP servers on session // creation — CreateSessionRequest.mcp_servers and its HTTP peer (issue #821). FeatureMCPServersOnCreate = "mcp_servers_on_create" // FeaturePromptFreeControls is the run-ID-addressed unary control family: // resolve-ask, cancel, steer, and cancel-steer. FeaturePromptFreeControls = "prompt_free_controls" // FeatureSessionActivityInventory reports that ListSessions pages carry the // atomically persisted activity projection. FeatureSessionActivityInventory = "session_activity_inventory" // FeatureSessionAgentDefinitions reports root agent-definition binding on both // create transports, independent of whether any definitions are configured. FeatureSessionAgentDefinitions = "session_agent_definitions" // FeatureSessionPermissionModes reports the five session-scoped permission // modes (plan, default, accept-edits, auto, yolo): AUTO and YOLO are valid on // CreateSession, SetMode, and session reads; each mode's authority applies // per session within the server ceiling; and an unspecified CreateSession // mode resolves to the server's configured default. The legacy posture // capability cannot answer this: an older server advertises auto/yolo // posture without supporting these session modes. FeatureSessionPermissionModes = "session_permission_modes" // FeatureRefusedModeRecovery reports that SetMode recovers a stored session // parked awaiting an approval in a mode this server no longer admits: a // SetMode to an admitted, strictly lower mode cancels the pending turn // without running it and applies the mode, instead of refusing mid-turn. // Every other SetMode on an awaiting session is still refused. FeatureRefusedModeRecovery = "refused_mode_recovery" )
A feature identifier is an OPEN STRING, not an enum value.
This is the discipline the event taxonomy already settled on the same axis (AGENTS.md: EvNoProgress/StopNoProgress are "STRING passthroughs on the wire … no `task generate` needed"). A closed proto enum would make every added feature a wire-compat event requiring codegen and a proto review, and would leave an older client decoding new values as UNKNOWN while its exhaustive switch silently grew a dead branch. Adding a server feature should be a minor SDK release, not a schema change.
Identifiers are STABLE ONCE PUBLISHED. Renaming one is a break dressed up as a refactor: a deployed client gates on the exact string.
const ( // DefaultSessionInventoryPageSize applies when the caller omits page_size. DefaultSessionInventoryPageSize = 50 // MaxSessionInventoryPageSize is the hard response-row bound. MaxSessionInventoryPageSize = 100 )
const ( // WatchPhaseReplay marks a record that was already durable when the watch // attached. WatchPhaseReplay = "replay" // WatchPhaseLive marks a record appended while the watch was following, and // the ONE phase-only frame that announces the boundary between the two. WatchPhaseLive = "live" // WatchPhaseGap marks a position where a durable append is KNOWN to have // failed. // // It is a PHASE rather than an event kind, and that is the whole point: // a gap is a fact about DELIVERY, not something that happened // in the run. Making it a session.Event would leak it into the event taxonomy, // the proto Event message, the kind-parity gate, and every consumer that folds // events into a session. TestGapAddsNoEventKind asserts that absence // structurally, because "just add an EvGap so clients can render it" is a // natural-sounding change that would silently relocate a delivery concern into // the domain. WatchPhaseGap = "gap" )
The watch delivery phases. They are OPEN STRINGS on the wire, not an enum — the same discipline the event `type`/`stop` fields carry — so adding a phase is a minor SDK release rather than a wire-compat event, and an older client decoding a new value gets a string it can pass through rather than a dead branch in an exhaustive switch.
const APIMajor int32 = 1
APIMajor is the wire-contract major version this build speaks.
It starts at 1 and bumps ONLY on a genuine break. Every additive change — a new RPC, a new field, a new capability — is announced through the feature vocabulary below instead, which is the entire reason that vocabulary exists. A client gates on APIMajor plus feature identifiers and NEVER on a server/package semver comparison: mecatl is deployed from main as often as from a tag, and a version string cannot tell a client whether a given RPC exists.
Variables ¶
var ( // ErrInvalidToken is the 401-class verdict: the credential is malformed, // unsigned, from the wrong issuer/audience, expired, not yet valid, or // otherwise not vouched for. A validator should wrap it. ErrInvalidToken = errors.New("invalid bearer token") // provider (its JWKS endpoint / discovery document) could not be reached, so // the token's validity is UNKNOWN. It is deliberately distinct from // ErrInvalidToken — an IdP outage must not be reported as an authn failure. ErrIdentityUnavailable = errors.New("identity provider unavailable") )
var ( // Wire adapters map it to Unimplemented / HTTP 501. ErrDreamUnavailable = errors.New("server: manual dream unavailable") // ErrDreamNotFound deliberately covers unknown, expired, and pre-restart plan IDs. ErrDreamNotFound = errors.New("server: dream plan not found; generate a new plan") // ErrDreamInProgress means the same authoritative decision is still applying. ErrDreamInProgress = errors.New("server: dream plan decision is still in progress") // ErrDreamConflict means an opposite decision cannot replace the applying decision. ErrDreamConflict = errors.New("server: dream plan has a conflicting decision in progress") // ErrDreamTerminalConflict means the plan already reached the opposite terminal decision. ErrDreamTerminalConflict = errors.New("server: dream plan was already decided differently") // ErrDreamCapacity means the bounded process-local review registry is full. ErrDreamCapacity = errors.New("server: dream review capacity exhausted") // ErrDreamGenerateFailed is the content-free generation failure category. ErrDreamGenerateFailed = errors.New("server: dream plan generation failed") // ErrDreamApplyFailed is the content-free partial/full application failure category. ErrDreamApplyFailed = errors.New("server: dream plan application failed") // ErrDreamDeadline is the content-free deadline category used by both transports. ErrDreamDeadline = errors.New("dream request deadline exceeded") // ErrDreamRequestFailed is the content-free fallback for unclassified backend errors. ErrDreamRequestFailed = errors.New("server: dream request failed") )
var ( // caller learns neither backend support nor aggregate storage scope. ErrManagementUnauthorized = errors.New("server: management authorization required") // maintenance cannot prove active-session exclusion in this deployment. ErrMaintenanceExclusionUnavailable = errors.New("server: storage maintenance exclusion unavailable") // ErrStorageHealthBackend is the sanitized aggregate-health backend failure. ErrStorageHealthBackend = errors.New("server: storage health unavailable") // ErrCleanupPlanStale reports that catalog candidates, scope, or policy changed // after dry-run. No item is deleted from a stale plan. ErrCleanupPlanStale = errors.New("server: cleanup plan is stale") // ErrCleanupUnsupported honestly reports a backend without indexed pruning. ErrCleanupUnsupported = errors.New("server: session cleanup is unsupported") // ErrCleanupBackend is the sanitized stable maintenance failure. ErrCleanupBackend = errors.New("server: storage maintenance failed") // ErrStaleRunControl is returned when a control (approve / cancel / steer) // carries an expected_run_id that does NOT name the run it would affect. // The control is refused and the current run is left untouched. // // It is a PRECONDITION-class failure, not a bad request: the request is // well-formed and the caller's belief was simply overtaken by events — the run // they meant to act on has already ended and another has begun. Adapters map // it to Aborted / HTTP 409 Conflict, alongside the other // you-lost-a-race sentinels (for example ErrProposalConflict), so a // client can distinguish "retry against the current run" from "fix your // arguments". ErrStaleRunControl = errors.New("server: control targets a run that is no longer current") // ErrAskNotPending means an exact run is live/rehydratable but the addressed // ordinary ask is unknown or was already consumed. ErrAskNotPending = errors.New("server: permission ask is not pending") // ErrPlanResolutionRequired keeps plan asks on their dedicated choreography; // detached ordinary controls must never consume or continue them. ErrPlanResolutionRequired = errors.New("server: plan ask requires plan resolution") // ErrInvalidArgument signals a malformed or missing required field. ErrInvalidArgument = errors.New("server: invalid argument") // ErrNotFound signals an unknown session id. ErrNotFound = errors.New("server: session not found") // ErrTeamNotFound signals an unknown team id. It is distinct from ErrNotFound // (whose message names a session) so a team lookup reports a team-appropriate // message rather than "session not found: team X". Adapters map it to the same // codes.NotFound / HTTP 404 as ErrNotFound. ErrTeamNotFound = errors.New("server: team not found") // ErrChildNotFound signals a CancelChild for a child id the session's // in-flight run does not hold live — unknown, or already finished (the // finished-as-you-pressed race). The wording is FAMILY-NEUTRAL ("child // agent", never "subagent"): it covers subagent, parallel-branch, // team-member, and background-shell child ids alike. Distinct from // ErrNotFound (whose message names a session) so the HTTP /cancel-child // mirror reports a child-appropriate message; adapters map it to the same // codes.NotFound / HTTP 404. ErrChildNotFound = errors.New("server: child agent not found or already finished") // ErrNoMCPProvider signals that an MCP inspection RPC requiring a live // provider (ReadMcpResource / GetMcpPrompt) was called but no MCP provider // is configured. Adapters map it to FailedPrecondition / HTTP 412. ErrNoMCPProvider = errors.New("server: no MCP provider configured") // ErrFailedStepRetryIneligible is the stable precondition sentinel returned when a // session cannot retry its failed model step from persisted conversation state. // Eligibility is based only on typed persisted state. ErrFailedStepRetryIneligible = fmt.Errorf("%w: failed-step retry is not eligible", ErrFailedPrecondition) // ErrFailedPrecondition signals the request is well-formed but the server is // in a state that forbids it — typically a server-side misconfiguration the // client cannot fix by changing its arguments (e.g. spawning a Mutating team // member when no EnvironmentForker is wired, or a member catalog that violates // the read-only-share invariant). Adapters map it to FailedPrecondition / // HTTP 412, distinguishing it from a bad request (ErrInvalidArgument). ErrFailedPrecondition = errors.New("server: failed precondition") // could not attach the prepared repository worktree. The fixed wording is safe // for client transports and deliberately excludes daemon/backend detail. ErrEnvironmentLogicalRootUnavailable = fmt.Errorf("%w: Guest could not attach the prepared repository worktree", ErrFailedPrecondition) ErrLearningUnavailable = errors.New("server: learning proposals are not configured") // ErrAttemptVersionConflict reports an opaque expected-version CAS mismatch. ErrAttemptVersionConflict = errors.New("server: learning attempt version conflict") // ErrAttemptTerminalConflict reports a lifecycle state that cannot perform the requested control. ErrAttemptTerminalConflict = errors.New("server: learning attempt terminal conflict") // ErrAttemptLiveClaimConflict reports an attempt currently fenced by a live worker claim. ErrAttemptLiveClaimConflict = errors.New("server: learning attempt has a live claim") // ErrReflectionCancelled reports caller cancellation during explicit reflection. ErrReflectionCancelled = errors.New("server: reflection cancelled") // ErrReflectionDeadline reports an explicit reflection deadline. ErrReflectionDeadline = errors.New("server: reflection timed out") // ErrReflectionQueueFull reports bounded coordinator admission exhaustion. ErrReflectionQueueFull = errors.New("server: reflection queue is full") // ErrReflectionFailed is the sanitized typed boundary for provider or persistence faults. ErrReflectionFailed = errors.New("server: reflection service failed") // ErrProposalConflict reports a stale proposal version or invalid lifecycle transition. ErrProposalConflict = errors.New("server: proposal conflict") // ErrInternal signals a server-side fault that is NOT the client's fault — a // transport/protocol error talking to a downstream (e.g. an MCP server that // is connected but errors a read). Adapters map it to Internal / HTTP 500, // distinguishing it from a bad request (ErrInvalidArgument). It exists so the // MCP read methods can keep an unknown-server name as InvalidArgument while a // genuine fault on a known server is reported as a server error. ErrInternal = errors.New("server: internal error") // ErrTooManySessionEngines is returned by createSession when the per-session // engine registry is already at Config.MaxSessionEngines. It bounds the memory // growth (CWE-770) from per-session engines created (by a client-MCP session OR a // non-default provider/model selector) but never released via CloseSession / // EndSession — the gRPC/HTTP surfaces have no connection-teardown drain, so a // hostile authed client could otherwise grow the map unbounded. Releasing a // session frees a slot. Adapters map it to ResourceExhausted / HTTP 429, mirroring // ErrTooManyTeams. ErrTooManySessionEngines = errors.New("server: too many live per-session engines") // ErrSessionLeasedElsewhere is returned by the run-entry funnel // (StartRunContent / resumeFromAwaiting) when a cross-process session lease // for the id is held by a DIFFERENT, still-live // process: in a multi-replica deployment another replica owns this session, so // this one must NOT drive it (the single-writer invariant). It is the // composition-side surfacing of port.ErrLeaseHeld at the run-entry gate. // Adapters map it to FailedPrecondition / HTTP 409 Conflict — distinct from // ErrNoActiveRun: the session exists and is well-formed, it is just owned // elsewhere right now (a later retry, after the holder releases or its lease // lapses, can succeed). Only ever returned when a SessionLease is wired. ErrSessionLeasedElsewhere = errors.New("server: session is leased by another process") // StartRunContent + resumeFromAwaiting) when the server is DRAINING — it has // been asked to stop accepting new runs (mecak8s graceful shutdown). // A drained run-entry is rejected before leasing/launching so a rolling update // steers new traffic to a survivor. In-flight runs are cancelled (not drained // to completion); a same-process Approve on a LIVE run is NOT a new run-entry // and stays allowed (it delivers a verdict to an already-running run). Adapters // map it to Unavailable / HTTP 503. The gate starts false (byte-identical // default); Service.Drain arms it. ErrUnavailable = errors.New("server: draining, not accepting new runs") // cannot be reached to open a session's broker session. The session's agent // does not run without one. Adapters map it to Unavailable / HTTP 503; a // later retry can succeed. ErrIdentityBrokerUnavailable = errors.New("server: identity broker unavailable") // the speculative floor could irreversibly compact valid persisted history. ErrContextWindowUnavailable = errors.New("server: context window unavailable") // ErrNotAwaitingPlan is returned by ApprovePlan when the session is not parked // awaiting a PLAN-ORIGINATED permission ask (issue #206): either a run // is LIVE for the session (an approve mid-run — use the Converse ResumeApproval // frame for a live run), the session is not in StateAwaiting, or its pending // ask is a generic tool-permission ask rather than the plan-approval gate's // PresentPlan signalling call. It is a PRECONDITION failure (the session exists // and is well-formed, it is just not in the state this atomic RPC requires), // NOT a bad request. Adapters map it to FailedPrecondition / HTTP 409 Conflict // (distinct from ErrNoActiveRun's "known session, no live run" — here the // session may well be live, just not awaiting a plan ask). ErrNotAwaitingPlan = errors.New("server: session is not awaiting a plan approval") // Schedule-surface sentinels (internal/adapter/server/schedule.go). Defined // here so toStatus/writeServiceError map them in the one error-classification // chokepoint alongside the team/session sentinels. // ErrNoScheduleStore signals that no ScheduleStore is available — the // configured store backend does not expose one. Adapters map it to // Unimplemented / HTTP 501. ErrNoScheduleStore = errors.New("server: scheduled tasks are not supported by the configured store") // ErrNoEventLog signals that no durable EventLog // (port.EventLog) is configured — the configured store backend does not expose // one. It is the EventLog analogue of ErrNoScheduleStore: // StreamSessionEvents returns it so the wire adapters map to UNIMPLEMENTED // (HTTP 501), honestly reporting that the read-back surface is absent rather // than pretending an unknown id. ListSessions does NOT use it (it degrades to // an empty list via PrunableStore instead). ErrNoEventLog = errors.New("server: no durable event log configured") // ErrClientMCPUnsupported means this DEPLOYMENT does not accept // client-provided MCP servers on session creation (the listener-scoped // authority, applied to outbound MCP). It is the deployment's refusal, not the // build's: the RPC and the field exist, this deployment just does not offer // them, exactly as ErrNoEventLog reports a wired-storage fact one level up. // Both map to UNIMPLEMENTED / 501 for that reason, and a client that wants to // know BEFORE it asks reads mcp_servers_on_create from GetCompatibilityInfo. ErrClientMCPUnsupported = errors.New("server: client-provided MCP servers are not accepted on this deployment") // ErrClientMCPUnreachable means the deployment DID accept the request but at // least one requested MCP server could not be connected, so the session was // not created. It is the counterpart of ErrClientMCPUnsupported and a // deliberately DIFFERENT code: "this deployment refuses the field" is // permanent and a client should stop asking, while "your server did not // answer" is transient and retryable once the client's own endpoint is up. // Collapsing them into one code would make an SDK unable to tell a // misconfigured deployment from a sleeping sidecar. // // Creation is ALL-OR-NOTHING on the wire for the reason this sentinel exists: // a partially-mounted session is one the client cannot detect, since the // unreachable-server WARN goes to the operator's log and the create otherwise // returns a perfectly ordinary session id. ErrClientMCPUnreachable = errors.New("server: a requested client-provided MCP server could not be connected") // ErrSessionDeleteUnsupported means the configured store cannot physically // remove snapshots and their sidecars. ErrSessionDeleteUnsupported = errors.New("server: session deletion is not supported by the configured store") // ErrSchedulerNotRunning is returned by FireNow when a ScheduleStore IS // available (Create/Get/List/etc. all work) but no scheduler.Scheduler is // wired on this process (s.scheduler == nil — e.g. --scheduler was not // passed, or this is a store-only replica). It is distinct from // ErrNoScheduleStore (which means the STORE itself cannot hold schedules at // all): here the schedule exists and is well-formed, there is just no // in-process scheduler to drive a manual fire. Adapters map it to // FailedPrecondition / HTTP 412, the same class as ErrScheduleDisabled. ErrSchedulerNotRunning = errors.New("server: scheduler is not running") // ErrScheduleDisabled is returned by FireNow when the schedule is not enabled // (paused or done). It wraps scheduler.ErrFireNowDisabled. Adapters map it to // FailedPrecondition / HTTP 412. ErrScheduleDisabled = errors.New("server: schedule is disabled") // ErrFireNowOverlap is returned by FireNow when the singleton overlap check // found a prior fire still running. It wraps scheduler.ErrFireNowOverlap AND // port.ErrFireNowOverlap (the port-level sentinel a layer that may not import // this adapter — e.g. engine/agent's Schedule tool — matches via errors.Is, // the same create-seam default-true Singleton holding through every surface). // Adapters map it to FailedPrecondition / HTTP 412 (the schedule exists and // is well-formed, it is just running — the same precondition-failed class as // ErrScheduleDisabled; the two surfaces agree). ErrFireNowOverlap = fmt.Errorf("server: fire-now skipped (prior fire still running): %w", port.ErrFireNowOverlap) // ErrScheduleExhausted is returned by FireNow when a one-shot schedule has // already fired (FireCount > 0). It wraps scheduler.ErrFireNowExhausted. // Adapters map it to FailedPrecondition / HTTP 412. ErrScheduleExhausted = errors.New("server: one-shot schedule already fired") // ErrScheduleNotLeader is returned by FireNow when this replica is not the // scheduler leader (a multi-replica deployment where a peer holds the // `__scheduler__` lease). It wraps scheduler.ErrNotLeader. Adapters map it // to FailedPrecondition / HTTP 412; the message names the current leader // (when known) so a client can redirect. ErrScheduleNotLeader = errors.New("server: not the scheduler leader") )
Sentinel errors the service returns; the gRPC and HTTP adapters map these to their respective status codes (codes.InvalidArgument / NotFound, HTTP 400 / 404).
var ( // ErrInvalidPlacementSelection reports a malformed selector or binding request. ErrInvalidPlacementSelection = errors.New("server: invalid placement selection") // ErrPlacementNotFound deliberately covers absent and authorization-hidden selectors. ErrPlacementNotFound = errors.New("server: placement selector not found") // ErrPlacementStale reports an expired selector without disclosing hidden choices. ErrPlacementStale = errors.New("server: placement selector is stale") ErrPlacementUnavailable = errors.New("server: placement unavailable") // ErrPlacementChanged reports an inventory revision race during Bind. ErrPlacementChanged = errors.New("server: placement changed during bind") // ErrInvalidPlacementBinding reports unsafe or internally inconsistent provider output. ErrInvalidPlacementBinding = errors.New("server: invalid placement binding") )
var ( // ErrSkillFileTooLarge reports a file over maxSkillFileBytes. It is refused, not truncated. ErrSkillFileTooLarge = errors.New("server: skill file is too large to read") // ErrSkillFileNotText reports a file that is not text: invalid UTF-8, or containing a NUL byte. ErrSkillFileNotText = errors.New("server: skill file is not valid text") )
var ErrActivityGap = errors.New("server: a durable event-log append failed; this watch has a delivery gap")
ErrActivityGap means a durable append failed while a watch was attached, so the watch's stream is known to be incomplete.
var ErrBrokerBindingMismatch = errors.New("MCP broker binding mismatch")
ErrBrokerBindingMismatch marks a session whose persisted binding does not match the live broker incarnation. The error it decorates also satisfies brokercontract.ErrStateUnavailable, so repair and settlement paths keep treating it as lost state — but live authorization controls must hard-fail on it rather than silently resolving the authorization as interrupted.
var ErrCommandBindingRetired = errors.New("harness command binding is retired")
ErrCommandBindingRetired requires explicit authorized activation, never an ordinary borrow.
var ErrConfig = errors.New("server: invalid config")
ErrConfig is returned by NewService when a required dependency is missing.
var ErrExecutionTemplatesDisabled = errors.New("execution templates disabled")
ErrExecutionTemplatesDisabled reports an unwired per-owner template policy or catalog.
var ErrNoActiveRun = errors.New("server: no active run for session")
ErrNoActiveRun is returned by Approve/Cancel when the session exists (possibly loaded from the store after a restart) but has no in-flight run in this process to deliver the control to AND nothing to resume. The session state is still loadable via GetSession.
An Approve/Deny against a runless AWAITING session does not return ErrNoActiveRun: it re-enters the loop AT the ask and resumes (resumeFromAwaiting). For Approve/Deny, ErrNoActiveRun means "the session exists but is in a terminal/idle state with nothing to resume" — idle, completed, cancelled, or failed. A failed/cancelled session recovers only through a NEW prompt (loadAndReopen → Recover/Interrupt), never through the approve seam. Cancel returns it in every state with no live run to cancel.
var ErrTeamNotRunning = errors.New("server: team is not running")
ErrTeamNotRunning is returned when an operation requires a RUNNING team but the team's phase is teamCreated (created, never run) or teamDone (RunTeam already returned) — a CancelTeammate has no in-flight run to reach into. It maps to codes.FailedPrecondition.
var ErrTeamRunning = errors.New("server: team is already running")
ErrTeamRunning is returned when an operation is rejected because the team is already running: a second concurrent RunTeam, a SpawnTeammate after the team has started, or a CleanupTeam on a still-running team. It maps to codes.FailedPrecondition.
var ErrTeamsDisabled = errors.New("server: agent teams are not enabled")
ErrTeamsDisabled is returned by the team methods when no MemberEngine is wired in Config — agent teams are an opt-in capability the composition root enables.
var ErrTooManyTeams = errors.New("server: too many live teams")
ErrTooManyTeams is returned by CreateTeam when the live-team registry is already at Config.MaxTeams. It bounds the leak from teams created but never cleaned up. It maps to codes.ResourceExhausted.
var ErrWatchLagging = errors.New("server: watch terminated because the client fell behind the bounded delivery buffer")
ErrWatchLagging means a watch was terminated because its client fell behind the bounded delivery buffer for longer than the grace.
TERMINATING is the point. Service.Subscribe, the pre-cursor live registry, DROPS events for a slow subscriber: the stream stays open and the client never learns it is missing data. A durable cursor exists precisely so that the honest alternative is available — end the stream, and let the client resume from the last cursor it received, losing nothing.
It carries NO cursor, deliberately. The server's furthest-queued position is NOT the client's: envelopes still sitting in the delivery buffer were never received, so resuming from a server-side cursor would SKIP exactly the events the termination was supposed to protect. The client's own last-received envelope is the only correct resume point, and the client always has it.
var ErrWatchUnsupported = errors.New("server: the configured event log does not support cursors")
ErrWatchUnsupported means the configured durable EventLog does not implement port.CursorEventLog, so it cannot serve a positional resume or a follow.
It is deliberately an ERROR rather than a degrade to "replay the whole transcript and stop". A client that asked to resume from a position and was handed everything from the beginning is a correctness problem dressed as a performance one: it would silently re-process events it had already acted on, and never learn that its cursor meant nothing.
Functions ¶
func AgentDefSessionRootFromContext ¶ added in v0.0.49
AgentDefSessionRootFromContext returns the root attached by ContextWithAgentDefSessionRoot, or "" if none was set.
func ClampInt32 ¶
ClampInt32 narrows a Go int (counter/index/count) to the proto int32 wire type, saturating at the int32 bounds rather than wrapping. These values (turn indices, counters, model counts) never realistically approach the limit; the clamp exists only so the conversion is provably overflow-safe. Exported so internal/app (e.g. the ProviderStatus model_count clamp) can reuse it instead of hand-rolling the same gosec G115 dance.
Written as the if-assign idiom, not `min(v, math.MaxInt32)`, because gosec's G115 range analysis tracks this bound but does NOT propagate it through the `min` builtin (the min form trips G115 on the int32 cast below).
func ClassifyAllBoundaries ¶
func ClassifyAllBoundaries() []error
ClassifyAllBoundaries runs every server-owned classified surface's guard and returns the concatenated findings — the single entry point TestInvariant_owned_access_is_classified drives (AC5.1).
func ClassifyCallerStoreBoundaries ¶
func ClassifyCallerStoreBoundaries() []error
ClassifyCallerStoreBoundaries walks every exported memory.CallerStore method (the cache/index boundary for caller-partitioned memory).
func ClassifyServiceBoundaries ¶
func ClassifyServiceBoundaries() []error
ClassifyServiceBoundaries walks every exported *Service method (the application-facade, in-memory-registry, and event-relay boundary) and reports one error per unclassified, misclassified, or stale entry.
func ClassifySystemBoundaries ¶
func ClassifySystemBoundaries() []error
ClassifySystemBoundaries walks every registered internal/syscaller.Root (the explicit shared-infrastructure system-principal scopes).
func ContextWithAgentDefSessionRoot ¶ added in v0.0.49
ContextWithAgentDefSessionRoot attaches an agent-bound session's own resolved governance root (ADR 0291's server-owned placement, PlacementGovernanceRoot) to ctx before invoking AgentDefSessionEngineFactory. root is "" when the session has no placement to bind to (profile: "no-fs"), which AgentDefSessionRootFromContext's callers treat as inert, never an error.
func DeriveTitle ¶
DeriveTitle returns the session's human-readable label: the snapshot Title if set, else the clamped text of the FIRST genuine user prompt found by walking sess.Conversation.Messages (via session.IsGenuineUserPrompt, which skips synthesised compaction summaries), else "" (no genuine prompt). It is the lazy display-time fallback for a session whose Title was never seeded (e.g. a session created before the Title field existed, or one whose first prompt was multimodal-only). It does NOT mutate sess.Title — NO write-on-read: the snapshot stays the authoritative set-once label, and the derived value is a pure read projection the caller places on the wire. Used by ListSessions (picker) and the GetSession handlers.
func NewPlacementReadinessError ¶ added in v0.0.42
NewPlacementReadinessError constructs the bounded public projection of a placement readiness failure. Unknown values fail closed to generic placement unavailability rather than carrying provider text across the server boundary.
func NewProtectedResourceHandler ¶ added in v0.0.26
func NewProtectedResourceHandler(profile ProtectedResourceProfile) http.Handler
NewProtectedResourceHandler returns the anonymous RFC 9728 endpoint for a complete profile. A nil result means discovery is disabled.
func NewScheduleManager ¶
func NewScheduleManager(cfg ScheduleManagerConfig) *scheduleManager
NewScheduleManager constructs a scheduleManager from the plain pre-Service inputs: a port.SessionStore + a now-func ALONE (no *Service value required, resolvable before buildEngine). It resolves the ScheduleStore as follows: when ScheduleManagerConfig.ScheduleStore is non-nil (the --schedule-store-url composition override) it WINS — the registry is a remote driver, not the session store's own accessor, so the in-chat Schedule tool + the tick loop + the fire path share the ONE resolveScheduleStore resolution; otherwise the store is type-asserted for a ScheduleStore via the scheduleStoreProvider accessor (the jsonlstore + redisstore expose one). A store that backs no ScheduleStore AND carries no override (the in-memory memstore) yields a nil/absent manager — the honest no-scheduling path, matching ServerCapabilities.Scheduling. The returned manager satisfies port.ScheduleManager (all nine verbs) and is the single truth the *Service delegates to.
Models is OPTIONAL: a standalone-constructed manager (no Models pointer) admits only the empty selector (an empty inventory) — composition passes the Service's own pointer so SetModels keeps working with no second copy. Diagnostics is OPTIONAL and nil-safe.
func PlacementGovernanceRoot ¶ added in v0.0.42
func PlacementGovernanceRoot(binding PlacementBinding) (string, error)
PlacementGovernanceRoot returns explicit host-side governance context when provided. A non-local empty root means no host governance context and never falls back to the execution namespace; local bindings fall back to the execution root for governance.
func PlanManualRetention ¶
func PlanManualRetention(rows []port.SessionDiscoveryMeta, policy RetentionPolicy, owner *session.Principal, live, leased map[session.SessionID]bool, now time.Time) sessionretention.Result
PlanManualRetention runs the shared, side-effect-free retention planner (sessionretention.Plan) behind the manual cleanup API. internal/app's automatic sweep (childGC.sweep) calls sessionretention.Plan directly with the same policy/scope shape; see TestSessionStorageContinuity_Scenario5_AutomaticManualPlannerParity in internal/app/childgc_test.go for the cross-check between the two real call sites (AC5.5).
func PresentScheduleName ¶
PresentScheduleName projects the caller-visible name from an authoritative stored schedule. Ownerless records carry literal names byte-for-byte. Owned records carry an owner-qualified physical key, which is stripped only when it matches the exact namespace derived from the stored owner. Arbitrary strings never acquire physical-key provenance from their grammar alone.
func ValidateClassifiedNames ¶
func ValidateClassifiedNames(surface string, table map[string]ClassificationEntry, boundaries []string) []error
ValidateClassifiedNames compares actual boundary names with their classification entries. It is exported for composition-owned registries whose concrete registrations are not visible to this package.
func WellKnownProtectedResourceURL ¶ added in v0.0.26
WellKnownProtectedResourceURL derives the RFC 9728 metadata URL for resource. The same helper is used for public routing and bearer challenges so path resources cannot advertise one endpoint and serve another.
func WithProtectedResourceMetadata ¶ added in v0.0.26
func WithProtectedResourceMetadata(profile ProtectedResourceProfile, next http.Handler) http.Handler
WithProtectedResourceMetadata mounts the anonymous metadata endpoint in front of next. Non-metadata routes retain next's existing behavior.
Types ¶
type ACPEnvironmentOverlay ¶ added in v0.0.24
type ACPEnvironmentOverlay func(session.SessionID, tool.Environment) (tool.Environment, error)
ACPEnvironmentOverlay decorates an already-authorized placement environment with editor-buffer semantics. The returned environment must preserve the exact placement identity.
type AccessKind ¶
type AccessKind int
AccessKind is one of the four classifications required for every designated application object-touching boundary.
const ( // KindCallerOwned means the boundary itself resolves the ownership // decision (ownsResource/authorizeSession/authorizeSchedule, or an // equivalent per-kind check such as memory.CallerStore's context-derived // namespace) on every call, denying a foreign caller as absence. // // MANAGEMENT-AUTHORITY SUB-CASE (the storage-maintenance boundaries: // StorageHealth, Plan/Apply/CancelSessionCleanup, SessionCleanupJob): the // identity decision — "is this the verified management principal", and // for the ones that mint a job/plan/token, "does this handle belong to // THIS caller" — so KindCallerOwned's structural contract (a real ctx // check, no bypass) holds. But unlike an ordinary caller-owned boundary, // the underlying DATA these operate over is store-wide (every session), // never narrowed to "this caller's own rows". Don't read their entries' // "caller-owned" kind as data-scoping; read the rationale text for what // is actually decided. A future 5th AccessKind naming this sub-case // explicitly would widen the closed 4-kind taxonomy — not done here. KindCallerOwned AccessKind = iota // KindDerived means the boundary carries no independent decision of its // own: it operates on an identifier a caller can only obtain from an // ALREADY-classified caller-owned boundary (e.g. the id a CreateSession // call just returned, or an id a Cancel/EndSession call already // authorized before reaching it). It resolves ownership by construction, // not by re-checking. KindDerived // non-caller-identified operation — an internal system-principal root // or a process-wide catalog/config read that is, // by design, the same for every caller. KindSharedInfrastructure // KindExempt is an explicit, reviewed carve-out for a boundary that // structurally cannot carry caller identity — a pure composition-time // wiring setter/accessor, a lifecycle control, or a workspace-path-scoped // (not caller-scoped) read gated by the pre-existing project-trust axis. KindExempt )
func (AccessKind) String ¶
func (k AccessKind) String() string
type ActivityGapError ¶ added in v0.0.22
type ActivityGapError struct{}
ActivityGapError is the process-local, GUARANTEED tier of the three-tier append-gap guarantee: when an append fails, every watcher in the failing process terminates with this error and its cursor never advances.
Like ErrWatchLagging it carries no cursor, for the same reason: the client's last-received envelope is the resume point, and the server must not invent one that would skip the buffered tail.
The guarantee this belongs to is DELIBERATELY WEAKER than an absolute, and the weakness is not an implementation gap. A failed append consumed no position, so it leaves nothing for a watcher in ANOTHER process to observe; the best-effort durable gap marker (AppendGap) covers the likely case of one rejected record, and a total backend outage plus process loss leaves a gap that is undetectable by construction. Do not restate this as an absolute.
It carries NO description of the underlying failure, deliberately. The cause is a raw backend error — `dial tcp 10.0.0.5:6379: connect: connection refused`, a jsonlstore path — and this value reaches the client as a gRPC status message and an SSE `error` field. That is the same exposure GetSession already refuses under ownership enforcement, on the same reasoning: the store's error routinely embeds infrastructure detail a caller has no business reading. The cause is not lost — it goes to the durable gap marker (tier 1) and to the append-failure WARN the recorder already emits — so the operator keeps every byte of it and the client gets the stable `activity_gap` code, which is the whole of what it can act on.
func (*ActivityGapError) Error ¶ added in v0.0.22
func (*ActivityGapError) Error() string
func (*ActivityGapError) Unwrap ¶ added in v0.0.22
func (*ActivityGapError) Unwrap() error
Unwrap lets errors.Is(err, ErrActivityGap) classify this through the shared error registry, so both transports report it identically.
type ActivityReplayStatus ¶
ActivityReplayStatus describes the optional EventLog activity plane. EventLog has no completeness attestation, so Complete and Authoritative remain false.
type AgentDefSessionEngineFactory ¶ added in v0.0.49
type AgentDefSessionEngineFactory func(ctx context.Context, sel ProviderSelector, profile SessionProfile, mode session.PermissionMode, limits session.Limits, defName string) (SessionEngineResult, error)
AgentDefSessionEngineFactory builds the dedicated engine for a session bound to a named AgentDef (ADR 0353): the session's catalog is built EXCLUSIVELY from the resolved def's own tools/mcpServers (never the deployment's default explorer catalog), and its minted session.Authority (SessionEngineResult.Authority) is derived from that SAME resolved catalog — never Config.RootAuthority's build-time default closure. It mirrors DebugSessionEngineFactory's shape, replacing the debug-target inputs with the def name that selects the engine; no workspace parameter is needed because catalog assembly never binds a filesystem root itself (the session's own tool.Environment does that at run time, exactly like every other per-session factory). An unresolvable defName is a loud error wrapping ErrInvalidArgument, mirroring how an unknown provider_id is handled today.
limits is the caller's REQUEST Limits, threaded in RAW (never WithDefaults-filled by the caller — see createSession, which skips its general WithDefaults(cfg.DefaultLimits) fold for an agent-bound create): only the composition-layer factory knows the bound def's own configured Limits/permissionMode ceiling (AC1.12/AC1.13, ADR 0353's tighten-only clamps), so it alone can tell "a zero field means not supplied, inherit the def's cap" apart from "the operator's own default already filled it in." The factory returns the clamped mode via SessionEngineResult.BuiltForMode (echoed exactly like every other factory when no def restricts it further) and the clamped Limits via SessionEngineResult.Limits; the caller applies both to what it actually persists on the session.
A placement-aware extension (memory: project, issue #33, ADR 0353 Scenario 2 AC2.5) still needs to know THIS session's own bound governance root (ADR 0291) despite the factory gaining no dedicated parameter for it — the caller attaches it to ctx via ContextWithAgentDefSessionRoot before invoking the factory; AgentDefSessionRootFromContext reads it back inside the factory's own composition-layer closure. This keeps the factory's shape exactly as originally frozen (no per-feature parameter growth) while still letting two agent-bound sessions on the SAME def but DIFFERENT placements resolve distinct project-memory files instead of leaking one into the other.
type AgentDefSessionSelection ¶ added in v0.0.49
AgentDefSessionSelection identifies a bounded root build through the ordinary owner/execution-scoped SessionContextEngine binding lifecycle.
func AgentDefSessionSelectionFromContext ¶ added in v0.0.49
func AgentDefSessionSelectionFromContext(ctx context.Context) (AgentDefSessionSelection, bool)
AgentDefSessionSelectionFromContext reports the bounded root requested by the service. SessionContextEngine must dispatch it after binding the owner sources, rather than constructing an ordinary explorer catalog.
type Authenticator ¶
type Authenticator struct {
// contains filtered or unexported fields
}
Authenticator bundles the configured auth + rate-limit policy and exposes the gRPC interceptors and HTTP middleware that enforce it. Construct it once and share it across both surfaces.
func NewAuthenticator ¶
func NewAuthenticator(cfg SecurityConfig) *Authenticator
NewAuthenticator builds an Authenticator from cfg. When rate limiting is disabled the limiter set is nil and the rate-limit checks are skipped.
func (*Authenticator) Close ¶
func (a *Authenticator) Close()
Close releases the edge's own long-lived resources at shutdown. Today that is exactly one thing: the configured validator's teardown, when it has one.
Teardown is an OPTIONAL CAPABILITY, type-asserted (the port.HookApprovalLearner idiom), never a method on PrincipalValidator — widening that single-method interface would break every fake and every test that scripts the seam. A validator without a Close needs none.
It exists because the real validator (toolhive-core/authn) owns a BACKGROUND JWKS refresh that its Close() stops, and cancelling the root context does NOT call Close(). Both server mains defer Authenticator.Close.
Safe to call more than once and on the identity-OFF zero value.
func (*Authenticator) Middleware ¶
func (a *Authenticator) Middleware(next http.Handler) http.Handler
Middleware wraps next with bearer-auth and rate-limit enforcement. The health endpoints (/healthz, /readyz) MUST be mounted outside this middleware so they remain reachable without credentials and are never rate limited.
func (*Authenticator) StreamInterceptor ¶
func (a *Authenticator) StreamInterceptor() grpc.StreamServerInterceptor
StreamInterceptor returns a grpc.StreamServerInterceptor enforcing auth then rate limiting before the stream handler runs. The rate check is applied once, at stream establishment.
func (*Authenticator) UnaryInterceptor ¶
func (a *Authenticator) UnaryInterceptor() grpc.UnaryServerInterceptor
UnaryInterceptor returns a grpc.UnaryServerInterceptor enforcing auth then rate limiting before the handler runs. The verified principal (if any) rides the handler context.
type AuthorizationTimer ¶ added in v0.0.26
type AuthorizationTimer interface{ Stop() bool }
AuthorizationTimer is a cancellable process-local expiry handle.
type AuthorizationTimerFactory ¶ added in v0.0.26
type AuthorizationTimerFactory func(time.Duration, func()) AuthorizationTimer
AuthorizationTimerFactory creates one expiry observation for a parked authorization.
type CORSPolicy ¶ added in v0.0.22
type CORSPolicy struct {
// contains filtered or unexported fields
}
CORSPolicy is an EXACT-ORIGIN cross-origin policy for the HTTP API.
Exact means exact: an origin matches only if it is byte-equal (after normalisation) to a configured one. There is no wildcard, no suffix match, and no subdomain match. Suffix matching is the classic CORS bug — an allowlist of "example.com" matched by suffix also admits "evil-example.com" and "example.com.attacker.net" — and mecatl's HTTP API can start agent runs, so the cost of getting it wrong is not information disclosure but arbitrary action taken with the victim's credentials.
A nil *CORSPolicy is the DEFAULT and is a no-op: with no --cors-origins the middleware is not installed at all and responses are byte-identical to before this type existed.
This is the LOCAL-DEVELOPMENT path. The production browser path remains a same-origin BFF that injects bearer credentials server-side and enforces its own Origin/CSRF policy.
func NewCORSPolicy ¶ added in v0.0.22
func NewCORSPolicy(origins []string) (*CORSPolicy, error)
NewCORSPolicy validates and builds a policy from configured origins.
Validation is strict and happens at STARTUP, where the operator is present and the message is actionable. A malformed entry is refused rather than silently ignored: an ignored entry looks identical to a working one until a browser quietly fails, and the operator's mental model would be wrong in the unsafe direction.
func (*CORSPolicy) AllowedOrigins ¶ added in v0.0.22
func (p *CORSPolicy) AllowedOrigins() []string
AllowedOrigins returns the configured origins, sorted. It exists for startup logging and tests; the policy decision never walks this slice.
func (*CORSPolicy) Middleware ¶ added in v0.0.22
func (p *CORSPolicy) Middleware(next http.Handler) http.Handler
Middleware applies the policy to next.
IT MUST WRAP OUTSIDE THE AUTH MIDDLEWARE. A browser preflight is an unauthenticated OPTIONS request — the CORS specification forbids sending credentials on it — so a policy installed INSIDE auth would 401 every preflight and cross-origin access would never work at all. Wrapping outside is safe because a preflight is answered with headers only: it never reaches a handler, never touches a session, and never returns data.
type CapabilityReason ¶
type CapabilityReason string
CapabilityReason is a stable machine-readable explanation for a disabled inventory action.
const ( // CapabilityReasonInspectOnlyKind means the session kind is available for // inspection but cannot be driven through the public chat entry point. CapabilityReasonInspectOnlyKind CapabilityReason = "inspect_only_kind" // CapabilityReasonAwaitingApproval means the chat has an unresolved approval. CapabilityReasonAwaitingApproval CapabilityReason = "awaiting_approval" // CapabilityReasonActiveElsewhere means another live run currently owns the chat. CapabilityReasonActiveElsewhere CapabilityReason = "active_elsewhere" CapabilityReasonTranscriptUnavailable CapabilityReason = "transcript_unavailable" // CapabilityReasonStorageUnsupported means the configured store cannot perform the action. CapabilityReasonStorageUnsupported CapabilityReason = "storage_unsupported" // CapabilityReasonUnknown means the row cannot prove action eligibility. CapabilityReasonUnknown CapabilityReason = "unknown" )
type ClassificationEntry ¶
type ClassificationEntry struct {
Kind AccessKind
Rationale string
}
ClassificationEntry is one boundary's per-kind table row. Rationale is MANDATORY: a shared-infrastructure/exempt entry that cannot state a concrete, reviewable reason is rejected by validate, so an exemption can never become a silent caller-owned bypass (AC5.3).
type CleanupCandidate ¶
type CleanupCandidate struct {
ID session.SessionID
Kind session.SessionKind
State session.State
Reason string
ModifiedAt time.Time
EstimatedBytes int64
// contains filtered or unexported fields
}
CleanupCandidate is content-free dry-run metadata, ordered oldest-first.
type CleanupCounts ¶
type CleanupCounts struct {
Total int
ByKind map[string]int
ByState map[string]int
ByReason map[string]int
}
CleanupCounts reports bounded aggregate classification without content.
type CleanupItemError ¶
CleanupItemError is a stable sanitized partial failure.
type CleanupJob ¶
type CleanupJob struct {
ID string
State string
Processed int
Deleted int
Skipped int
Stale int
Failed int
Errors []CleanupItemError
}
CleanupJob is a caller-bound management projection.
type CleanupPlan ¶
type CleanupPlan struct {
Token string
JobID string
Available bool
Generation string
PolicyVersion string
Eligible []CleanupCandidate
EligibleCounts CleanupCounts
Protected CleanupCounts
EstimatedBytes int64
}
CleanupPlan is a read-only manual retention result.
type CleanupScope ¶
type CleanupScope struct {
Kinds []session.SessionKind
}
CleanupScope is the exact durable-kind subset a store-wide management plan covers.
type ClientMCPGrant ¶ added in v0.0.22
type ClientMCPGrant struct {
// contains filtered or unexported fields
}
ClientMCPGrant is a DECIDED client-MCP result: specs that have passed the shared classifier AND this deployment's policy gate. Only Service.ClientMCPFromWire mints a non-empty one, because specs is unexported — so the invariant is carried by the TYPE rather than by a doc comment asking callers to behave.
That matters because WithClientMCP and the CreateSession* entries are all exported: before this, any in-process caller (the scheduler, a future composition root, a later refactor of the ACP adapter) could construct the option from raw specs and bypass both the classifier and the gate. A ClientMCPGrant{} built outside this package is EMPTY, which is inert — the worst a bypass attempt achieves is a session with no client MCP, never an unvalidated mount.
func (ClientMCPGrant) IsEmpty ¶ added in v0.0.22
func (g ClientMCPGrant) IsEmpty() bool
IsEmpty reports whether the grant carries no servers — either because the request declared none, or because it is a zero value built outside this package.
type Clock ¶
Clock returns the current wall time. It defaults to time.Now when nil so the server can stamp session creation timestamps deterministically in tests.
type Command ¶
type Command struct {
// Name is the command's invocation name (without the leading "/").
Name string
// Description is a short, capped one-line summary for the palette.
Description string
}
Command is the surface-agnostic listing metadata for one slash command (name + short description), mirroring prompt.Command. The Service exposes its own type so wire adapters need not import the prompt domain package directly.
type CommandSourceBinding ¶ added in v0.0.41
type CommandSourceBinding interface {
prompt.CommandExpander
prompt.CommandLister
}
CommandSourceBinding supplies live listing and expansion from one resolved source.
type CommandSourceResolver ¶ added in v0.0.41
type CommandSourceResolver interface {
Borrow(context.Context, session.SessionID, *session.Principal, string) (CommandSourceBinding, func(), error)
Activate(context.Context, session.SessionID, *session.Principal, string) error
Retire(session.SessionID)
}
CommandSourceResolver owns per-session command source generations. Borrow returns an authoritative binding plus a mandatory release function; callers must release exactly once after all instruction/command/skill operations using that generation finish. Activate is the owner-authorized reload path and must create a fresh generation after retirement. Retire bars new borrows for only the current generation while already-borrowed engines drain.
type Config ¶
type Config struct {
// BuildID is the composed binary build identity exposed by GetServerInfo only.
BuildID string
// ServerImplementation is the stable composition family exposed by GetServerInfo.
// NewService admits only [a-z][a-z0-9-]{0,63}; invalid values report "unknown".
// It must not identify an instance, deployment, topology, configuration,
// capabilities, or authentication.
ServerImplementation string
// ProviderEndpoint returns the configured endpoint for a provider already known
// to the caller and composition. It must not perform discovery, session/store or
// config reads, or other side effects; GetServerInfo sanitizes its result before
// every response boundary. nil and unknown providers report unavailable.
ProviderEndpoint func(providerID string) string
// Engine is the shared agent engine that drives every run. Required.
Engine *agent.Engine
// DebugSessionEngine builds dedicated no-filesystem debug-session engines.
// Nil disables creation and makes persisted debug sessions fail closed at
// rehydration rather than falling back to Engine or SessionEngine.
DebugSessionEngine DebugSessionEngineFactory
// AgentDefSessionEngine builds the dedicated engine for a session bound to
// a named AgentDef (ADR 0353). Nil rejects a create naming
// agent_definition_name with ErrInvalidArgument, mirroring the
// DebugSessionEngine-nil posture. The composition root (internal/app)
// supplies it.
AgentDefSessionEngine AgentDefSessionEngineFactory
// DebugMCP reports whether the debug factory can currently borrow selected
// direct tools from the published direct MCP runtime. It is read on every
// capabilities request because the runtime can change after startup. Nil
// means unavailable.
DebugMCP func() bool
// Store persists and looks up sessions. Required.
Store port.SessionStore
// SessionCleared drops process-local state tied to a source session after a
// successful ClearSession successor publication. nil is inert.
SessionCleared func(session.SessionID)
// StorageManagementAuthorized gates process-wide storage health. A nil
// authorizer disables the management capability. It must be derived from the
// trusted request context, never request-supplied owner data.
StorageManagementAuthorized func(context.Context) bool
// LocalStorageMaintenanceSingleWriter is true only when composition has proved
// the store itself is private to this process (the in-process IsLive registry
// plus backend family locks are then sufficient). Management authorization is
// not such a proof. Any durable or otherwise shareable store must leave this
// false and wire a working SessionLease before destructive migration, cleanup,
// or automatic retention is advertised or run.
LocalStorageMaintenanceSingleWriter bool
// SessionLiveness carries process-local engine-owned child activity. Service's
// own runs map covers top-level runs; delegation children never enter that map,
// so destructive maintenance must consult both. Cross-process activity remains
// protected by SessionLease.
SessionLiveness port.SessionLiveness
// RetentionPolicy is the effective operator policy projected into health.
RetentionPolicy RetentionPolicy
// StorageMaintenanceStatus reports the shared retention/migration/cleanup lifecycle.
StorageMaintenanceStatus func() StorageMaintenanceStatus
// StorageMaintenanceUpdate receives sanitized lifecycle transitions. nil keeps
// maintenance APIs functional without process-wide health observability.
StorageMaintenanceUpdate func(StorageMaintenanceEvent)
// OwnershipEnforced is true only when the request edge has a verifier wired.
// Its zero value preserves the ownerless compatibility path. When enabled,
// create retries compare the verified issuer/subject pair before exposing an
// existing caller-selected ID, and the store must implement port.SessionCreator
// so no generated, forked, or scheduled session can overwrite an existing snapshot.
OwnershipEnforced bool
// ClientMCPOnCreate permits CLIENT-PROVIDED MCP servers on a session-creating
// API request (CreateSessionRequest.mcp_servers and its HTTP peer). It is a
// deployment/composition policy (listener-scoped authority), NOT an
// inference the server package makes from its own socket state.
//
// The zero value FAILS CLOSED: a Service built without an explicit grant
// refuses the field. That direction is deliberate — accepting an arbitrary
// outbound endpoint plus its auth headers from an API caller lends the server's
// ambient network authority to a remote principal, so a composition root that
// has not thought about it must not accidentally grant it. mecated derives it
// from listener topology (clientMCPOnCreateForListeners): permitted only on a
// UNIX-socket gRPC listener with HTTP disabled. An attacker-named endpoint
// carrying caller-supplied credentials lends greater ambient authority than
// ordinary loopback traffic.
//
// It gates the WIRE surface only. The in-process CreateSessionWithMCP /
// LoadSessionWithMCP entries are unaffected: their caller is the ACP adapter,
// which is a stdio peer of the operator's own editor and has no listener at
// all, so listener-derived policy is meaningless there.
//
// The SAME value drives the mcp_servers_on_create advertisement (FeatureScope),
// so a deployment cannot advertise what it will refuse.
ClientMCPOnCreate bool
// PlacementProvider is the deployment-owned atomic placement seam.
// Bind authorizes creation/successor choices, Reattach resolves only an exact
// persisted EnvironmentRef, and ListWorktrees issues source-scoped ephemeral
// selectors. app.Build always supplies the trusted local default; alternative
// composition may supply one provider that owns worktree or remote placements.
// It is mandatory.
PlacementProvider PlacementProvider
// PlacementScope is the trusted deployment scope supplied to every provider
// Bind. It must be non-empty when PlacementProvider is configured.
PlacementScope PlacementScope
// ExecutionTemplateAllowed is an operator-owned per-principal grant. A nil
// function denies all public template selection even if the shared provider
// mTLS client has a broader allowlist.
ExecutionTemplateAllowed func(*session.Principal, string, string) bool
// ExecutionAccess is an optional host-only run-ownership seam. Local and no-FS
// placements leave it nil and perform no lifecycle RPCs.
ExecutionAccess ExecutionAccess
// ReferenceIntents enables owner-safe reconciliation of provider-retained
// publication/deletion outcomes. Nil is fully inert.
ReferenceIntents ReferenceIntentLifecycle
// SessionReadLedger optionally selects a durable read-before-write ledger for
// each session independently of its placement's content backend. The returned
// handle must be non-nil; nil fails the run closed.
SessionReadLedger func(session.SessionID) tool.ReadLedger
// RootAuthority mints a complete authority set for a newly composed root.
// A nil callback preserves host-managed legacy sessions; app.Build always wires
// this callback with its assembled catalog. Carryover forks copy their source
// authority instead of invoking it.
RootAuthority func(session.SessionKind) session.Authority
// RootAuthorityForOperation mints authority from the runtime pinned in ctx for
// direct operations that build roots after their operation boundary.
RootAuthorityForOperation func(context.Context, session.SessionKind) session.Authority
ReviewDetails *ReviewDetailRegistry
// GuardrailCoverage projects the effective checker route and rules over the
// already-assembled, session-specific authority. Nil reports guardrails disabled.
GuardrailCoverage func(*session.Session) GuardrailCoverage
// DefaultMode is applied when a CreateSession request leaves mode
// unspecified. Defaults to session.ModeDefault when empty.
DefaultMode session.PermissionMode
// MaxAllowedMode is the server ceiling: the most-permissive mode sessions may
// enter. SetMode rejects a requested mode above this ceiling with ErrInvalidArgument.
// Empty means no ceiling (all modes reachable). Populated by the composition layer
// from Config.MaxAllowedMode via the permission-mode token.
MaxAllowedMode session.PermissionMode
// EnforcingCheckerConfigured reports whether a guardrails checker is configured
// in enforcing (not advisory) mode. Used by SetMode to gate entry into ModeAuto,
// which requires an enforcing checker. Set by the composition root from the
// resolved checker state at startup.
EnforcingCheckerConfigured bool
// DefaultLimits are the stop limits applied to a session created without
// explicit limits. Because a zero Limits value DISABLES every stop condition
// by design in package session, the composition root injects non-zero
// defaults here so a default session is always bounded. Per-field: a request
// that supplies any non-zero limit field is taken as explicit and used as-is.
DefaultLimits session.Limits
// Now supplies the creation timestamp; defaults to time.Now.
Now Clock
// AuthorizationTimer creates process-local expiry observations. It defaults to time.AfterFunc.
AuthorizationTimer AuthorizationTimerFactory
// NewID allocates session ids; defaults to a crypto-random hex generator.
NewID IDGenerator
// MCPProvider exposes the connected MCP servers' resources/prompts to the
// catalog-level inspection RPCs. Optional and nil-safe: when nil, the list
// RPCs return empty and the read/get RPCs return ErrNoMCPProvider.
MCPProvider mcp.Provider
// MCPSources is the startup inventory fallback used only when MCPStatus is nil.
// Production direct MCP composition supplies the reconciler's cached status.
MCPSources []source.SourceInfo
// MCPRefresh reconciles direct MCP sources and returns the exact immutable
// runtime snapshot considered by this request. It is nil when direct refresh
// is unavailable. Shared reconciliation outlives caller cancellation.
MCPRefresh func(ctx context.Context) (MCPRefreshSnapshot, error)
// MCPStatus returns the reconciler's cached publication/source status without
// consulting an upstream source. It is nil when direct MCP is unavailable.
MCPStatus func() MCPSourceStatus
// Commands owns source-only slash-command bindings for each session, backing
// ListCommands and the run-path expander. The resolver receives only the
// authoritative stored owner/profile; execution placement is not a command
// source. Optional and nil-safe: when nil (command expansion disabled, or no
// expander enumerates), ListCommands returns an empty list.
Commands CommandSourceResolver
// engine's policy collaborators were assembled for. Every filesystem-capable
// placement with a different composition root must use SessionEngine, including
// guest execution namespaces, custom environment kinds, and rootless shared deployments.
SharedEngineRoot string
// Agents is the resolved agent-definition snapshot taken at startup. It backs
// ListAgents and is a pure read of this snapshot (no live discovery). The
// composition root (internal/app) resolves the registry once and projects each
// def into the proto form (name/description/resolved model/effective read-only
// tool scope/permission mode/color) so the server adapter never imports the
// agents adapter. May be empty (agent definitions disabled or none found).
Agents []*mecatlv1.AgentInfo
// Models seeds the resolved selectable-model inventory projected by composition.
// It carries public ModelInfo metadata only and remains the compatibility path
// when ModelInventory is nil.
Models []*mecatlv1.ModelInfo
// ModelInventory is the read-only composition-owned models/status publication
// shared by wire responses, model-facing discovery and schedule validation.
// When supplied, compatibility setters do not write another local snapshot.
ModelInventory ModelInventory
// DefaultCapabilities is the NEUTRAL per-(default provider+default model) input
// capability — the catalog ∩ adapter INTERSECTION computed once in composition
// (internal/app modelCapability for the registry default + cfg.Model). It is the
// single source for BOTH the shared/default-engine session_capabilities echo
// (when a session uses no per-session engine) AND ProviderCapabilities() (the ACP
// gate). The server adapter holds only this neutral value — it never imports the
// catalog or registry. The zero value (text-only) is the safe default for a
// child/member service with no provider.
DefaultCapabilities port.ProviderCapabilities
// ResolveCapabilities returns the composition-owned capability intersection for
// an exact persisted provider/model pair. It lets GetSession remain accurate
// after process restart before the per-session engine is rebuilt. Nil preserves
// the default-only behavior for lightweight consumers and tests.
ResolveCapabilities func(providerID, modelID string, mode session.PermissionMode) port.ProviderCapabilities
// ResolveSessionModel returns the composition-resolved identity for persisted
// selector labels. GetSession uses it after restart before run entry rebuilds the
// per-session engine. It must be side-effect free; nil preserves the default-only
// behavior for lightweight consumers and tests.
ResolveSessionModel func(ProviderSelector, session.PermissionMode) ResolvedModel
// Posture is the SERVER-WIDE operator posture-ladder tier as a string
// ("strict"/"trusted"/"auto"/"yolo"), projected into the ServerCapabilities echo.
// It tracks the server ceiling (strict and trusted share the accept-edits
// ceiling), so a client uses it to bound which modes it may cycle to. It does
// not grant allow-all: that follows each session's permission MODE. It never
// changes per session.
// Empty (the zero value / an unconfigured child service) yields no badge. String
// passthrough — no enum on the wire (the EvNoProgress/StopBudget discipline).
Posture string
// ProjectTrusted is the effective project-trust decision for the launch
// workspace, projected into the ServerCapabilities echo as CHROME ONLY. nil
// (an unconfigured child service) leaves the echo unset.
ProjectTrusted *bool
// SubagentAskReviewer is the headless subagent ask reviewer state ("on",
// "off", "inert"), projected into the ServerCapabilities echo. nil (an
// unconfigured child service) leaves the echo unset.
SubagentAskReviewer *string
// DeploymentID is an optional, opaque, operator-set label for this deployment,
// surfaced on GetServerInfo. It is empty by default and is NEVER derived from
// hostname, pod name, or environment: infrastructure topology is not something
// an authenticated caller is owed, and a label the operator did not choose is a
// leak with no consenting author. Bounded and validated at the composition
// root (mecated --deployment-id), not here.
DeploymentID string
// DefaultResolvedModel is the EFFECTIVE provider+model the DEFAULT/shared engine
// resolved to (the registry default provider + cfg.Model + the default context
// window), computed once in composition. It is the single source for the
// resolved_model echo of a session that uses no per-session engine, the SAME
// composition-computed single-source discipline as DefaultCapabilities — the
// server holds only this value and never recomputes the resolution in a handler.
// The zero value (empty ids) is the safe default for a child/member service with
// no provider; a client maps it to a no-model-segment header.
DefaultResolvedModel ResolvedModel
// DefaultModelPending is true when the DEFAULT/shared engine booted with an
// UNRESOLVED default model (issue #262 review finding 1: the sole
// intent-driven — ToolHive gateway — provider probed down at Build, so
// cfg.Model stayed ""). It routes EVERY zero-selector session through the
// per-session engine factory (sessionNeedsPerFactory) and, for a session
// persisted before a restart into a still-down proxy, through rehydration
// (needsRehydration) too — so the model is resolved AT SESSION-BUILD TIME
// (resolve-at-use, mirroring the Deps.ContextWindow precedent, but at
// session granularity) instead of being frozen at the shared engine's
// Build-time construction. Without this, a post-boot heal
// (registry.healDefaultModel) updates the registry's resolved default but
// never reaches a zero-selector session, which keeps sending an empty
// model id to the provider (the R1.4 "no-restart" promise silently broken
// for the flagship sole-provider case). Static for the process lifetime
// (set once in composition from the SAME condition healDefaultModel guards
// on: an intent-driven default provider with no resolved model at Build);
// false everywhere else (a keyed default, or an operator-configured
// --model/--default-model) — byte-identical to today.
DefaultModelPending bool
// Skills is the resolved skills-inventory snapshot taken at startup. It backs
// ListSkills and is a pure read of this snapshot (no live discovery — skills
// are discovered once at build time and immutable for the process lifetime).
// The composition root (internal/app) discovers the skills once and projects
// each into the proto form (name + description); that PROJECTION (skillSnapshot)
// lives in internal/app, not here, so the server adapter holds only the proto
// snapshot and never reaches into the skills adapter's discovery types. May be
// empty (skills disabled or none found).
Skills []*mecatlv1.SkillInfo
// Soul is the resolved soul (persona) BUILD-TIME SNAPSHOT taken at startup. It
// backs GetSoul and is a pure read of this snapshot — the soul is selected once
// (USER-wins precedence, project trust gate, drift check) and is immutable for the
// process lifetime, so no live re-read is warranted. The composition root
// (internal/app) projects the winning soul's content + soulMeta into the proto form
// (soulSnapshot) so the server adapter never reaches into the soul adapter or the
// composition-layer soulMeta type. nil when no soul source is wired (--no-soul or
// none present); a nil Soul makes capabilities().Soul false and GetSoul return an
// empty (present=false) snapshot.
Soul *mecatlv1.SoulInfo
// UserModel lists the CURRENT user-model entries, backing GetUserModel. Unlike
// Soul (a startup snapshot) it is a LIVE lister: the composition root closes over
// the user-model store's Index so a refresh reflects entries saved since startup.
// It is the same seam idiom as Commands. Optional and nil-safe: when nil (user
// model disabled) capabilities().UserModel is false and GetUserModel returns empty.
UserModel UserModelLister
// ReflectSession enables explicit completed-session reflection independently of
// automatic learning mode. Attempts expose only content-free lifecycle
// projections from the verified caller's private partition. Proposals and the
// mutation callbacks expose the bounded, caller-partitioned staged-learning
// review surface.
ReflectSession ExplicitReflector
Attempts learning.AttemptRepository
AttemptPrincipal func(*session.Principal) string
Proposals learning.ProposalRepository
ProposalManifest ProposalManifestLoader
ProposalPrincipal func(*session.Principal) string
PromoteProposal ProposalPromoter
UndoProposal ProposalUndoer
ProjectPromotionAllowed func(project string) bool
ProposalActionAvailable func(project string) (bool, string)
// DreamReviewer is the transport-neutral, process-local manual consolidation
// coordinator. DreamCapabilities is the composition-computed availability
// snapshot for the exact Build-owned project-memory and user-model stores. Both
// zero values keep manual dreaming unavailable.
DreamReviewer DreamReviewer
DreamCapabilities DreamCapabilities
// LearnedSkills exposes caller-partitioned, agent-owned lifecycle records. The
// publisher atomically refreshes the shared live Skill catalog after mutations.
LearnedSkills learning.SkillRepository
PublishLearnedSkills func(context.Context, learning.SkillPartition) error
BeginSkillPublication func(learning.SkillPartition) func()
LiveSkillGeneration func(learning.SkillPartition) uint64
SkillActionAvailable func(learning.SkillPartition, string) (bool, string)
LearnedSkillNameAvailable func(string) bool
LiveSkills func(context.Context) []*mecatlv1.SkillInfo
// SkillSourceFor returns the read-only skill source for the caller's skill view, the
// view LiveSkills lists. It backs ListSkillFiles and ReadSkillFile. Nil, or a nil
// result, means skills are disabled.
SkillSourceFor func(context.Context) tool.SkillSource
// TitleGenerationEligible is the composition-resolved eligibility check for
// server-owned automatic title generation. Nil and false keep the durable
// lifecycle disabled; true persists pending at session creation. It receives
// only the neutral fixed session selector, never registry or credential access.
TitleGenerationEligible func(ProviderSelector) bool
// TitleGenerator is the optional Build-owned, server-private title call. When
// absent automatic work is unavailable; it never receives session authority.
TitleGenerator SessionTitleGenerator
// TitleGeneratorForSession resolves a title generator for the session's fixed
// provider selector. It takes precedence over TitleGenerator when present.
TitleGeneratorForSession func(ProviderSelector) SessionTitleGenerator
// SessionEngine builds a PER-SESSION engine over a non-default provider/model
// selector AND/OR client-provided streaming-HTTP MCP servers (the ACP
// session/new mcpServers). It is the seam that lets a session bind its OWN
// provider/model or mount its OWN MCP tools without leaking them (or the
// provider registry) into the shared Engine every other session uses. When nil,
// a non-default selector or non-empty MCP specs are rejected with
// ErrInvalidArgument; a session with the zero selector and no client MCP always
// uses the shared Engine (zero overhead). The composition root (internal/app)
// supplies it.
SessionEngine SessionEngineFactory
// SessionEngineWithTools is required when MCPBroker is wired. It receives the
// exact wrappers owned by the local broker attachment.
SessionEngineWithTools SessionEngineWithToolsFactory
// SessionContextEngine derives the engine from authoritative stored source scope.
// It is composition-only; client input never selects a source context.
SessionContextEngine SessionContextEngineFactory
// MCPBroker owns logical broker state; Service owns only local attachments.
MCPBroker brokercontract.Service
// IdentityBroker is the agent identity broker, or nil when it is not
// enabled. With it set, every root session with an owner has a broker
// session; see openIdentityBrokerSession.
IdentityBroker identitybroker.Service
// MCPConnectorInspector exposes local-only inventory for the bundled broker.
MCPConnectorInspector brokercontract.ConnectorInspector
// WorkspaceEnrollment advertises the optional pre-prompt enrollment capability.
// It must be true only when MCPBroker attachments implement the enrollment boundary.
WorkspaceEnrollment bool
// ModeNeedsEngine reports whether a given session PermissionMode resolves a model
// that DIFFERS from the shared engine's model — i.e. whether a
// plan slot is configured and active. It is the composition-injected predicate that
// lets a DEFAULT-FS session (which normally rides the shared engine, zero overhead)
// be PROMOTED to a per-session factory engine when its mode would change the model.
// The Service never resolves a model itself; it asks this predicate.
//
// When nil (no plan slot configured) a default-FS session is NEVER promoted
// (a mode flip changes nothing, the shared engine is unchanged). This is the
// regression-guard seam: composition wires it ONLY when a plan slot is active.
ModeNeedsEngine func(mode session.PermissionMode) bool
// OperationPin pins one immutable direct-MCP runtime for a root run. The
// returned context carries the generation into composition factories and child
// engines; release is called only when the run registry settles. Nil disables
// runtime publication integration.
OperationPin func(context.Context) (context.Context, func(), error)
// OperationRevision reads the revision carried by OperationPin. Shared and
// cached engines are rebuilt before use when their tag differs.
OperationRevision func(context.Context) (uint64, bool)
SharedEngineRevision uint64
// MemberEngine builds a team member's Engine from the shared team and the
// member spec (see engine/agent.MemberEngine). It is the seam that wires
// the agent-team RPCs: when nil, those RPCs return ErrTeamsDisabled. The
// composition root supplies it (internal/app), capturing the per-member
// catalog (read-only base + MemberTools, plus mutating tools only for a
// Mutating member) and the provider/model.
MemberEngine MemberEngineFactory
// MemberEngineForOperation resolves the direct RunTeam member factory from the
// operation-pinned context acquired at RunTeam. Nil uses MemberEngine.
MemberEngineForOperation func(context.Context) MemberEngineFactory
// TeamGoalUntrusted, when true, re-fences the gRPC/HTTP CreateTeam goal as
// UNTRUSTED data in member and synthesis prompts (threaded to
// agent.WithUntrustedGoal). DEFAULT false: the goal is the team's TRUSTED
// top-level instruction (its provenance is the deployment/operator that owns the
// gRPC front door, not a peer — peer messages and task descriptions stay fenced
// regardless). A multi-tenant / relay deployment that interpolates untrusted
// end-user text into the goal should set this true so the goal is fenced as data.
// It is a composition decision (the deployment knows the goal's provenance); the
// supervisor only takes the bool.
TeamGoalUntrusted bool
// TeamTokenBudget is the team-wide cumulative token budget threaded into every
// CreateTeam supervisor (agent.WithTeamTokenBudget). 0 disables. The per-request
// proto knob is deferred.
TeamTokenBudget int
// Forker isolates a Mutating team member's workspace (force-copy: own `.git`).
// Optional; required only if a Mutating member is spawned.
Forker tool.EnvironmentForker
// ReadOnlyForker isolates a read-only-isolated team member's workspace as a cheap
// git worktree (shares the base repo's `.git` ⇒ full history) so an inspect-only
// member can run a shell (git log/show, build, test) confined to a throwaway
// checkout. Optional; required only if the member factory marks any read-only
// member IsolateReadOnly (which the composition root does only when this is
// wired). When nil, read-only members base-share with no shell.
ReadOnlyForker tool.EnvironmentForker
// read-only member (the no-shell fallback tier) so it never inherits a relaxed
// base's out-of-root reach (the path-escape-posture Scenario 5 boundary —
// threaded to agent.WithTeamSharedBaseWorkspace). The composition root wires it
// whenever the Workspaces factory may return a relaxed workspace (auto/yolo).
// Optional; nil shares the base verbatim.
SharedBaseWorkspace func(tool.Workspace) tool.Workspace
// TeamHooks fires the team lifecycle hooks (TeammateIdle) and is passed to
// member coordination tools for the TaskCreated / TaskCompleted gates.
// Optional.
TeamHooks port.HookRunner
// MaxTeams caps the number of live (un-cleaned) teams the registry holds at
// once, bounding the leak when clients create teams but never CleanupTeam.
// CreateTeam returns ErrTooManyTeams (ResourceExhausted) when the cap is
// reached; cleaning up a created/done team frees a slot. Defaults to
// defaultMaxTeams when zero.
MaxTeams int
// MaxSessionEngines caps the number of live (un-released) PER-SESSION engines
// the registry holds at once (CWE-770). A per-session engine is registered when
// a session needs a non-default provider/model selector OR client-provided MCP
// servers. The ACP surface drains them on editor disconnect, but the gRPC/HTTP
// surfaces have no teardown signal, so without a cap a hostile authed client
// could call CreateSession with a valid provider_id repeatedly (never closing)
// and grow the map unbounded. createSession returns ErrTooManySessionEngines
// (ResourceExhausted) when the cap is reached; CloseSession / EndSession frees a
// slot. It is a generous count (a session is multi-turn and its engine MUST
// persist across turns, so this is NOT terminal-state eviction). Defaults to
// defaultMaxSessionEngines when zero.
MaxSessionEngines int
// OnCloseSession, when non-nil, is invoked by CloseSession with the closing
// session id BEFORE the per-session engine teardown. It is the composition
// seam for releasing session-scoped state the Service does not own — currently
// the per-session LEARNED permission rules (issue #3), evicted via
// permstore.Memory.Forget so they do not outlive the session. Optional and
// nil-safe.
OnCloseSession func(session.SessionID)
// EventLog durably records the relay-side event projection per session.
// Relays observe every event, including the
// drain-to-discard tail, while their run-scoped recorders coalesce streaming
// text deltas before Append; the loop itself stays storage-agnostic (it only
// emits). Optional and nil-safe: when nil the relay records nothing
// (byte-identical to the pre-3a behaviour). The composition root wires the
// durable jsonlstore Store (which also implements EventLog) or an in-memory
// sibling when no store dir is configured.
EventLog port.EventLog
// Diagnostics is the operational logging sink the relay uses to WARN once per
// recorder after EventLog.Append failures (a best-effort durable log must not
// break the live stream). Optional and nil-safe: when nil, Append failures are
// silently tolerated (the durability gap is the only effect). The composition
// root supplies the same sink the rest of the build uses.
Diagnostics port.Diagnostics
// SessionLoadFailureMetric records one bounded class for each non-not-found
// GetSession load failure under ownership enforcement. It receives no target,
// principal, locator, cause, blob, or size. Optional and nil-safe; diagnostics
// remain enabled when this callback is nil.
SessionLoadFailureMetric func(port.SessionLoadFailureClass)
// ReplayApprovals repopulates the in-memory learned-rule store (permstore) for a
// loaded session from its durable EventLog allow-always verdicts. The permstore
// is in-memory and lost on restart, so without this a previously allow-always'd
// tool would re-ask after a process restart. The composition root (internal/app)
// supplies the closure — it owns BOTH the EventLog and the Policy.Learn seam, so
// it reads the verdicts, correlates each allow-always askID back to its ToolCall
// in the loaded conversation (the askID encodes the call id; see agent.newAskID),
// and re-Learns the reconstructed rule. Keeping the correlation in composition
// keeps the EventLog event METADATA-ONLY (no raw args on the wire) while the real
// rule is rebuilt from history the session already carries (no leak).
//
// The Service invokes it from loadAndReopen (the single run-entry funnel) AT MOST
// ONCE per session id per process: a freshly-created in-memory session learns
// live, so it never needs a replay, and a re-run of an already-replayed session
// would only re-derive idempotent rules. Optional and nil-safe: when nil (no
// store, or replay not wired) loadAndReopen does nothing extra.
ReplayApprovals func(ctx context.Context, sess *session.Session)
// ResolveContextWindow is THE live-first context-window resolver injected by
// composition (the SAME reg.windowResolver the engine reads via Deps.ContextWindow,
// wrapped to int64: override→live→catalog→128k floor). Service.ResolvedModel
// consults it for BOTH the default-session and the per-session-engine branch, so
// the wire echo is byte-identical to the engine's resolve-at-use window. nil keeps
// the baked DefaultResolvedModel.ContextWindow verbatim — the memstore/driver/test
// paths. Only the ContextWindow scalar is resolved; provider/model identity never
// recomputes.
ResolveContextWindow func(providerID, modelID string) int64
// AwaitContextWindow blocks run admission until composition can safely resolve
// the effective provider/model window. Nil preserves compatibility for embedders.
AwaitContextWindow func(context.Context, string, string) error
// SessionLease is the OPTIONAL cross-process single-writer seam. When wired, the run-entry funnel acquires a per-session
// lease (AFTER the same-process runEntryMu, so same-process exclusion stays
// cheap) before driving the engine, refreshes it from a Service-owned renewer
// goroutine, and releases it on CloseSession / shutdown. A competing process
// holding the lease makes StartRunContent / resumeFromAwaiting fail with
// ErrSessionLeasedElsewhere. Optional and nil-safe: when nil there is NO
// acquire, NO renewer, and NO release — the single-writer-by-affinity
// posture. The loop NEVER imports port.SessionLease;
// the renewer and the held-lease registry live entirely on Service (the same
// storage-agnostic discipline as EventLog). A backend that reports
// ErrLeaseUnsupported is stickily disabled (one INFO, then the no-lease path).
SessionLease port.SessionLease
// MutationCapability is the process-local admission gate shared by Service
// and the engine's guarded persistence/recorder adapters. Composition supplies
// one instance to both. When nil, Service creates the matching local gate;
// no-lease and unsupported-lease paths remain pass-through.
MutationCapability *SessionMutationCapability
// LeaseOwner is this process's owner-identity string for SessionLease, built
// once per Build (e.g. "<hostname>-<pid>-<nonce>") so two Builds in one
// process get distinct owners. Ignored when SessionLease is nil.
LeaseOwner string
// LeaseTTL is the lease lifetime requested at Acquire and the renew window;
// the renewer ticks at LeaseRenewInterval (default LeaseTTL/3). A non-positive
// value defaults to defaultLeaseTTL. Ignored when SessionLease is nil.
LeaseTTL time.Duration
// LeaseRenewInterval is how often the renewer refreshes a held lease. A
// non-positive value defaults to LeaseTTL/3. Ignored when SessionLease is nil.
LeaseRenewInterval time.Duration
// Scheduler is the OPTIONAL in-process scheduled-tasks tick loop (issue #189).
// When wired, NewService stores it on the Service so Close drains it
// (Stop cancels the tick loop + joins in-flight fires) and Drain arms its drain
// gate (no new fires mid-tick during shutdown). The scheduler is STARTED by
// composition (app.Build) AFTER NewService — its FireFunc closes over the
// Service, so Build calls SetFire then Start; NewService does NOT start it.
// nil = no scheduling (the byte-identical default).
//
// NOTE: this field is the LEGACY late-attach path. The schedule surface now
// lives on the store-shaped scheduleManager — see ScheduleManager
// below. NewService still seeds the Service's manager-side scheduler reference
// from this field for byte-identical Close/Drain; composition attaches the
// scheduler via SetScheduler (delegated to the manager) AFTER NewService.
Scheduler *scheduler.Scheduler
// ScheduleManager is the pre-Service store-shaped schedule manager:
// the validated create/read/update/fire seam constructed BEFORE buildEngine
// from the store + now-func, with the scheduler / model-inventory as
// late-bound atomic fields. When non-nil, the Service delegates its nine
// port.ScheduleManager methods + EmitScheduleEvent + GetFire to it — the RPC
// surface is byte-identical. When nil, the Service self-constructs one from
// Store (the legacy test path + any caller that does not pre-construct); a
// store that backs no ScheduleStore yields a nil manager (the honest
// no-scheduling path). Composition (app.Build) constructs the manager from
// the store before buildEngine and hands it here — the SAME manager its
// shared catalog's Schedule tool factory resolves (one manager, one
// truth). The field is the CONCRETE *scheduleManager (exposed to
// composition as the ScheduleManagerImpl alias) so the typed-nil
// discipline holds end-to-end: a store with no ScheduleStore yields an
// untyped nil here, never a non-nil interface boxing a nil pointer.
ScheduleManager *scheduleManager
// PlanModeAutoApprove is the OPT-IN, OPERATOR-TIER-ONLY, DEFAULT-OFF flag that
// auto-approves a plan-mode PresentPlan ask when the run ends without a human
// operator. It is a deliberate autonomous-approval capability — an operator
// deployment decision, NEVER load-bearing for safety. When true AND the engine
// is headless (no interactive client attached), the Service auto-resolves a
// parked plan-approval ask via the EXISTING ApprovePlan path (ModeDefault + a
// loud note). It does NOT fire when interactive (a human can approve), NOT in
// non-plan modes, NOT for non-plan asks. DEFAULT false (the existing safe
// default: headless plan ask is auto-denied by the engine). Composition
// (internal/app) sets this from Config.PlanModeAutoApprove; the cmd mains wire
// the --plan-mode-auto-approve flag.
PlanModeAutoApprove bool
// Interactive reports whether a HUMAN approver is attached to the main engine's
// runs (a live Converse / HTTP-SSE client that can answer a permission ask).
// It mirrors app.Config.Interactive (threaded onto the engine's Deps.Interactive)
// and gates the PlanModeAutoApprove observer: an interactive deployment NEVER
// auto-approves (the human answers). DEFAULT false (fail-safe: the observer
// treats the deployment as headless).
Interactive bool
}
Config wires the Service's collaborators and resolved composition values.
type CreateSessionOption ¶
type CreateSessionOption func(*createSessionOpts)
CreateSessionOption is a variadic option applied to a CreateSession* call (the Go options idiom — NOT a method-signature widening). The only option today is WithSessionID, which lets a caller (the scheduler fire path) mint a session under a CALLER-chosen id instead of the Service's NewID generator. Unknown options from future callers are a no-op.
func WithAgentDefinitionName ¶ added in v0.0.49
func WithAgentDefinitionName(name string) CreateSessionOption
WithAgentDefinitionName persists a root's named AgentDef binding (ADR 0353). The dedicated factory resolves the name and provider/model, builds the restricted catalog, and clamps limits and permission mode. Empty uses the ordinary path.
func WithClientMCP ¶ added in v0.0.22
func WithClientMCP(grant ClientMCPGrant) CreateSessionOption
WithClientMCP mounts client-provided streaming-HTTP MCP servers for the new session's lifetime, via a per-session engine (which requires Config.SessionEngine, else ErrInvalidArgument).
It takes a ClientMCPGrant, not raw specs: the grant is unforgeable outside this package, so "validated and policy-checked" is a type-level fact rather than a convention. This option does not validate and must not — one classifier, one gate, at the wire seam.
It also arms the ALL-OR-NOTHING mount requirement (clientMCPStrict): every requested server must actually connect or the create fails. That is the wire contract, and this option is the wire's only entry, so the two travel together rather than as a separate flag a handler could forget. The ACP path (CreateSessionWithMCP) deliberately does not come through here and keeps composition's best-effort behaviour.
An EMPTY grant is a no-op: it arms nothing, so a caller that passes a zero value gets the ordinary shared-engine create rather than a strict-mode session with nothing to mount.
func WithDebugMCP ¶ added in v0.0.22
func WithDebugMCP(names []string) CreateSessionOption
WithDebugMCP selects already-configured server-global MCP servers for a debug session. Names are validated at the create boundary and no connection details cross this seam.
func WithDebugTarget ¶ added in v0.0.22
func WithDebugTarget(id session.SessionID) CreateSessionOption
WithDebugTarget creates a dedicated debug session bound to id. The target is authorized through the ordinary absence-shaped ownership seam and is only loaded for validation; its state and conversation are never changed or copied.
func WithExecutionSelection ¶ added in v0.0.48
func WithExecutionSelection(e ExecutionSelection) CreateSessionOption
WithExecutionSelection carries a validated public selection to atomic Bind.
func WithOwner ¶
func WithOwner(p *session.Principal) CreateSessionOption
WithOwner overrides the owner a CreateSession* call stamps on the new session. By DEFAULT the owner comes from the verified principal on the context (session.PrincipalFromContext) — a caller can never name its own owner in the request body, which is why CreateSessionRequest has no owner field. This option is the in-process injection seam for a caller that already holds the owning principal out of band: the scheduler fire path, which runs under the system principal but must attribute the fire session to the SCHEDULE's captured owner.
WithOwner(nil) is the EXPLICIT ownerless injection (a system-owned session with nobody to attribute it to) and does NOT fall back to the context principal — a fabricated owner is worse than none.
func WithPlacementBinding ¶ added in v0.0.24
func WithPlacementBinding(binding PlacementBinding) CreateSessionOption
WithPlacementBinding supplies a trusted exact binding already reauthorized by composition. It is intended for scheduled fire only; public transports cannot construct or select it.
func WithScheduledRelationship ¶
func WithScheduledRelationship(scheduleName string, origin session.SessionID) CreateSessionOption
WithScheduledRelationship is the trusted composition-only creation seam for scheduler fires. No public request field maps to this option.
func WithSessionID ¶
func WithSessionID(id session.SessionID) CreateSessionOption
WithSessionID overrides the session id a CreateSession* call mints. When set, the id MUST be non-empty and MUST NOT collide with a live per-session engine (the sessionEngines map); a collision is rejected with ErrInvalidArgument. An empty id is rejected. When no WithSessionID option is passed, the existing NewID path is byte-identical. It is the seam the scheduler fire path uses to mint "sched--"-prefixed fire-session ids.
func WithSourceSession ¶
func WithSourceSession(id session.SessionID) CreateSessionOption
WithSourceSession seeds a NEW session's conversation history from the named source session (issue #20: model-switch context carryover). The source is loaded through the run-entry funnel (loadAndReopen recovers terminal states to idle), snapshotted via session.ForkSnapshot (a deep copy with trailing unanswered tool calls stripped), and seeded into the new session BEFORE its first Store.Save via session.SeedHistory. Carryover is ALWAYS allowed across providers: a SAME-provider carryover replays the history verbatim (blobs intact, warm cache); a CROSS-provider carryover seeds a provider-neutral copy (session.StripProviderState clears Reasoning/ProviderPhase/ItemID). A source that is still running/awaiting is rejected with ErrFailedPrecondition. Empty (no option) is the byte-identical no-carryover path.
type DebugSessionEngineFactory ¶ added in v0.0.22
type DebugSessionEngineFactory func(ctx context.Context, sel ProviderSelector, profile SessionProfile, mode session.PermissionMode, target session.SessionID, targetFingerprint string, targetOwner *session.Principal, selectedServers, toolCeiling []string) (SessionEngineResult, error)
DebugSessionEngineFactory builds the dedicated engine for a debug session. targetFingerprint and targetOwner bind every evidence/MCP read to the exact authorized target incarnation; neither may be projected to the model or wire.
type DreamCapabilities ¶
type DreamCapabilities struct {
Generate bool
Decide bool
Targets map[DreamTarget]DreamTargetCapability
}
DreamCapabilities is the honest process-wide manual-review capability snapshot. Reasons are fixed operator-facing categories and never contain memory or provider content.
type DreamDecision ¶
type DreamDecision string
DreamDecision is the complete manual-plan decision vocabulary.
const ( // DreamDecisionApply applies the exact retained authoritative plan. DreamDecisionApply DreamDecision = "apply" // DreamDecisionDismiss retires the plan without mutating memory. DreamDecisionDismiss DreamDecision = "dismiss" )
type DreamOperation ¶
type DreamOperation struct {
Kind string
Survivor DreamParticipant
Sources []DreamParticipant
Replacement DreamReplacement
Reason string
ExactDuplicateEligible bool
}
DreamOperation is one ordered operation. It deliberately contains no versions, paths, provider/model identity, or caller-supplied target information.
type DreamParticipant ¶
DreamParticipant is reviewable memory content for one survivor or source.
type DreamReceipt ¶
type DreamReceipt struct {
ID string
Target DreamTarget
Disposition DreamDecision
Planned int
Applied int
Conflicted int
Skipped int
Failed int
}
DreamReceipt reports source counts supplied by the core dream.Report.
type DreamReplacement ¶
DreamReplacement is the proposed survivor content after synthesis.
type DreamReview ¶
type DreamReview struct {
ID string
Target DreamTarget
ExpiresAt time.Time
Operations []DreamOperation
PlannedOperations int
PlannedSourceCount int
}
DreamReview is the detached review projection returned by generation.
type DreamReviewer ¶
type DreamReviewer interface {
Generate(context.Context, DreamTarget) (DreamReview, error)
Decide(context.Context, string, DreamDecision) (DreamReceipt, error)
}
DreamReviewer owns process-local plan retention and whole-plan decisions.
type DreamTarget ¶
type DreamTarget string
DreamTarget is a closed, transport-neutral manual-consolidation target.
const ( // DreamTargetProjectMemory selects the Build-owned project-memory store. DreamTargetProjectMemory DreamTarget = "project_memory" // DreamTargetUserModel selects the Build-owned cross-project user-model store. DreamTargetUserModel DreamTarget = "user_model" )
type DreamTargetCapability ¶
DreamTargetCapability describes one exact Build-owned target.
type ExecutionAccess ¶ added in v0.0.42
type ExecutionAccess interface {
Applies(session.EnvironmentRef) bool
AcquireRun(context.Context, ExecutionRunRequest) (ExecutionRunHandle, error)
}
type ExecutionRunHandle ¶ added in v0.0.42
type ExecutionRunRequest ¶ added in v0.0.42
type ExecutionSelection ¶ added in v0.0.48
type ExecutionSelection struct {
Kind PlacementSelectorKind
ID, Revision string
}
ExecutionSelection is the public create choice. The zero value selects the deployment default; none never allocates an execution environment.
type ExecutionTemplateCatalog ¶ added in v0.0.48
type ExecutionTemplateCatalog interface {
ListExecutionTemplates(context.Context, *session.Principal) ([]ExecutionTemplateInfo, string, error)
}
ExecutionTemplateCatalog is optional and must enumerate only operator-authorized revisions for this deployment. The host requires a verified owner before use; Bind reauthorizes the exact revision for that owner.
type ExecutionTemplateInfo ¶ added in v0.0.48
type ExecutionTemplateInfo struct {
ID, Revision, Name, Description, DisplayToken string
Extensions map[string]string
DeclaredExecutionFiles, DeclaredBuiltInShell bool
}
ExecutionTemplateInfo is bounded inert display metadata, never an execution recipe.
type ExecutionWorkspaceAcquirer ¶ added in v0.0.41
ExecutionWorkspaceAcquirer lazily borrows the exact server-authorized session workspace as a source-only capability. The caller owns the returned release.
type ExplicitReflector ¶
ExplicitReflector submits one caller-owned completed session for reflection.
type FeatureScope ¶ added in v0.0.22
type FeatureScope struct {
// ExactPlanAskControl requires durable failure recording for accepted
// server-owned plan continuations.
ExactPlanAskControl bool
// ClientMCPOnCreate reports whether this deployment accepts
// CreateSessionRequest.mcp_servers.
ClientMCPOnCreate bool
// SessionActivityInventory reports whether ListSessions reads an atomic,
// activity-projecting metadata pager.
SessionActivityInventory bool
}
FeatureScope is what the DEPLOYMENT permits, as distinct from what the build implements. It combines composition policy and wired storage capabilities; neither is inferred from a request's socket state.
One *Service backs both the gRPC and HTTP listeners, so each scope value is shared by both compatibility transports.
type ForkSuccessorRequest ¶ added in v0.0.24
type ForkSuccessorRequest struct {
Source session.SessionID
Placement SuccessorPlacement
Title string
ProviderID string
ModelID string
ReasoningEffort string
}
ForkSuccessorRequest is the additive internal successor shape used before the public contract cutover.
type GuardrailCoverage ¶ added in v0.0.41
type GuardrailCoverage struct {
Enabled bool
CheckerProviderID, CheckerModelID string
Entries []GuardrailCoverageEntry
}
GuardrailCoverage is the composition-owned effective checker projection for one session.
type GuardrailCoverageEntry ¶ added in v0.0.41
type GuardrailCoverageEntry struct {
Tool, Phase, Job, Mode, RuleID, RuleOrigin, Inspection, Reason string
}
GuardrailCoverageEntry describes one effective tool-direction rule.
type GuardrailReviewDetail ¶ added in v0.0.41
type GuardrailReviewDetail struct {
ReviewID, Concern, SourceDisplay, NextAction string
}
GuardrailReviewDetail is bounded live-only human display data.
type HTTPHandler ¶
type HTTPHandler struct {
// contains filtered or unexported fields
}
HTTPHandler is the HTTP/SSE adapter over the shared Service. It serves the thin REST surface from ARCHITECTURE §7.2:
POST /v1/sessions -> CreateSession (JSON)
GET /v1/sessions/{id} -> GetSession (JSON snapshot)
DELETE /v1/sessions/{id} -> CloseSession (release session resources; 204)
POST /v1/sessions/{id}/rename -> RenameSession (persist an explicit title)
POST /v1/sessions/{id}/delete -> DeleteSession (physical snapshot + sidecars)
POST /v1/sessions/{id}/compact -> CompactSession (bodyless manual compaction)
GET /v1/sessions/{id}/mcp-authorizations/{authorization_id}/presentation -> live browser URL
POST /v1/sessions/{id}/mcp-authorizations/{authorization_id}/recheck -> status/continuation SSE
POST /v1/sessions/{id}/mcp-authorizations/{authorization_id}/cancel -> cancellation/continuation SSE
POST /v1/sessions/{id}/workspace-enrollment/connect -> begin or observe workspace enrollment
POST /v1/sessions/{id}/workspace-enrollment/{enrollment_id}/retry -> replace one exact enrollment
POST /v1/sessions/{id}/workspace-enrollment/{enrollment_id}/cancel -> cancel one exact enrollment
POST /v1/sessions/{id}/prompt -> start a run; text/event-stream of Events
POST /v1/sessions/{id}/controls/resolve-ask -> resolve an ask on one exact run
POST /v1/sessions/{id}/controls/cancel -> cancel one exact run
POST /v1/sessions/{id}/cancel-child -> cancel ONE child (subagent) of the run
POST /v1/sessions/{id}/controls/steer -> steer one exact run
POST /v1/sessions/{id}/controls/cancel-steer -> retract a steer on one exact run
POST /v1/sessions/{id}/fork -> ForkSession (peer session from a history snapshot; 201)
GET /v1/sessions/{id}/events -> replay the durable event log; the stream ENDS
GET /v1/sessions/{id}/watch -> durable replay-then-follow; the stream STAYS OPEN
Every Event is emitted as one SSE `data:` line carrying the proto Event marshalled to JSON, so the HTTP and gRPC surfaces share one event shape.
func NewHTTPHandler ¶
func NewHTTPHandler(svc *Service) *HTTPHandler
NewHTTPHandler constructs an HTTPHandler over svc. The returned value is an http.Handler ready to mount.
func (*HTTPHandler) ServeHTTP ¶
func (h *HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP routes to the registered handlers.
type HarnessServer ¶
type HarnessServer struct {
mecatlv1.UnimplementedHarnessServiceServer
// contains filtered or unexported fields
}
HarnessServer implements the generated mecatlv1.HarnessServiceServer over the shared Service. It is the primary (gRPC) surface; the HTTP/SSE adapter wraps the same Service.
func NewHarnessServer ¶
func NewHarnessServer(svc *Service) *HarnessServer
NewHarnessServer constructs a HarnessServer over svc.
func (*HarnessServer) AbandonLearningAttempt ¶ added in v0.0.24
func (h *HarnessServer) AbandonLearningAttempt(ctx context.Context, req *mecatlv1.MutateLearningAttemptRequest) (*mecatlv1.MutateLearningAttemptResponse, error)
AbandonLearningAttempt abandons only the attempt; it performs no compensation.
func (*HarnessServer) ActivateLearnedSkill ¶
func (h *HarnessServer) ActivateLearnedSkill(ctx context.Context, req *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*HarnessServer) ApplySessionCleanup ¶
func (h *HarnessServer) ApplySessionCleanup(ctx context.Context, req *mecatlv1.ApplySessionCleanupRequest) (*mecatlv1.CleanupJob, error)
func (*HarnessServer) ApprovePlan ¶
func (h *HarnessServer) ApprovePlan(req *mecatlv1.ApprovePlanRequest, stream mecatlv1.HarnessService_ApprovePlanServer) error
ApprovePlan atomically resolves a parked plan-approval ask and — on an allow verdict — streams the resumed run's AND the continuation run's events on one response stream. See Service.ApprovePlan for the contract.
func (*HarnessServer) ArchiveLearnedSkill ¶
func (h *HarnessServer) ArchiveLearnedSkill(ctx context.Context, req *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*HarnessServer) CancelMcpAuthorization ¶ added in v0.0.26
func (h *HarnessServer) CancelMcpAuthorization(stream grpc.BidiStreamingServer[mecatlv1.CancelMcpAuthorizationRequest, mecatlv1.CancelMcpAuthorizationResponse]) error
func (*HarnessServer) CancelRun ¶ added in v0.0.39
func (h *HarnessServer) CancelRun(ctx context.Context, req *mecatlv1.CancelRunRequest) (*mecatlv1.CancelRunResponse, error)
CancelRun cancels the exact addressed live run.
func (*HarnessServer) CancelRunSteer ¶ added in v0.0.39
func (h *HarnessServer) CancelRunSteer(ctx context.Context, req *mecatlv1.CancelRunSteerRequest) (*mecatlv1.CancelRunSteerResponse, error)
CancelRunSteer retracts pending steering from the exact addressed live run.
func (*HarnessServer) CancelSessionCleanup ¶
func (h *HarnessServer) CancelSessionCleanup(ctx context.Context, req *mecatlv1.CancelSessionCleanupRequest) (*mecatlv1.CleanupJob, error)
func (*HarnessServer) CancelTeammate ¶
func (h *HarnessServer) CancelTeammate(ctx context.Context, req *mecatlv1.CancelTeammateRequest) (*mecatlv1.CancelTeammateResponse, error)
CancelTeammate cancels one member of a running team (issue #29).
func (*HarnessServer) CancelWorkspaceEnrollment ¶ added in v0.0.26
func (h *HarnessServer) CancelWorkspaceEnrollment(ctx context.Context, req *mecatlv1.WorkspaceEnrollmentControlRequest) (*mecatlv1.WorkspaceEnrollment, error)
func (*HarnessServer) CleanupTeam ¶
func (h *HarnessServer) CleanupTeam(ctx context.Context, req *mecatlv1.CleanupTeamRequest) (*mecatlv1.CleanupTeamResponse, error)
CleanupTeam tears down a finished team.
func (*HarnessServer) ClearSession ¶ added in v0.0.24
func (h *HarnessServer) ClearSession(ctx context.Context, req *mecatlv1.ClearSessionRequest) (*mecatlv1.ClearSessionResponse, error)
ClearSession creates a distinct empty-history successor.
func (*HarnessServer) CloseSession ¶
func (h *HarnessServer) CloseSession(ctx context.Context, req *mecatlv1.CloseSessionRequest) (*mecatlv1.CloseSessionResponse, error)
CloseSession ends a session and releases its server-side resources. It returns NotFound only for a never-created id; an already-released session succeeds (idempotent). It calls Service.EndSession, NOT the void Service.CloseSession, so an unknown id surfaces as NotFound rather than a silent success.
func (*HarnessServer) CompactSession ¶ added in v0.0.22
func (h *HarnessServer) CompactSession(ctx context.Context, req *mecatlv1.CompactSessionRequest) (*mecatlv1.CompactSessionResponse, error)
CompactSession applies one out-of-band compaction pass to an owned session.
func (*HarnessServer) ConnectWorkspaceServices ¶ added in v0.0.26
func (h *HarnessServer) ConnectWorkspaceServices(ctx context.Context, req *mecatlv1.WorkspaceEnrollmentConnectRequest) (*mecatlv1.WorkspaceEnrollment, error)
func (*HarnessServer) Converse ¶
func (h *HarnessServer) Converse(stream mecatlv1.HarnessService_ConverseServer) error
Converse drives one run over a bidi stream. The first frame MUST be a Prompt or RetryStart; the server then relays the run's Events while concurrently reading ResumeApproval / Cancel control frames, until the events channel closes (the terminal result was delivered) or the stream context is cancelled.
func (*HarnessServer) CreateSession ¶
func (h *HarnessServer) CreateSession(ctx context.Context, req *mecatlv1.CreateSessionRequest) (*mecatlv1.CreateSessionResponse, error)
CreateSession allocates a new session and returns its id.
func (*HarnessServer) CreateTeam ¶
func (h *HarnessServer) CreateTeam(ctx context.Context, req *mecatlv1.CreateTeamRequest) (*mecatlv1.CreateTeamResponse, error)
CreateTeam allocates a new agent team and returns its id, enrolling the optional initial roster atomically (any member failure abandons the whole team). The enrolled roster is echoed back so the caller need not follow up with ListTeam.
func (*HarnessServer) DecideDreamPlan ¶
func (h *HarnessServer) DecideDreamPlan(ctx context.Context, req *mecatlv1.DecideDreamPlanRequest) (*mecatlv1.DecideDreamPlanResponse, error)
DecideDreamPlan applies or dismisses the exact retained review plan.
func (*HarnessServer) DecideLearningProposal ¶
func (h *HarnessServer) DecideLearningProposal(ctx context.Context, req *mecatlv1.DecideLearningProposalRequest) (*mecatlv1.DecideLearningProposalResponse, error)
DecideLearningProposal applies a version-checked approve or reject decision.
func (*HarnessServer) DeleteSession ¶
func (h *HarnessServer) DeleteSession(ctx context.Context, req *mecatlv1.DeleteSessionRequest) (*mecatlv1.DeleteSessionResponse, error)
DeleteSession physically removes an idle main session and store-managed sidecars.
func (*HarnessServer) DiffLearnedSkillVersions ¶
func (h *HarnessServer) DiffLearnedSkillVersions(ctx context.Context, req *mecatlv1.DiffLearnedSkillVersionsRequest) (*mecatlv1.DiffLearnedSkillVersionsResponse, error)
func (*HarnessServer) ForkSession ¶
func (h *HarnessServer) ForkSession(ctx context.Context, req *mecatlv1.ForkSessionRequest) (*mecatlv1.ForkSessionResponse, error)
ForkSession creates a history-carrying successor.
func (*HarnessServer) GenerateDreamPlan ¶
func (h *HarnessServer) GenerateDreamPlan(ctx context.Context, req *mecatlv1.GenerateDreamPlanRequest) (*mecatlv1.GenerateDreamPlanResponse, error)
GenerateDreamPlan creates a retained manual consolidation review.
func (*HarnessServer) GetCompatibilityInfo ¶ added in v0.0.22
func (h *HarnessServer) GetCompatibilityInfo(ctx context.Context, _ *mecatlv1.GetCompatibilityInfoRequest) (*mecatlv1.GetCompatibilityInfoResponse, error)
GetCompatibilityInfo returns the deployment's compatibility descriptor.
Distinct from GetServerInfo above, which answers "which BUILD is this?" under the server-info privacy boundary. This answers "what may I do with this server?" and carries exactly the capabilities/configuration that boundary keeps out of the identity response.
It is authenticated like every other RPC, which keeps UNAUTHENTICATED and UNIMPLEMENTED distinguishable at the client: the SDK treats UNIMPLEMENTED as "below the compatibility floor" and fails loudly, so an auth failure must not be able to masquerade as one.
func (*HarnessServer) GetGuardrailReviewDetail ¶ added in v0.0.41
func (h *HarnessServer) GetGuardrailReviewDetail(ctx context.Context, req *mecatlv1.GetGuardrailReviewDetailRequest) (*mecatlv1.GetGuardrailReviewDetailResponse, error)
func (*HarnessServer) GetLearnedSkill ¶
func (h *HarnessServer) GetLearnedSkill(ctx context.Context, req *mecatlv1.GetLearnedSkillRequest) (*mecatlv1.GetLearnedSkillResponse, error)
func (*HarnessServer) GetLearningAttempt ¶ added in v0.0.24
func (h *HarnessServer) GetLearningAttempt(ctx context.Context, req *mecatlv1.GetLearningAttemptRequest) (*mecatlv1.GetLearningAttemptResponse, error)
GetLearningAttempt returns one content-free attempt projection from the caller partition.
func (*HarnessServer) GetLearningProposal ¶
func (h *HarnessServer) GetLearningProposal(ctx context.Context, req *mecatlv1.GetLearningProposalRequest) (*mecatlv1.GetLearningProposalResponse, error)
GetLearningProposal returns bounded detail for one caller-owned proposal.
func (*HarnessServer) GetMcpAuthorizationPresentation ¶ added in v0.0.26
func (h *HarnessServer) GetMcpAuthorizationPresentation(ctx context.Context, req *mecatlv1.GetMcpAuthorizationPresentationRequest) (*mecatlv1.GetMcpAuthorizationPresentationResponse, error)
GetMcpAuthorizationPresentation returns the live browser URL for one owned, still-pending authorization. The request carries correlation only.
func (*HarnessServer) GetMcpPrompt ¶
func (h *HarnessServer) GetMcpPrompt(ctx context.Context, req *mecatlv1.GetMcpPromptRequest) (*mecatlv1.GetMcpPromptResponse, error)
GetMcpPrompt expands a named prompt with arguments on the named server.
func (*HarnessServer) GetServerInfo ¶ added in v0.0.22
func (h *HarnessServer) GetServerInfo(_ context.Context, req *mecatlv1.GetServerInfoRequest) (*mecatlv1.GetServerInfoResponse, error)
GetServerInfo returns safe build, composition, and the caller-selected provider endpoint projection.
func (*HarnessServer) GetSession ¶
func (h *HarnessServer) GetSession(ctx context.Context, req *mecatlv1.GetSessionRequest) (*mecatlv1.GetSessionResponse, error)
GetSession returns a snapshot of the requested session.
func (*HarnessServer) GetSessionCleanupJob ¶
func (h *HarnessServer) GetSessionCleanupJob(ctx context.Context, req *mecatlv1.GetSessionCleanupJobRequest) (*mecatlv1.CleanupJob, error)
func (*HarnessServer) GetSessionTranscript ¶
func (h *HarnessServer) GetSessionTranscript(ctx context.Context, req *mecatlv1.GetSessionTranscriptRequest) (*mecatlv1.GetSessionTranscriptResponse, error)
GetSessionTranscript returns the owned session's snapshot-derived transcript.
func (*HarnessServer) GetSoul ¶
func (h *HarnessServer) GetSoul(ctx context.Context, _ *mecatlv1.GetSoulRequest) (*mecatlv1.GetSoulResponse, error)
GetSoul returns the resolved soul (persona) snapshot.
func (*HarnessServer) GetStorageHealth ¶
func (h *HarnessServer) GetStorageHealth(ctx context.Context, _ *mecatlv1.GetStorageHealthRequest) (*mecatlv1.GetStorageHealthResponse, error)
GetStorageHealth returns authenticated aggregate storage status.
func (*HarnessServer) GetUserModel ¶
func (h *HarnessServer) GetUserModel(ctx context.Context, req *mecatlv1.GetUserModelRequest) (*mecatlv1.GetUserModelResponse, error)
GetUserModel returns the current user-model index snapshot.
func (*HarnessServer) ListAgents ¶
func (h *HarnessServer) ListAgents(ctx context.Context, _ *mecatlv1.ListAgentsRequest) (*mecatlv1.ListAgentsResponse, error)
ListAgents returns the resolved agent-definition inventory snapshot.
func (*HarnessServer) ListCommands ¶
func (h *HarnessServer) ListCommands(ctx context.Context, req *mecatlv1.ListCommandsRequest) (*mecatlv1.ListCommandsResponse, error)
ListCommands returns commands for an owned session placement.
func (*HarnessServer) ListExecutionTemplates ¶ added in v0.0.48
func (h *HarnessServer) ListExecutionTemplates(ctx context.Context, _ *mecatlv1.ListExecutionTemplatesRequest) (*mecatlv1.ListExecutionTemplatesResponse, error)
ListExecutionTemplates returns the caller's execution template catalog.
func (*HarnessServer) ListGuardrailCoverage ¶ added in v0.0.41
func (h *HarnessServer) ListGuardrailCoverage(ctx context.Context, req *mecatlv1.ListGuardrailCoverageRequest) (*mecatlv1.ListGuardrailCoverageResponse, error)
func (*HarnessServer) ListLearnedSkills ¶
func (h *HarnessServer) ListLearnedSkills(ctx context.Context, req *mecatlv1.ListLearnedSkillsRequest) (*mecatlv1.ListLearnedSkillsResponse, error)
func (*HarnessServer) ListLearningAttempts ¶ added in v0.0.24
func (h *HarnessServer) ListLearningAttempts(ctx context.Context, req *mecatlv1.ListLearningAttemptsRequest) (*mecatlv1.ListLearningAttemptsResponse, error)
ListLearningAttempts returns one bounded attempt page from the caller partition.
func (*HarnessServer) ListLearningProposals ¶
func (h *HarnessServer) ListLearningProposals(ctx context.Context, req *mecatlv1.ListLearningProposalsRequest) (*mecatlv1.ListLearningProposalsResponse, error)
ListLearningProposals returns one bounded proposal page for the caller partition.
func (*HarnessServer) ListMcpPrompts ¶
func (h *HarnessServer) ListMcpPrompts(ctx context.Context, req *mecatlv1.ListMcpPromptsRequest) (*mecatlv1.ListMcpPromptsResponse, error)
ListMcpPrompts returns the prompt snapshots for the requested server (empty server = all). Nil provider yields an empty list.
func (*HarnessServer) ListMcpResources ¶
func (h *HarnessServer) ListMcpResources(ctx context.Context, req *mecatlv1.ListMcpResourcesRequest) (*mecatlv1.ListMcpResourcesResponse, error)
ListMcpResources returns the resource snapshots for the requested server (empty server = all). Nil provider yields an empty list.
func (*HarnessServer) ListMcpSources ¶
func (h *HarnessServer) ListMcpSources(ctx context.Context, _ *mecatlv1.ListMcpSourcesRequest) (*mecatlv1.ListMcpSourcesResponse, error)
ListMcpSources returns the resolved MCP source inventory snapshot.
func (*HarnessServer) ListModels ¶
func (h *HarnessServer) ListModels(ctx context.Context, _ *mecatlv1.ListModelsRequest) (*mecatlv1.ListModelsResponse, error)
ListModels returns models and provider statuses from one completed publication.
func (*HarnessServer) ListSessionMcpConnectors ¶ added in v0.0.34
func (h *HarnessServer) ListSessionMcpConnectors(ctx context.Context, req *mecatlv1.ListSessionMcpConnectorsRequest) (*mecatlv1.ListSessionMcpConnectorsResponse, error)
ListSessionMcpConnectors implements the owner-scoped broker inventory RPC.
func (*HarnessServer) ListSessions ¶
func (h *HarnessServer) ListSessions(ctx context.Context, req *mecatlv1.ListSessionsRequest) (*mecatlv1.ListSessionsResponse, error)
ListSessions returns the stored-session inventory — the picker metadata a client renders to let an operator open an EXISTING session by id (issue #245).
func (*HarnessServer) ListSkillChanges ¶
func (h *HarnessServer) ListSkillChanges(ctx context.Context, req *mecatlv1.ListSkillChangesRequest) (*mecatlv1.ListSkillChangesResponse, error)
func (*HarnessServer) ListSkillFiles ¶ added in v0.0.48
func (h *HarnessServer) ListSkillFiles(ctx context.Context, req *mecatlv1.ListSkillFilesRequest) (*mecatlv1.ListSkillFilesResponse, error)
ListSkillFiles lists the readable files of one skill in the caller's skill view.
func (*HarnessServer) ListSkills ¶
func (h *HarnessServer) ListSkills(ctx context.Context, _ *mecatlv1.ListSkillsRequest) (*mecatlv1.ListSkillsResponse, error)
ListSkills returns the resolved skills-inventory snapshot.
func (*HarnessServer) ListTeam ¶
func (h *HarnessServer) ListTeam(ctx context.Context, req *mecatlv1.ListTeamRequest) (*mecatlv1.ListTeamResponse, error)
ListTeam returns a snapshot of the team roster, task list, and completion state.
func (*HarnessServer) ListToolHiveGroups ¶
func (h *HarnessServer) ListToolHiveGroups(ctx context.Context, _ *mecatlv1.ListToolHiveGroupsRequest) (*mecatlv1.ListToolHiveGroupsResponse, error)
ListToolHiveGroups returns the distinct, non-empty ToolHive groups derived from the inventory snapshot.
func (*HarnessServer) ListWorktrees ¶
func (h *HarnessServer) ListWorktrees(ctx context.Context, req *mecatlv1.ListWorktreesRequest) (*mecatlv1.ListWorktreesResponse, error)
ListWorktrees returns scoped placement choices for an owned session.
func (*HarnessServer) PlanSessionCleanup ¶
func (h *HarnessServer) PlanSessionCleanup(ctx context.Context, req *mecatlv1.PlanSessionCleanupRequest) (*mecatlv1.PlanSessionCleanupResponse, error)
PlanSessionCleanup returns a caller-bound read-only retention plan.
func (*HarnessServer) ReadMcpResource ¶
func (h *HarnessServer) ReadMcpResource(ctx context.Context, req *mecatlv1.ReadMcpResourceRequest) (*mecatlv1.ReadMcpResourceResponse, error)
ReadMcpResource reads a single resource by URI from the named server.
func (*HarnessServer) ReadSkillFile ¶ added in v0.0.48
func (h *HarnessServer) ReadSkillFile(ctx context.Context, req *mecatlv1.ReadSkillFileRequest) (*mecatlv1.ReadSkillFileResponse, error)
ReadSkillFile returns the text of one file of a skill in the caller's skill view.
func (*HarnessServer) RecheckMcpAuthorization ¶ added in v0.0.26
func (h *HarnessServer) RecheckMcpAuthorization(stream grpc.BidiStreamingServer[mecatlv1.RecheckMcpAuthorizationRequest, mecatlv1.RecheckMcpAuthorizationResponse]) error
func (*HarnessServer) ReflectSession ¶
func (h *HarnessServer) ReflectSession(ctx context.Context, req *mecatlv1.ReflectSessionRequest) (*mecatlv1.ReflectSessionResponse, error)
ReflectSession submits one caller-owned completed session to the bounded coordinator.
func (*HarnessServer) RefreshMcpSources ¶ added in v0.0.41
func (h *HarnessServer) RefreshMcpSources(ctx context.Context, req *mecatlv1.RefreshMcpSourcesRequest) (*mecatlv1.RefreshMcpSourcesResponse, error)
RefreshMcpSources reconciles direct MCP and grants additions to an eligible owned root.
func (*HarnessServer) RejectLearnedSkill ¶
func (h *HarnessServer) RejectLearnedSkill(ctx context.Context, req *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*HarnessServer) RenameSession ¶
func (h *HarnessServer) RenameSession(ctx context.Context, req *mecatlv1.RenameSessionRequest) (*mecatlv1.RenameSessionResponse, error)
RenameSession explicitly replaces an idle main session's persisted title.
func (*HarnessServer) ResolvePlanAsk ¶ added in v0.0.41
func (h *HarnessServer) ResolvePlanAsk(ctx context.Context, req *mecatlv1.ResolvePlanAskRequest) (*mecatlv1.ResolvePlanAskResponse, error)
ResolvePlanAsk resolves one plan-originated permission ask on the exact run.
func (*HarnessServer) ResolveRunAsk ¶ added in v0.0.39
func (h *HarnessServer) ResolveRunAsk(ctx context.Context, req *mecatlv1.ResolveRunAskRequest) (*mecatlv1.ResolveRunAskResponse, error)
ResolveRunAsk resolves one ordinary permission ask on the exact addressed run.
func (*HarnessServer) RetryLearningAttempt ¶ added in v0.0.24
func (h *HarnessServer) RetryLearningAttempt(ctx context.Context, req *mecatlv1.MutateLearningAttemptRequest) (*mecatlv1.MutateLearningAttemptResponse, error)
RetryLearningAttempt retries one failed attempt under opaque-version CAS.
func (*HarnessServer) RetryWorkspaceEnrollment ¶ added in v0.0.26
func (h *HarnessServer) RetryWorkspaceEnrollment(ctx context.Context, req *mecatlv1.WorkspaceEnrollmentControlRequest) (*mecatlv1.WorkspaceEnrollment, error)
func (*HarnessServer) RollbackLearnedSkill ¶
func (h *HarnessServer) RollbackLearnedSkill(ctx context.Context, req *mecatlv1.RollbackLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*HarnessServer) RunTeam ¶
func (h *HarnessServer) RunTeam(req *mecatlv1.RunTeamRequest, stream mecatlv1.HarnessService_RunTeamServer) error
RunTeam drives the team to quiescence, streaming every member event tagged with the producing member, then ends the stream with the single terminal frame carrying TeamEvent.outcome (issue #36). Supervisor.Run serialises sink calls through a single forwarder, so stream.Send is never invoked concurrently. A send failure cancels the run so the team stops promptly rather than running on to quiescence unseen; the outcome frame is sent only when no send has failed (relay-drain discipline — a dead client gets no further writes).
func (*HarnessServer) SendTeammateMessage ¶
func (h *HarnessServer) SendTeammateMessage(ctx context.Context, req *mecatlv1.SendTeammateMessageRequest) (*mecatlv1.SendTeammateMessageResponse, error)
SendTeammateMessage posts a message into a member's inbox.
func (*HarnessServer) SetMode ¶
func (h *HarnessServer) SetMode(ctx context.Context, req *mecatlv1.SetModeRequest) (*mecatlv1.SetModeResponse, error)
SetMode changes the permission posture of the requested session.
func (*HarnessServer) SpawnTeammate ¶
func (h *HarnessServer) SpawnTeammate(ctx context.Context, req *mecatlv1.SpawnTeammateRequest) (*mecatlv1.SpawnTeammateResponse, error)
SpawnTeammate enrols a member in a team and returns its roster entry.
func (*HarnessServer) SteerRun ¶ added in v0.0.39
func (h *HarnessServer) SteerRun(ctx context.Context, req *mecatlv1.SteerRunRequest) (*mecatlv1.SteerRunResponse, error)
SteerRun injects content into the exact addressed live run without promotion.
func (*HarnessServer) StreamSessionEvents ¶
func (h *HarnessServer) StreamSessionEvents(req *mecatlv1.StreamSessionEventsRequest, stream grpc.ServerStreamingServer[mecatlv1.Event]) error
StreamSessionEvents replays a session's durable event log as a server stream of Event envelopes (issue #245).
func (*HarnessServer) StreamSessionLive ¶
func (h *HarnessServer) StreamSessionLive(req *mecatlv1.StreamSessionLiveRequest, stream grpc.ServerStreamingServer[mecatlv1.Event]) error
StreamSessionLive is the LIVE per-session event stream (fire-result delivery): a thin transport over the in-process per-session subscription registry (Service.Subscribe / PublishSessionEvent). It is the UNIFIED bridge serving BOTH the embedded mecatui (which dials its in-process server over a real gRPC UNIX socket) AND a remote mecated — ONE proto, ONE TUI consumption path.
Relay discipline: the live wire applies the SAME log-only skip as the live Converse relay, with ONE narrow exception — a fire-result DELIVERY note (an EvUserPrompt whose text starts with the renderFireDelivery provenance header "[scheduled task ") is RELAYED so a connected client renders the delivery card as it happens (AC6.2). The other two log-only kinds (EvApproval, EvCompactionArchive) stay SKIPPED, and a non-delivery EvUserPrompt stays skipped too (the client already holds its own prompt). The delivery note is metadata-only/redacted by construction (gauntlet #7).
Drain-to-discard: a Send error (dead/disconnected client) cancels the subscription and the handler returns — the in-process registry's PublishSessionEvent is already non-blocking (a full subscriber channel drops the event, AC6.3), so a dead client never wedges the delivery run. The durable log records the tail regardless (it is appended by the relay/loop, independent of this stream).
func (*HarnessServer) UndoLearningPromotion ¶
func (h *HarnessServer) UndoLearningPromotion(ctx context.Context, req *mecatlv1.UndoLearningPromotionRequest) (*mecatlv1.UndoLearningPromotionResponse, error)
UndoLearningPromotion applies a version-checked compensating promotion undo.
func (*HarnessServer) WatchSessionEvents ¶ added in v0.0.22
func (h *HarnessServer) WatchSessionEvents(req *mecatlv1.WatchSessionEventsRequest, stream grpc.ServerStreamingServer[mecatlv1.WatchSessionEventsResponse]) error
WatchSessionEvents is the DURABLE replay-then-follow stream (issue #821): a thin transport over Service.WatchSessionEvents.
The SSE route GET /v1/sessions/{id}/watch consumes the SAME service method, so the two transports deliver identical envelope sequences by construction rather than by parallel maintenance (AC7.3). Everything below is framing.
Relay discipline mirrors StreamSessionEvents, NOT the live wire: this is the READ-BACK of the durable log, so ALL events are relayed including the three log-only kinds (EvApproval/EvCompactionArchive/EvUserPrompt) — a client replaying a session wants the verdicts and prompts, as they ARE the transcript. Do NOT copy relayLiveEvent's filter here.
A Send error means the client is gone: break out of the iterator, which releases the watch and its backend read per port.CursorEventLog's contract. There is no drain-to-discard to do — unlike a live relay, this stream pulls from durable storage and has no run whose emits could wedge behind it.
type HealthHandler ¶
type HealthHandler struct {
// contains filtered or unexported fields
}
HealthHandler serves the liveness and readiness probes. Liveness (/healthz) always returns 200 while the process is up; readiness (/readyz) returns 200 only when the injected ReadyFunc reports ready, else 503. These endpoints carry no secrets and MUST be mounted outside the auth/rate-limit middleware so orchestrators can probe them without credentials.
func NewHealthHandler ¶
func NewHealthHandler(ready ReadyFunc) *HealthHandler
NewHealthHandler constructs a HealthHandler. A nil ready func means the server is considered ready as soon as the process is up.
func (*HealthHandler) Live ¶
func (*HealthHandler) Live(w http.ResponseWriter, _ *http.Request)
Live handles GET /healthz: a pure liveness probe that is 200 whenever the process can serve HTTP at all.
func (*HealthHandler) Ready ¶
func (h *HealthHandler) Ready(w http.ResponseWriter, _ *http.Request)
Ready handles GET /readyz: 200 when dependencies are ready, 503 otherwise.
func (*HealthHandler) RegisterHealth ¶
func (h *HealthHandler) RegisterHealth(mux *http.ServeMux)
RegisterHealth mounts the health endpoints on mux. They are intentionally registered on the outer mux (before auth) so they bypass authentication and rate limiting.
type IDGenerator ¶
IDGenerator returns a fresh, unique session id. It defaults to a random hex id when nil; tests may inject a deterministic generator.
type ListSessionsPage ¶
type ListSessionsPage struct {
Sessions []SessionSummary
NextCursor string
TotalCount int
}
ListSessionsPage is one bounded owner-filtered inventory response.
type ListSessionsPageRequest ¶
ListSessionsPageRequest asks for one bounded inventory page.
type LocalSessionContextServer ¶ added in v0.0.26
type LocalSessionContextServer struct {
mecatlv1.UnimplementedLocalSessionContextServiceServer
// contains filtered or unexported fields
}
LocalSessionContextServer implements the privileged local-client workspace-root projection. Registration is deliberately left to composition, which must attest the listener is local-client trusted.
func NewLocalSessionContextServer ¶ added in v0.0.26
func NewLocalSessionContextServer(svc *Service) *LocalSessionContextServer
NewLocalSessionContextServer constructs the separately registered privileged service over svc. It does not register the service on any listener.
func (*LocalSessionContextServer) GetLocalSessionContext ¶ added in v0.0.26
func (s *LocalSessionContextServer) GetLocalSessionContext(ctx context.Context, req *mecatlv1.GetLocalSessionContextRequest) (*mecatlv1.GetLocalSessionContextResponse, error)
GetLocalSessionContext returns only the exact reattached local workspace root.
type MCPAuthorizationControl ¶ added in v0.0.26
MCPAuthorizationControl is safe caller correlation. It carries no success assertion, browser code, credential, binding, or tool arguments.
type MCPAuthorizationResult ¶ added in v0.0.26
type MCPAuthorizationResult struct {
Status session.AuthorizationStatus
Event session.Event
Run *agent.Run
}
MCPAuthorizationResult is the concrete domain outcome observed by a control. Run is non-nil only when that control won and registered a continuation.
type MCPRefreshResult ¶ added in v0.0.41
MCPRefreshResult reports the exact runtime revision considered by this request and whether that cycle published a runtime or added authority.
type MCPRefreshSnapshot ¶ added in v0.0.41
MCPRefreshSnapshot is the immutable direct-runtime snapshot considered by one explicit refresh request. ToolNames are active direct names only.
type MCPSourceStatus ¶ added in v0.0.41
type MCPSourceStatus struct {
Sources []source.SourceInfo
Revision uint64
Stale bool
Reconciling bool
}
MCPSourceStatus is the reconciler's cached public status. Sources are the published/pre-shadow inventory and are never populated by a status-time probe.
type MemberEngineFactory ¶
type MemberEngineFactory func(t *team.Team, spec agent.MemberSpec, routedModel string) agent.MemberBuild
MemberEngineFactory builds a team member's engine (and its optional per-member permission mode), binding it to the shared team (so the member's catalog includes that team's coordination tools) and shaping it from the member spec (read-only base vs mutating tools, the member's agent definition). The composition root supplies it via Config.MemberEngine; CreateTeam adapts it to an agent.MemberEngine by capturing the per-team aggregate. Returning agent.MemberBuild (rather than a bare *Engine) is how a def's permissionMode reaches the supervisor's per-member session.
routedModel is the OPT-IN model router's classification — the ALREADY-RESOLVED concrete model id for an UNDEFINED member, "" otherwise (no router, a miss, or a DEFINED member whose def pins its own model). It is the same shape as agent.TeamMemberEngineFactory so one factory satisfies both. On the gRPC RunTeam path the supervisor runs ZERO-CAPS (no parent caps ⇒ no routeTask), so routedModel is always "" there and the member is built byte-identically to today.
type ModeScopedWorkspace ¶ added in v0.0.50
type ModeScopedWorkspace interface {
ForPermissionMode(mode session.PermissionMode) tool.Workspace
}
ModeScopedWorkspace is an optional Workspace capability for a workspace whose serving depends on the executing session's permission mode. The run-entry funnel binds the view for the session's current mode once per run; the mode is fixed for a run because SetMode is refused mid-turn.
type ModelInventory ¶ added in v0.0.26
type ModelInventory interface {
CurrentModelSnapshot() ModelSnapshot
}
ModelInventory is a pure reader of one composition-owned publication.
type ModelSnapshot ¶ added in v0.0.41
type ModelSnapshot struct {
Models []*mecatlv1.ModelInfo
ProviderStatus []*mecatlv1.ProviderStatus
}
ModelSnapshot captures model rows and provider statuses from one publication.
type OwnerlessCutoverInventory ¶
type OwnerlessCutoverInventory struct {
SessionsAvailable bool
SessionCount int
SessionIDs []string
SessionIDsTruncated bool
SchedulesAvailable bool
ScheduleCount int
ScheduleNames []string
ScheduleNamesTruncated bool
}
OwnerlessCutoverInventory is a content-free preflight for enabling caller ownership. Identifiers are bounded samples; counts cover the full available inventory. Availability is per family because custom stores may expose only one metadata seam.
type PlacementBindRequest ¶ added in v0.0.24
type PlacementBindRequest struct {
Selector PlacementSelector
Principal *session.Principal
Scope PlacementScope
Operation PlacementOperation
// BindingID is the final server-minted session identity. Providers that
// allocate durable environments use it as their idempotency/reference key.
BindingID session.SessionID
}
PlacementBindRequest contains the complete authorization context a provider needs to atomically authorize and resolve one placement record version.
type PlacementBinder ¶ added in v0.0.24
type PlacementBinder struct {
// contains filtered or unexported fields
}
PlacementBinder is the server-owned choke point around one deployment provider. It exposes no registry, inventory, signer, cache, or split authorization/resolution operation.
func NewPlacementBinder ¶ added in v0.0.24
func NewPlacementBinder(provider PlacementProvider) (*PlacementBinder, error)
NewPlacementBinder constructs the binding choke point.
func (*PlacementBinder) Bind ¶ added in v0.0.24
func (b *PlacementBinder) Bind(ctx context.Context, req PlacementBindRequest) (PlacementBinding, error)
Bind validates the request, delegates exactly one atomic operation to the provider, then validates that the returned environment and exact ref agree.
func (*PlacementBinder) Reattach ¶ added in v0.0.24
func (b *PlacementBinder) Reattach(ctx context.Context, req PlacementReattachRequest) (PlacementBinding, error)
Reattach resolves only the exact persisted ref. Providers without the explicit reattachment capability fail closed; Bind is never used as fallback.
type PlacementBinding ¶ added in v0.0.24
type PlacementBinding struct {
Environment tool.Environment
Ref session.EnvironmentRef
Metadata PlacementMetadata
// GovernanceRoot is explicit trusted host context for project-scoped
// governance, including permission, learning, and continuation partitioning.
// It is independent of harness-context sources and of the execution namespace
// exposed by Environment.Workspace().Root(). Non-local bindings leave it empty
// when there is no host governance context; guest roots are never used as a
// fallback. No-FS bindings always leave it empty.
GovernanceRoot string
// Commit publishes a provisional durable reference after the session store
// definitively publishes the matching binding. Close aborts it only while Commit
// has not succeeded; an ambiguous commit must remain recoverable.
Commit func(context.Context) error
// Close detaches a published placement binding. Service ownership is
// transferred only after the session snapshot is durably created.
Close func() error
// Rollback permanently removes this exact unpublished placement. Providers
// that provision durable state during Bind must supply it; it is never used
// after publication or for ordinary EndSession teardown.
Rollback func() error
}
PlacementBinding is the indivisible successful result of Bind.
type PlacementDeleteRequest ¶ added in v0.0.42
type PlacementDeleteRequest struct {
Ref session.EnvironmentRef
Principal *session.Principal
Scope PlacementScope
}
PlacementDeleteRequest authorizes cleanup of one exact schedule-owned placement. It contains no path and cannot select a current default.
type PlacementDeleteResult ¶ added in v0.0.42
type PlacementDeleteResult struct {
Retained bool
}
PlacementDeleteResult reports whether cleanup retained dirty worktree state.
type PlacementDeleter ¶ added in v0.0.42
type PlacementDeleter interface {
DeletePlacement(context.Context, PlacementDeleteRequest) (PlacementDeleteResult, error)
}
PlacementDeleter is the optional exact-ref cleanup capability used only for placements durably marked as owned by an independent schedule.
type PlacementDiscoverer ¶ added in v0.0.24
type PlacementDiscoverer interface {
ListWorktrees(context.Context, PlacementDiscoveryRequest) ([]ScopedWorktree, error)
}
PlacementDiscoverer is the provider-owned discovery capability. Worktree availability is derived only from the mandatory PlacementProvider implementing this interface; there is no independent Config discovery seam.
type PlacementDiscoveryRequest ¶ added in v0.0.24
type PlacementDiscoveryRequest struct {
Source session.SessionID
SourceRef session.EnvironmentRef
Principal *session.Principal
Scope PlacementScope
}
PlacementDiscoveryRequest scopes alternate-worktree discovery to an owned source and its exact current placement.
type PlacementMetadata ¶ added in v0.0.24
type PlacementMetadata struct {
Kind string
Label string
// Branch is the short branch name, such as "feat/x", not a full ref.
Branch string
Revision string
}
PlacementMetadata is the bounded, display-safe provider projection returned with a binding. It contains no roots, locators, credentials, or authority.
type PlacementOperation ¶ added in v0.0.24
type PlacementOperation string
PlacementOperation identifies the server operation requesting a new binding.
const ( // PlacementOperationCreate binds a placement for a new root session. PlacementOperationCreate PlacementOperation = "create" // PlacementOperationSuccessor binds or reauthorizes a placement while // creating a successor session. PlacementOperationSuccessor PlacementOperation = "successor" )
type PlacementProvider ¶ added in v0.0.24
type PlacementProvider interface {
Bind(context.Context, PlacementBindRequest) (PlacementBinding, error)
}
PlacementProvider owns placement authorization, atomic binding resolution, and private environment construction.
type PlacementReattachRequest ¶ added in v0.0.24
type PlacementReattachRequest struct {
Ref session.EnvironmentRef
Principal *session.Principal
Scope PlacementScope
// BindingID identifies the durable reference being reattached.
BindingID session.SessionID
}
PlacementReattachRequest carries the trusted authorization context and the exact durable identity to reattach. Ref must include Kind, ID, and Revision.
type PlacementReattacher ¶ added in v0.0.24
type PlacementReattacher interface {
Reattach(context.Context, PlacementReattachRequest) (PlacementBinding, error)
}
PlacementReattacher is the exact persisted-ref half of a placement provider. It is separate from PlacementProvider so legacy providers cannot accidentally receive a reattachment request through Bind and follow their current default.
type PlacementScope ¶ added in v0.0.24
type PlacementScope string
PlacementScope is a trusted composition-owned authorization scope. It is not derived from a placement ID or filesystem path.
type PlacementSelector ¶ added in v0.0.24
type PlacementSelector struct {
Kind PlacementSelectorKind
ID string
Revision string
Source session.SessionID
SourceRef session.EnvironmentRef
}
PlacementSelector is the private server/provider binding protocol. It never crosses the engine or public transport boundary.
func DefaultPlacement ¶ added in v0.0.24
func DefaultPlacement() PlacementSelector
DefaultPlacement selects the provider-owned deployment default.
func NoFSPlacement ¶ added in v0.0.24
func NoFSPlacement() PlacementSelector
NoFSPlacement selects explicit filesystem attenuation.
func SelectTemplate ¶ added in v0.0.48
func SelectTemplate(id, revision string) PlacementSelector
SelectTemplate binds a validated operator-owned recipe by exact revision.
func SelectWorktree ¶ added in v0.0.24
func SelectWorktree(source session.SessionID, ref session.EnvironmentRef, token string) PlacementSelector
SelectWorktree carries a source-scoped ephemeral selector to the provider.
func (PlacementSelector) IsDefault ¶ added in v0.0.24
func (s PlacementSelector) IsDefault() bool
IsDefault reports whether the deployment default was selected.
func (PlacementSelector) IsNoFS ¶ added in v0.0.24
func (s PlacementSelector) IsNoFS() bool
IsNoFS reports whether filesystem attenuation was selected.
func (PlacementSelector) IsTemplate ¶ added in v0.0.48
func (s PlacementSelector) IsTemplate() bool
IsTemplate reports whether an exact execution template was selected.
func (PlacementSelector) IsWorktree ¶ added in v0.0.24
func (s PlacementSelector) IsWorktree() bool
IsWorktree reports whether a source-scoped worktree token was selected.
func (PlacementSelector) Valid ¶ added in v0.0.24
func (s PlacementSelector) Valid() bool
Valid reports whether the selector has exactly one valid protocol shape.
type PlacementSelectorKind ¶ added in v0.0.24
type PlacementSelectorKind string
PlacementSelectorKind is the closed private binding vocabulary.
const ( PlacementSelectorTemplate PlacementSelectorKind = "template" PlacementSelectorDefault PlacementSelectorKind = "default" PlacementSelectorNoFS PlacementSelectorKind = "no-fs" PlacementSelectorWorktree PlacementSelectorKind = "worktree" )
Private placement selector kinds.
type PlacementSuccessorRequest ¶ added in v0.0.42
type PlacementSuccessorReservoir ¶ added in v0.0.42
type PlacementSuccessorReservoir interface {
ReserveSuccessor(context.Context, PlacementSuccessorRequest) (PlacementBinding, error)
}
type PlacementValidator ¶ added in v0.0.42
PlacementValidator performs side-effect-free startup validation. Providers whose Bind allocates resources implement this seam so preflight never binds.
type PrincipalValidator ¶
type PrincipalValidator interface {
Validate(ctx context.Context, bearer string) (*session.Principal, error)
}
PrincipalValidator verifies a bearer credential and returns the caller it vouches for. Validation itself — JWT parse, signature, alg, issuer/audience/exp/nbf, JWKS fetch and rotation — is DELEGATED to the implementation (toolhive-core/authn); mecatl hand-rolls none of it. This narrow interface is the seam: the edge only decides what to do with the verdict.
A nil returned principal with a nil error is treated as a rejection: the edge never fabricates an anonymous caller (absent identity is a nil principal, and that only happens when NO validator is wired at all).
type ProposalManifestLoader ¶ added in v0.0.26
type ProposalManifestLoader func(context.Context, learning.ProposalPartition, learning.ProposalID) (learning.MaterializationManifest, bool, error)
ProposalManifestLoader loads the immutable selected-evidence manifest stored atomically with a proposal.
type ProposalPromoter ¶
type ProposalPromoter func(context.Context, learning.ProposalPartition, learning.ProposalID, learning.ProposalVersion, bool) (learning.ProposalRecord, error)
ProposalPromoter applies an approved proposal through the configured memory target.
type ProposalUndoer ¶
type ProposalUndoer func(context.Context, learning.ProposalPartition, learning.ProposalID, learning.ProposalVersion) (learning.ProposalRecord, error)
ProposalUndoer commits a compensating memory revision for a promoted proposal.
type ProtectedResourceProfile ¶ added in v0.0.26
type ProtectedResourceProfile struct {
Resource string
Issuer string
Audience string
ClientID string
Scopes []string
}
ProtectedResourceProfile is the validated, public subset of the server's OIDC configuration that RFC 9728 makes discoverable. This is a minimal adaptation of Apache-2.0 ToolHive v0.40.0 pkg/auth/well_known.go; it keeps the profile type open for mecatl's namespaced fields and routes only the configured resource path.
type ProviderSelector ¶
type ProviderSelector struct {
// ProviderID is the registry id ("" => server default).
ProviderID string
// ModelID is the model selector ("" => provider default; a non-empty id the
// catalog doesn't know is passed through to the provider verbatim).
ModelID string
// ReasoningEffort is the per-session reasoning-effort selector: a
// NEUTRAL token ("" / "auto" => unset, the operator default applies; otherwise
// low/medium/high/xhigh/max). It is OPAQUE to the adapter — the composition root
// normalises + clamps it per provider and re-mints the engine's adapter when it
// differs from the operator default. "" keeps the operator default (and the
// shared engine on a byte-identical default path). It composes orthogonally with
// ProviderID/ModelID; unlike ModelID it is meaningful WITHOUT a ProviderID (it
// rides the server-default provider).
ReasoningEffort string
}
ProviderSelector names a per-session provider+model. The zero value (both empty) means "server default" — the shared engine, no per-session build. It is a NEUTRAL value object owned by the server adapter: the composition root (internal/app) resolves it against the registry/catalog; the adapter never imports either. Setting ModelID with an empty ProviderID is a client error (a bare model on an env-derived default provider is ambiguous) — rejected at the create boundary before the factory is consulted.
type ReadyFunc ¶
type ReadyFunc func() bool
ReadyFunc reports whether the server's dependencies (engine, store) are ready to serve traffic. It is consulted by the /readyz handler on every probe so readiness can change at runtime. A nil ReadyFunc is treated as always-ready.
type ReferenceDeleteHandle ¶ added in v0.0.42
type ReferenceIntent ¶ added in v0.0.42
type ReferenceIntent struct {
Ref session.EnvironmentRef
Principal *session.Principal
BindingID session.SessionID
SourceBindingID session.SessionID
OperationID string
PendingDelete bool
}
ReferenceIntent is the owner-attested, exact provider operation retained after an ambiguous publication or deletion outcome.
type ReferenceIntentLifecycle ¶ added in v0.0.42
type ReferenceIntentLifecycle interface {
ListReferenceIntents(context.Context, int) ([]ReferenceIntent, error)
CommitReferenceIntent(context.Context, ReferenceIntent) error
ConfirmReferenceIntentDelete(context.Context, ReferenceIntent) error
CancelReferenceIntentDelete(context.Context, ReferenceIntent) error
}
ReferenceIntentLifecycle is the optional host reconciliation seam. Its list is scoped by the provider to the authenticated mTLS client and bounded by limit.
type ReferenceLifecycle ¶ added in v0.0.42
type ReferenceLifecycle interface {
Applies(session.EnvironmentRef) bool
PrepareReferenceDelete(context.Context, PlacementSuccessorRequest) (ReferenceDeleteHandle, error)
}
type ReflectionReceipt ¶
type ReflectionReceipt struct {
ID string
Disposition string
Reason string
Queued int
Abstained bool
Staged int
Promoted int
Conflicted int
Usage session.AuxiliaryUsage
}
ReflectionReceipt is the bounded result of an explicit reflection request.
type ResolvedModel ¶
type ResolvedModel struct {
ProviderID string
ModelID string
ContextWindow int64
// ReasoningEffort is the effective per-session reasoning-effort token,
// "" when unset. Carried on the resolved-model echo so the wire (and the
// TUI footer) can show the active effort; it is the value held on the
// per-session engine record (sessionEngine.reasoningEffort), not recomputed.
ReasoningEffort string
}
ResolvedModel is the per-session EFFECTIVE model echoed on the wire: the provider+model id this session resolved to plus its context window. It is the SINGLE composition-computed value (see Config.DefaultResolvedModel and the per-session SessionEngineResult fields) — the server holds it and echoes it verbatim, mirroring the capability-intersection single-source rule; a handler must never read it back off the request (model_id is empty for a default session and ambiguous for passthrough).
type RetentionPolicy ¶
type RetentionPolicy struct {
// Version changes whenever the effective policy semantics change. When empty,
// the server derives a stable version from the scalar limits.
Version string
MainMaxAge time.Duration
MainMaxCount int
ChildMaxAge time.Duration
ChildMaxCount int
ScheduledMaxAge time.Duration
ScheduledMaxCount int
SweepCadence time.Duration
}
RetentionPolicy is the effective process-wide session retention policy. Zero values disable their respective limit or cadence.
type ReviewDetailRegistry ¶ added in v0.0.41
type ReviewDetailRegistry struct {
// contains filtered or unexported fields
}
ReviewDetailRegistry owns bounded live review detail by delegation root.
func NewReviewDetailRegistry ¶ added in v0.0.41
func NewReviewDetailRegistry() *ReviewDetailRegistry
NewReviewDetailRegistry creates an empty bounded live-detail registry.
func (*ReviewDetailRegistry) PublishReviewDetail ¶ added in v0.0.41
func (r *ReviewDetailRegistry) PublishReviewDetail(_ context.Context, detail agent.ReviewDetail)
PublishReviewDetail satisfies agent.ReviewDetailSink. The engine supplies the explicit delegation root; missing root identity is rejected rather than treating a child as its own lifecycle owner.
type RunAskAcknowledgement ¶ added in v0.0.39
RunAskAcknowledgement is the bounded correlation returned by ResolveRunAsk.
type RunControlAcknowledgement ¶ added in v0.0.39
type RunControlAcknowledgement struct {
RunID string
}
RunControlAcknowledgement is the bounded correlation returned by CancelRun.
type RunEventRecorder ¶ added in v0.0.22
type RunEventRecorder struct {
// contains filtered or unexported fields
}
RunEventRecorder is the run-scoped durable projection of a live event stream. It coalesces high-frequency text deltas while leaving the client-facing stream untouched. Close must be called after the stream has been drained.
func NewRunEventRecorder ¶ added in v0.0.22
NewRunEventRecorder creates a recorder for one relayed run or merged relay.
func (*RunEventRecorder) Close ¶ added in v0.0.22
func (r *RunEventRecorder) Close()
Close attempts any incomplete final turn's buffered deltas once.
func (*RunEventRecorder) Observe ¶ added in v0.0.22
func (r *RunEventRecorder) Observe(ev session.Event)
Observe adds ev to the durable projection. Availability is live-only and is omitted without disturbing buffered deltas. Delta events are buffered in bounded UTF-8 chunks; every other projected event first flushes buffered deltas and is then appended itself. Every projected event is attempted exactly once because EventLog.Append may return an error after durably writing it.
type RunSteerAcknowledgement ¶ added in v0.0.39
type RunSteerAcknowledgement struct {
Outcome agent.SteerOutcome
RunID string
MessageID string
}
RunSteerAcknowledgement is the bounded correlation returned by strict steer and retraction controls.
type ScheduleManagerConfig ¶
type ScheduleManagerConfig struct {
// Store is the port.SessionStore the schedule's origin validation reads
// (validateScheduleOrigin). It is also the ScheduleStore discovery source
// when ScheduleStore is nil (the scheduleStoreProvider accessor).
Store port.SessionStore
// ScheduleStore is the OPTIONAL explicit port.ScheduleStore override (the
// --schedule-store-url composition path). When non-nil it WINS over the
// Store type-assertion discovery: the registry is a remote driver, not the
// session store's own accessor, so the in-chat Schedule tool + the tick
// loop + the fire path all share the ONE resolveScheduleStore resolution.
// When nil, behaviour is byte-identical to the accessor discovery.
ScheduleStore port.ScheduleStore
Now func() time.Time
ModelInventory ModelInventory
Models *atomic.Pointer[[]*mecatlv1.ModelInfo]
Diagnostics port.Diagnostics
// OwnershipEnforced mirrors server.Config.OwnershipEnforced (true only when
// the request edge has a verifier wired). It gates whether the manager
// namespaces the store-facing schedule key by verified caller (issue #368):
// a schedule Name is a caller-chosen, human-readable
// key exactly like a memory key, so two DIFFERENT owners may legitimately
// pick the identical name without colliding — mirroring
// memory.CallerStore's owner-digest scheme. When false (no verifier wired,
// or a standalone-constructed manager that leaves this unset), the key is
// BYTE-IDENTICAL to today: the bare literal name, one flat namespace.
OwnershipEnforced bool
}
ScheduleManagerConfig is the pre-Service construction input for a scheduleManager: the plain inputs available before buildEngine. Store is a port.SessionStore; the ScheduleStore is type-asserted off it via the scheduleStoreProvider accessor (the jsonlstore + redisstore expose one). ScheduleStore is the OPTIONAL explicit override (the --schedule-store-url composition path): when non-nil it WINS over the accessor discovery, so a driver-backed registry backs the in-chat Schedule TOOL too — the registry is a remote driver, NOT the session store's own accessor, so the tool + tick loop + fire path share the ONE resolveScheduleStore resolution (no split-brain with an accessor-ful store + the override, and no absent tool with an accessor-less store + the override). When nil, behaviour is byte-identical to the accessor discovery (the pre-override posture). Now is the now-func (the same clock the Service uses). Models is the SHARED model-inventory pointer (selector validation reads *models.Load()); the Service passes its own pointer so SetModels keeps working with no second copy. Diagnostics is the operational diagnostic seam; nil-safe. A store that backs no ScheduleStore yields a nil manager (NewScheduleManager returns nil).
type ScheduleManagerImpl ¶
type ScheduleManagerImpl = scheduleManager
ScheduleManagerImpl exposes the concrete manager type to the COMPOSITION layer (internal/app) only: buildEngine must thread the ONE manager it constructs through to server.Config.ScheduleManager, and an interface-typed round-trip would re-introduce the typed-nil hazard (a nil *scheduleManager boxed in a non-nil port.ScheduleManager defeats the mgr == nil honest-absence gate). Consumers still interact with the manager via the port.ScheduleManager interface; the alias exists ONLY so the concrete value crosses the adapter boundary with its nil-ness intact. It adds no methods to the public surface beyond what port.ScheduleManager already declares.
type ScheduleServer ¶
type ScheduleServer struct {
mecatlv1.UnimplementedScheduleServiceServer
// contains filtered or unexported fields
}
ScheduleServer implements mecatlv1.ScheduleServiceServer over the shared Service. It embeds UnimplementedScheduleServiceServer for forward compatibility (require_unimplemented_servers=true in buf.gen.yaml), mirroring HarnessServer's embed of UnimplementedHarnessServiceServer.
func NewScheduleServer ¶
func NewScheduleServer(svc *Service) *ScheduleServer
NewScheduleServer constructs a ScheduleServer over svc.
func (*ScheduleServer) CreateSchedule ¶
func (h *ScheduleServer) CreateSchedule(ctx context.Context, req *mecatlv1.CreateScheduleRequest) (*mecatlv1.CreateScheduleResponse, error)
CreateSchedule saves a new schedule (upsert by name) and returns the created aggregate. The create-seam (composition) validates the spec fail-closed — the trigger XOR, the prompt-or-parts rule, the cron grammar, the Mutating/Mode invariant — so the handler only checks the wire-required fields (spec non-nil, name non-empty) and delegates.
func (*ScheduleServer) DeleteSchedule ¶
func (h *ScheduleServer) DeleteSchedule(ctx context.Context, req *mecatlv1.DeleteScheduleRequest) (*mecatlv1.DeleteScheduleResponse, error)
DeleteSchedule removes the schedule stored under name. Idempotent.
func (*ScheduleServer) FireNow ¶
func (h *ScheduleServer) FireNow(ctx context.Context, req *mecatlv1.FireNowRequest) (*mecatlv1.FireNowResponse, error)
FireNow forces an immediate fire of the schedule, returning the per-fire session id (fire_id == session_id on the wire).
func (*ScheduleServer) GetFire ¶
func (h *ScheduleServer) GetFire(ctx context.Context, req *mecatlv1.GetFireRequest) (*mecatlv1.GetFireResponse, error)
GetFire returns the fire record stored under fire_id.
func (*ScheduleServer) GetSchedule ¶
func (h *ScheduleServer) GetSchedule(ctx context.Context, req *mecatlv1.GetScheduleRequest) (*mecatlv1.GetScheduleResponse, error)
GetSchedule returns the schedule stored under name.
func (*ScheduleServer) ListFires ¶
func (h *ScheduleServer) ListFires(ctx context.Context, req *mecatlv1.ListFiresRequest) (*mecatlv1.ListFiresResponse, error)
ListFires returns the fire records for a schedule.
func (*ScheduleServer) ListSchedules ¶
func (h *ScheduleServer) ListSchedules(ctx context.Context, _ *mecatlv1.ListSchedulesRequest) (*mecatlv1.ListSchedulesResponse, error)
ListSchedules returns all stored schedules.
func (*ScheduleServer) PauseSchedule ¶
func (h *ScheduleServer) PauseSchedule(ctx context.Context, req *mecatlv1.PauseScheduleRequest) (*mecatlv1.PauseScheduleResponse, error)
PauseSchedule disables a schedule without deleting it (Enabled=false).
func (*ScheduleServer) ResumeSchedule ¶
func (h *ScheduleServer) ResumeSchedule(ctx context.Context, req *mecatlv1.ResumeScheduleRequest) (*mecatlv1.ResumeScheduleResponse, error)
ResumeSchedule re-enables a paused schedule (Enabled=true).
func (*ScheduleServer) UpdateSchedule ¶
func (h *ScheduleServer) UpdateSchedule(ctx context.Context, req *mecatlv1.UpdateScheduleRequest) (*mecatlv1.UpdateScheduleResponse, error)
UpdateSchedule updates an existing schedule's spec (the State half is preserved on overwrite — the Service.Load+Save discipline).
type ScopedWorktree ¶ added in v0.0.24
type ScopedWorktree struct {
Selector string
Label string
// Branch is the short branch name, such as "feat/x", not a full ref.
Branch string
Revision string
Bare bool
}
ScopedWorktree is the additive path-free discovery projection used by the server-owned placement cutover. Selector is ephemeral authority; the other fields are display-only.
type SecurityConfig ¶
type SecurityConfig struct {
// AuthToken, when non-empty, requires every RPC/request to present
// Authorization: Bearer <AuthToken> (gRPC: the "authorization" metadata
// header). An empty token disables authentication (dev mode).
AuthToken string
// RateLimit is the sustained per-client request rate in requests/second. A
// value <= 0 disables rate limiting entirely. Limiting is applied both
// per-client (keyed by token or peer IP) and globally.
RateLimit float64
// RateBurst is the token-bucket burst size. It defaults to a small multiple
// of RateLimit when left zero (see newLimiterSet).
RateBurst int
// Validator, when non-nil, turns caller identity ON: every request must
// present a bearer the validator vouches for, and the verified principal is
// stashed on the handler context (session.WithPrincipal). Nil (the default)
// leaves the path byte-identical to a mecatl without identity: no
// validation, no principal, no new failure mode.
Validator PrincipalValidator
// HTTP bearer challenges are deliberately generic. The configured resource is
// a service-wide base identity, while API requests are subordinate paths and
// the request Host is untrusted; this middleware cannot prove an exact RFC
// 9728 resource identity for a request.
// Diagnostics receives sanitized authentication outcome records. Accepted
// outcomes are emitted once per closed category/transport pair; rejected and
// unavailable outcomes remain per-request. Nil leaves diagnostics disabled;
// records never include credentials or validator errors.
Diagnostics port.Diagnostics
}
SecurityConfig configures the reusable authentication and rate-limiting interceptors/middleware shared by the gRPC and HTTP surfaces. The zero value is a valid, fully permissive (dev) configuration: no token is required and no rate limit is enforced.
Both knobs compose with the loopback-default + off-loopback warning in the composition root (cmd/mecated): an empty AuthToken on a non-loopback bind is a loud-but-not-fatal misconfiguration the operator is warned about.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the surface-agnostic application service shared by the gRPC and HTTP/SSE adapters. It owns session lifecycle (create/lookup), starts runs on the shared engine, and keeps a registry of in-flight runs keyed by session id so out-of-band approve/cancel reach the right run. It is safe for concurrent use.
Persistence and auto-resume ¶
The engine mutates the session in place over a run and the Service persists it to the SessionStore at meaningful transitions: at create, when the run pauses awaiting approval (see Persist), and at run end. With a durable store (jsonlstore via --store-dir) the latest snapshot therefore survives a process restart.
A registered run is removed by the wire adapter that owns the stream: each adapter `defer`s FinishRun(id, run) after it finishes draining run.Events() (the channel closes when the run terminates). The Service does not deregister runs on its own — there is no internal relay goroutine that does so.
GetSession, Approve and Cancel for a session id NOT in the in-memory run registry fall back to SessionStore.Load, so a session created (or last persisted) before a restart is still observable and its terminal/awaiting state is loadable. An in-flight STREAM does not survive a restart: the *agent.Run and its event channel live only in process memory. A persisted awaiting session is resumable instead: an approval that finds it only in the store (ResolveRunAsk → resolvePersistedRunAsk, or Approve → resumeFromAwaiting) rebuilds the engine and re-enters the loop at the ask via Engine.ResumeApproval. A Cancel that finds the session only in the store — with no live run — returns ErrNoActiveRun rather than silently succeeding.
func NewService ¶
NewService validates cfg and constructs a Service.
func (*Service) AbandonLearningAttempt ¶ added in v0.0.24
func (s *Service) AbandonLearningAttempt(ctx context.Context, id, expectedVersion string) (*mecatlv1.LearningAttempt, error)
AbandonLearningAttempt performs only the repository's non-compensating CAS transition. It does not roll back or invalidate downstream artifacts.
func (*Service) ActivateLearnedSkill ¶
func (s *Service) ActivateLearnedSkill(ctx context.Context, r *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*Service) ActiveRuns ¶
ActiveRuns reports the number of sessions this process is actively driving — the count of held session leases (one per live run-entry). It is the "draining: N active runs" figure a graceful shutdown logs after Drain, so the operator can see how many in-flight runs the bounded GracefulStop will cancel. Zero (or no lease wired) means nothing is in flight.
func (*Service) AdmittedModes ¶ added in v0.0.50
func (s *Service) AdmittedModes() []session.PermissionMode
AdmittedModes lists, in plan → yolo order, the permission modes this server admits for a session right now (the ceiling and the auto checker requirement), so a client can offer exactly the modes SetMode will accept.
func (*Service) ApplySessionCleanup ¶
ApplySessionCleanup re-plans before mutation, then serializes each deletion by run-entry lock -> maintenance lease -> backend family lock (inside Delete).
func (*Service) Approve ¶
func (s *Service) Approve(ctx context.Context, id session.SessionID, askID string, verdict session.ApprovalVerdict) error
Approve resolves the paused permission ask on the session's in-flight run with the client's three-way verdict (deny / allow-once / allow-always).
SAME-PROCESS path FIRST: a live registered run resolves the ask over its in-memory channel while this process still holds the session lease. On a LookupRun MISS — typically the process that parked the ask died and a different process now serves the Approve — it falls to resumeFromAwaiting: if the persisted session is in StateAwaiting it loads the snapshot, rebuilds the engine, re-enters the loop AT the ask, applies the verdict, and drives to completion; the caller relays the returned run's events (the resumed run is registered like any other). A non-awaiting (idle/completed/cancelled/failed) session stays terminal and yields ErrNoActiveRun; an unknown session yields ErrNotFound. The returned run, when non-nil, is the resumed run the wire adapter must drain + FinishRun.
func (*Service) ApprovePlan ¶
func (s *Service) ApprovePlan(ctx context.Context, id session.SessionID, targetMode session.PermissionMode, note string) (<-chan session.Event, error)
ApprovePlan is the atomic plan-approval RPC (issue #206). It resolves a parked PLAN-ORIGINATED permission ask (a PresentPlan call surfaced in plan mode) and — on an ALLOW verdict — starts a FRESH continuation run carrying the harness proceed message, streaming BOTH runs' events on the one returned channel. It composes EXISTING seams and adds NO new engine machinery:
- A live run for the session is rejected (ErrNotAwaitingPlan → 409): an approve mid-run must use the Converse ResumeApproval frame, not this RPC.
- The session is loaded and must be StateAwaiting on a PLAN-ORIGINATED ask (sess.PendingAsk().Origin() == AskOriginPlan); anything else is ErrNotAwaitingPlan. An unknown session is ErrNotFound (via GetSession).
- targetMode → verdict: ModeDefault → VerdictAllowOnce (flip to default), ModeAccept → VerdictAllowAlways (flip to accept-edits), ModePlan/zero → VerdictDeny (iterate, no flip, no continuation run).
- resumeFromAwaiting re-enters the loop AT the ask: Engine.ResumeApproval applies the verdict, the allow paths set r.planApprovedTarget, the run terminates StopPlanApproved, and terminateComplete flips the session mode at the terminal boundary. (The deny path synthesises a deny result and the loop CONTINUES in plan mode — but since this is a fresh resumed run with no further model turns scripted, it ends at StopPlanApproved-less terminal; the session stays in plan mode for the next prompt.)
- ATOMIC CONTINUATION (allow paths only): after the resumed run drains, a FRESH run is started via the SAME StartRunContent path (loadAndReopen → engineAndEnvironmentFor CASE 1 rebuild picks up the FLIPPED mode → execute model) carrying the proceed message agent.PlanApprovedProceedText + an optional operator note. Both runs' events are relayed on the returned channel. On deny, NO continuation run starts (the session stays in plan mode; the model re-plans on the next prompt).
The returned channel carries the MERGED event stream of the resumed run and (on allow) the continuation run, closing once both have ended. The caller (gRPC/HTTP relay) owns the wire discipline: appendEvent per event, skip the three log-only kinds on the client wire, Persist on EvPermissionAsk, and — critically — CANCEL ctx on a send error / client disconnect so this method's internal ctx-watcher cancels the LIVE run (the run is registered in s.runs like any other; this method deregisters it after drain). The caller MUST cancel the passed ctx once it stops draining, or the run can wedge behind a dead relay (mirrors the run.Cancel() the live relays call on disconnect).
func (*Service) ApproveRun ¶
func (s *Service) ApproveRun(ctx context.Context, id session.SessionID, askID string, verdict session.ApprovalVerdict, expectedRunID string) (*agent.Run, error)
ApproveRun is Approve plus the resumed *agent.Run handle. On the SAME-PROCESS path (a live registered run) it resolves the ask over the channel and returns (nil, nil): there is no new run, the existing relay delivers the verdict's effects. On the rehydrate path (no live run, the session is awaiting) it returns the freshly-registered resumed run so the caller can relay its events and FinishRun it after the drain. A nil run with a nil error means "the same-process channel handled it; keep relaying the existing stream".
CONCURRENCY: two Approves for the SAME awaiting session that both MISS the live-run fast path must NOT both spawn a resumed run (Engine.ResumeApproval spawns the driving goroutine immediately, so the pending tool would execute twice). The resume decision is therefore serialized per session via s.resumeMu: under the per-session lock the loser re-checks LookupRun, sees the winner's now-registered run, and routes its verdict to that run's channel (the same-process path) — the pending tool runs EXACTLY ONCE. The common live-run case takes the service lock only long enough to order approval against lease-loss invalidation.
WIRE EXPOSURE: no wire route calls Approve/ApproveRun; their callers are in-process tests. resumeFromAwaiting is still reached from the wire through ApprovePlan (gRPC ApprovePlan, HTTP POST /v1/sessions/{id}/plan:approve), which relays the continuation run. Converse resolves only its own live run. Client ask approval goes through gRPC ResolveRunAsk and HTTP POST /v1/sessions/{id}/controls/resolve-ask → Service.ResolveRunAsk → resolvePersistedRunAsk, the acknowledgement-only, Service-owned transition above.
func (*Service) ArchiveLearnedSkill ¶
func (s *Service) ArchiveLearnedSkill(ctx context.Context, r *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*Service) BindPlacement ¶ added in v0.0.24
func (s *Service) BindPlacement(ctx context.Context, selector PlacementSelector, operation PlacementOperation) (PlacementBinding, error)
BindPlacement atomically authorizes and resolves a placement through the deployment provider. The caller principal comes only from the authenticated context and the scope only from trusted composition; neither is supplied by the selector or inferred from possession of its opaque ID.
func (*Service) CanProcessSchedule ¶
CanProcessSchedule reports whether a durable schedule is eligible to be claimed by this deployment's scheduler. Rejected legacy state is logged before the scheduler's claim fence so it cannot revive an off-root filesystem path.
func (*Service) Cancel ¶
Cancel cancels the session's in-flight run. Store fallback: ErrNotFound when the session is unknown, ErrNoActiveRun when it exists only in the store with no live run (unlike Approve, Cancel never resumes a persisted awaiting run).
func (*Service) CancelChild ¶
CancelChild cancels ONE child (a subagent) of the session's in-flight run, addressed by its child session id (the `agentId:` trailer / subagent.start child_id). It mirrors Approve exactly: LookupRun, then the store fallback — ErrNotFound for an unknown session, ErrNoActiveRun for a known-but-runless one. A live run that does not hold the child (unknown id, or the child already finished) yields ErrChildNotFound (HTTP 404; the stream-frame path ignores that race by design instead).
func (*Service) CancelMCPAuthorization ¶ added in v0.0.26
func (s *Service) CancelMCPAuthorization(ctx context.Context, id session.SessionID, control MCPAuthorizationControl) (MCPAuthorizationResult, error)
CancelMCPAuthorization precisely cancels and resolves one pending control.
func (*Service) CancelRun ¶ added in v0.0.39
func (s *Service) CancelRun(ctx context.Context, id session.SessionID, expectedRunID string) (RunControlAcknowledgement, error)
CancelRun cancels only the exact addressed live run.
func (*Service) CancelRunSteer ¶ added in v0.0.39
func (s *Service) CancelRunSteer(ctx context.Context, id session.SessionID, expectedRunID, messageID string) (RunSteerAcknowledgement, error)
CancelRunSteer retracts only from the exact addressed live run.
func (*Service) CancelSessionCleanup ¶
CancelSessionCleanup stops future items; committed deletions are not rolled back.
func (*Service) CancelSteer ¶
func (s *Service) CancelSteer(ctx context.Context, id session.SessionID, expectedRunID string) (agent.SteerOutcome, error)
CancelSteer retracts the session's live run's PENDING (un-drained) steer, reporting the engine's authoritative outcome (retracted / none_pending). It is the Service-level owner of the steer_cancel route — the wire handler drives THIS (mirror of how Cancel routes through the Service), so the live-run lookup stays single-owner and the deferred HTTP/SSE steer endpoint reuses the same Service decision rather than re-deriving it. A steer that already drained at a turn boundary is ordinary recorded history and cannot be retracted (the engine reports none_pending then: the drain won). A session with no live run reports none_pending (there is no inbox to retract from — the steer that would be pending is already lost with its run; the inbox is a best-effort in-memory contract). expectedRunID has the same optional strictness as the other run controls: when set, no absent or replacement run may be touched. The wire's steer_cancel message_id never crosses the Service (the ack-side echo is the caller's own frame field), so the signature stays correlation-id-free.
func (*Service) CancelTeammate ¶
CancelTeammate cancels ONE member of a RUNNING team mid-round, via the Supervisor.CancelMember seam (the same per-member cancel the Converse-path registry route fires; BACKGROUND-SUBAGENTS D4, issue #29). The member de-schedules with the cancelled stop reason and its claimed tasks release; the run continues and still delivers its outcome.
The phase is read briefly under Service.mu and released BEFORE touching the supervisor — the same no-lock-across-supervisor discipline as SendTeammateMessage. The teamRunning requirement is ALSO what makes the lock-free CancelMember map read safe: the supervisor's members map is written only by AddMember, and every AddMember serialises BEFORE the teamCreated→teamRunning flip (SpawnTeammate holds the per-team `run` mutex across its phase check + AddMember and rejects once the team has started) — admitting a teamCreated team here would race a concurrent SpawnTeammate's map write. The race on the OTHER side of the gate is benign: RunTeam may finish between the phase read and CancelMember, in which case the late cancel lands as an idempotent no-op (the member's ctx just goes unobserved). Cancelling an already-stopped-but-PRESENT member is likewise an honest no-op (nil success); only an unknown member name returns ErrChildNotFound. A team that is not running (teamCreated / teamDone) returns ErrTeamNotRunning.
func (*Service) CancelWorkspaceEnrollment ¶ added in v0.0.26
func (s *Service) CancelWorkspaceEnrollment(ctx context.Context, id session.SessionID, enrollmentID session.WorkspaceEnrollmentID) (WorkspaceEnrollmentProjection, error)
CancelWorkspaceEnrollment cancels one exact bundle and clears its prompt gate.
func (*Service) CleanupTeam ¶
CleanupTeam drops a created or done team from the registry and frees its slot. Forked member workspaces are torn down by the supervisor when RunTeam returns, so a done team is safe to drop; this releases the registry entry. A team whose phase is teamRunning is NOT dropped — deleting it out from under the in-flight RunTeam would orphan the live supervisor — so it returns ErrTeamRunning (FailedPrecondition) instead. It returns ErrNotFound for an unknown team.
func (*Service) ClearSessionSuccessor ¶ added in v0.0.24
func (s *Service) ClearSessionSuccessor(ctx context.Context, source session.SessionID, placement SuccessorPlacement) (session.SessionID, error)
ClearSessionSuccessor cancels any exact source lifecycle, waits for its relay to deregister, then creates a distinct empty-history peer while preserving source ownership, labels, limits, mode, and exact placement unless a current source-scoped selector is supplied.
func (*Service) ClientMCPFromWire ¶ added in v0.0.22
func (s *Service) ClientMCPFromWire(servers []mcp.ClientServer) (ClientMCPGrant, error)
ClientMCPFromWire is the SINGLE enforcement seam for client-provided MCP servers arriving on a session-creating API request. Both wire transports call it; neither classifies an entry itself.
Order is load-bearing, and it is the ordinary "400 before 501" shape:
- CLASSIFY, unconditionally, through the shared mcp.PartitionClientServers — the same validator the ACP surface uses. A stdio or sse entry is rejected AS SUCH on every deployment, so "No stdio MCP, ever" (AGENTS.md) stays an invariant of the request shape rather than a downstream consequence of a policy flag that some future composition root might flip. Classification is pure string work: it opens no connection and has no side effect, so running it on a deployment that will refuse anyway costs nothing.
- GATE on the deployment policy. A well-formed request that this deployment does not accept is refused with the typed ErrClientMCPUnsupported (UNIMPLEMENTED / 501), never silently dropped — a client whose servers were quietly ignored would run a session it believes has tools it does not have.
An empty list returns an EMPTY grant and no error on EVERY deployment: sending no MCP servers is not a use of the feature, so a TCP deployment must not fail an ordinary create that merely carries an empty repeated field.
It returns a ClientMCPGrant rather than raw specs so that "these specs were classified and permitted" is enforced by the type system: WithClientMCP accepts nothing else, and the grant's field is unexported, so this function is the only place a non-empty one comes from.
Header values never appear in the returned error (they are secret-shaped).
func (*Service) Close ¶
func (s *Service) Close()
Close tears down all per-session engines' MCP managers. It is the Service's shutdown hook so a process exit does not leak any per-session MCP connection. It is safe to call multiple times.
func (*Service) CloseSession ¶
CloseSession tears down the per-session engine registered for id (if any) and removes it from the registry. It is idempotent: an id with no per-session engine is a no-op. The ACP adapter calls it when an editor disconnects so a session's client-provided MCP manager does not outlive the session.
SAFE under an in-flight run (so it needs no run-aware guard like the team path): the close func is the MCP manager's Close, a GRACEFUL shutdown — the underlying go-sdk ClientSession.Close "prevents new requests from being handled, and WAITS for ongoing requests to return" before terminating the connection, and is documented idempotent + concurrency-safe. A disconnect that races a live engine.Run dispatching an MCP tool call therefore does NOT yank the connection mid-call: Close blocks until that CallTool returns (or the jsonrpc2 layer retires it with an error response the remoteTool maps to a model-facing error). The editor disconnect already implies the run is being abandoned, so blocking briefly for the in-flight call to unwind is the correct, leak-free behaviour.
func (*Service) CompactSession ¶ added in v0.0.22
func (s *Service) CompactSession(ctx context.Context, id session.SessionID, caller *session.Principal) (agent.ManualCompactionResult, error)
CompactSession applies one configured compaction pass to an owned main-chat session at a turn boundary. caller is the verified transport principal; it is bound to ctx only when the context has no principal, and a mismatch is rejected. The operation is serialized against run entry and cross-process mutations. A successful no-op saves only when the compactor returned accounting; it never appends compaction events.
func (*Service) CompatibilityInfo ¶ added in v0.0.22
func (s *Service) CompatibilityInfo(ctx context.Context) *mecatlv1.GetCompatibilityInfoResponse
CompatibilityInfo returns the deployment's compatibility descriptor: the API major, the operator-enabled capabilities, the build's supported feature identifiers, and the optional build/deployment labels.
It exists so a client can answer "what is this server?" WITHOUT creating a probe session. ServerCapabilities is exposed only by this compatibility descriptor; session responses retain only session-specific media capabilities.
The capabilities half REUSES s.capabilities() rather than recomputing a parallel projection. That is the load-bearing part: every compatibility transport reads the same service value.
The two vocabularies stay SEPARATE by design. capabilities answers "what has this operator enabled?" and changes with operator config; features answers "what does this build implement?" and changes on upgrade. Folding one into the other makes a --no-shell deployment indistinguishable from version skew.
func (*Service) ConnectWorkspaceServices ¶ added in v0.0.26
func (s *Service) ConnectWorkspaceServices(ctx context.Context, id session.SessionID) (WorkspaceEnrollmentProjection, error)
ConnectWorkspaceServices begins or observes the one pre-prompt enrollment bundle.
func (*Service) CreateACPSession ¶ added in v0.0.24
func (s *Service) CreateACPSession(ctx context.Context, cwd string, mode session.PermissionMode, limits session.Limits, specs []mcp.ServerConfig, overlay ACPEnvironmentOverlay) (*session.Session, error)
CreateACPSession binds the composition-configured default placement before it consults the ACP cwd assertion. cwd can only confirm that trusted binding; it is never used to construct or select an environment.
func (*Service) CreateSchedule ¶
func (s *Service) CreateSchedule(ctx context.Context, spec port.ScheduleSpec) (port.Schedule, error)
CreateSchedule delegates to the embedded scheduleManager (the single schedule truth). The manager validates the spec fail-closed, applies the create-seam defaults, computes the first NextFireAt, and Saves. When no manager is wired (the store backs no ScheduleStore) it returns ErrNoScheduleStore — the byte-identical no-scheduling path the gRPC/REST handlers map to Unimplemented.
func (*Service) CreateSession ¶
func (s *Service) CreateSession(ctx context.Context, mode session.PermissionMode, limits session.Limits) (*session.Session, error)
CreateSession allocates a new idle session on the server-owned default placement, persists it, and returns it. An unspecified mode falls back to DefaultMode. It is the no-selector, no-MCP fast path.
func (*Service) CreateSessionWithMCP ¶
func (s *Service) CreateSessionWithMCP(ctx context.Context, mode session.PermissionMode, limits session.Limits, specs []mcp.ServerConfig) (*session.Session, error)
CreateSessionWithMCP creates a session that mounts the client-provided streaming-HTTP MCP servers (specs) for the lifetime of that session, via a PER-SESSION engine. It is the ACP session/new entry for an editor that supplies mcpServers.
- With NO specs it takes the same path as CreateSession: the session uses the SHARED engine unless Config.MCPBroker or Config.LearnedSkills forces a per-session engine.
- A per-session engine REQUIRES Config.SessionEngine or Config.SessionEngineWithTools (else ErrInvalidArgument: "per-session engine not supported"); it is built via that factory and, on success, registered under the new session id so StartRun routes the session's runs to it. A factory error is returned as-is (the caller maps it).
The per-session engine's MCP manager is torn down by CloseSession (editor disconnect) or by the Service's Close.
func (*Service) CreateSessionWithProfile ¶
func (s *Service) CreateSessionWithProfile(ctx context.Context, mode session.PermissionMode, limits session.Limits, sel ProviderSelector, profile SessionProfile, opts ...CreateSessionOption) (*session.Session, error)
CreateSessionWithProfile creates a session with an optional provider/model selector and tool-surface profile. It is the gRPC/HTTP create entrypoint. Ordinary sessions use the shared engine unless the selector, profile, broker, or learned skills require Config.SessionEngine or Config.SessionEngineWithTools. Agent-bound sessions always require Config.AgentDefSessionEngine instead. Unknown/unavailable providers surface as ErrInvalidArgument. ModelID without ProviderID is rejected for ordinary sessions; agent-bound sessions resolve it through the dedicated factory. Placement is server-owned, including authorized execution-template selections, no-FS profiles, and trusted supplied bindings.
opts is the variadic options pattern (CreateSessionOption): WithSessionID overrides the minted id (the scheduler fire path mints a "sched--"-prefixed id). Zero opts mints a fresh id as usual.
func (*Service) CreateSessionWithProvider ¶
func (s *Service) CreateSessionWithProvider(ctx context.Context, mode session.PermissionMode, limits session.Limits, sel ProviderSelector) (*session.Session, error)
CreateSessionWithProvider creates a session bound to a non-default provider/model selector via a PER-SESSION engine, with no client MCP and the DEFAULT profile.
func (*Service) CreateTeamForSession ¶ added in v0.0.24
func (s *Service) CreateTeamForSession(ctx context.Context, source session.SessionID, name, goal string, maxTeamTokens int, members []agent.MemberSpec) (string, []team.Member, error)
CreateTeamForSession creates a team in an owning session's exact authorized environment. The caller supplies no path or selector; no-FS is never upgraded.
func (*Service) CreateTeamOnDefaultPlacement ¶ added in v0.0.24
func (s *Service) CreateTeamOnDefaultPlacement(ctx context.Context, name, goal string, maxTeamTokens int, members []agent.MemberSpec) (string, []team.Member, error)
CreateTeamOnDefaultPlacement allocates a new agent team over the trusted default placement, stores an optional initial roster, and returns its server-assigned id together with that roster. Declarations intentionally remain engine-free and member-session-free until RunTeam acquires its operation pin and member leases.
Enrolment is ATOMIC: if any member fails to enrol the whole team is abandoned — it is never registered (no partial team leaks) and does not consume a MaxTeams slot. The supervisor's AddMember already cleans up a member's own fork on its own failure, and an un-registered supervisor (with whatever members it did add) is simply garbage-collected. The failing member's error is classified via classifyAddMemberErr. members may be empty: the team is created empty and the client can still SpawnTeammate before RunTeam.
maxTeamTokens is the per-request team-wide token budget, folded into the server-configured Config.TeamTokenBudget TIGHTEN-ONLY at create time (agent.TightenTeamTokenBudget, issue #36): a non-positive value inherits the server budget; a positive value applies only when it is lower.
It returns ErrTeamsDisabled when teams are not enabled. CreateTeamOnDefaultPlacement is the explicit trusted-composition entry for a team that is not derived from an existing session.
func (*Service) DecideDream ¶
func (s *Service) DecideDream(ctx context.Context, id string, decision DreamDecision) (DreamReceipt, error)
DecideDream applies or dismisses one retained opaque plan. No operation material is accepted from the caller, so the authoritative retained plan is the only mutation input.
func (*Service) DecideLearningProposal ¶
func (s *Service) DecideLearningProposal(ctx context.Context, id, expected, decision, reason, project string) (*mecatlv1.LearningProposal, error)
DecideLearningProposal rejects or approves a staged proposal using version CAS.
func (*Service) DeleteSchedule ¶
DeleteSchedule delegates to the embedded scheduleManager. Idempotent (the store's Delete discipline).
func (*Service) DeleteSession ¶
DeleteSession physically removes an owned main session and all store-managed sidecars. Absence and foreign ownership are both idempotent success, preventing deletion from becoming an ownership oracle. Infrastructure failures remain loud.
func (*Service) DeleteSessionForRetention ¶
DeleteSessionForRetention removes one session selected by the composition-owned automatic-retention policy. Unlike DeleteSession it is not restricted to main chats, but it still serializes against run entry, acquires the cross-process mutation lease, and revalidates durable taxonomy and lifecycle after acquiring that lease. It is an internal composition callback, never a wire operation.
func (*Service) DeleteSessionForRetentionCandidate ¶
func (s *Service) DeleteSessionForRetentionCandidate(ctx context.Context, candidate port.SessionDiscoveryMeta) error
DeleteSessionForRetentionCandidate removes one exact planner candidate while keeping the mandatory maintenance/run-entry lease exclusions held through the backend's atomic final metadata comparison and family deletion. Automatic and manual retention intentionally use the same exclusion posture.
func (*Service) Diagnostics ¶
func (s *Service) Diagnostics() port.Diagnostics
Diagnostics returns the operational diagnostics sink the Service was configured with. It is the read-side accessor composition (the scheduler's FireFunc) uses to WARN on a non-fatal degradation (e.g. a carried-context prior-session-load failure that degrades to fresh-context). A NopDiagnostics is returned when none was wired (the constructor guarantees non-nil, so this is belt-and-suspenders).
func (*Service) DiffLearnedSkillVersions ¶
func (s *Service) DiffLearnedSkillVersions(ctx context.Context, request *mecatlv1.DiffLearnedSkillVersionsRequest) (*mecatlv1.DiffLearnedSkillVersionsResponse, error)
func (*Service) Drain ¶
func (s *Service) Drain()
Drain arms the drain gate (mecak8s): subsequent run-entries (StartRunContent / resumeFromAwaiting via acquireLease) are rejected with ErrUnavailable so a shutting-down replica stops accepting new runs and a rolling update steers traffic to a survivor. It is idempotent and safe to call from a signal handler or the /drain HTTP endpoint. In-flight runs are NOT cancelled here — that is the bounded GracefulStop's job in the cmd binary; Drain only gates new entries. The gate is one-way: there is no un-drain (a draining replica is retiring).
func (*Service) EmitScheduleEvent ¶
func (s *Service) EmitScheduleEvent(ctx context.Context, payload session.SchedulePayload)
EmitScheduleEvent appends a SchedulePayload as an EvSchedule* event to the fire session's durable EventLog. It is the composition-injected emit callback the scheduler invokes (via scheduler.Config.EmitScheduleEvent) for fired/failed/ skipped fires. Delivery is durable-log-only (pull-only via GetFire/ListFires); a live broadcast stream is not implemented. A skipped fire (no session id) is dropped from the durable log (the log is session-keyed) and surfaces only via the operator diagnostic.
It routes through the ONE appendEvent chokepoint so the lifecycle events are stamped with the acting caller exactly like the fire's run events — the scheduler's system principal for a tick fire, the requester for a manual FireNow (every durable append path stamps). ctx is the caller's; it is cancel-detached here so a fire's finished/cancelled ctx cannot abort the durable append, while its VALUES (the principal) survive.
The fire closes its session, releasing the session lease, before the scheduler reports the outcome, so the append holds the lease itself for its duration. reaffirmLease skips the run-entry drain gate: a fire settled during shutdown still records its terminal event.
func (*Service) EndScheduledRun ¶ added in v0.0.50
EndScheduledRun closes a scheduled session's broker session when its run ends: the design ends a scheduled run's authority with the run. The scheduler calls it with the fire's session as each fire returns; the session itself is kept for result delivery. Only a scheduled session's broker session is closed, so an interactive session passed by mistake keeps its broker session. A failure is logged, not returned.
func (*Service) EndSession ¶
EndSession is the precondition-checked sibling of CloseSession: the surface-facing session-end entry for the gRPC/HTTP transports (the ACP adapter calls the void CloseSession directly on disconnect). It verifies the session exists and serializes against run admission. A locally registered run owns the session until its relay calls FinishRun, so close fails with ErrFailedPrecondition without releasing the lease or tearing down any local engine, policy, or environment. A persisted awaiting snapshot with no local run is not active ownership: teardown releases local resources while leaving the durable PendingAsk untouched. Closing an already-released (but still persisted) session remains idempotent. EndSession never deletes the persisted snapshot and never cancels a run; cancellation is an orthogonal operation.
func (*Service) FinishRun ¶
FinishRun removes run from the in-flight registry for id. It is the EXPORTED counterpart of register that every wire adapter must call (typically via `defer`) once it has finished draining run.Events(), so a completed run does not leak in the registry. It is idempotent and only removes the entry if run is still the one recorded (a later run for the same session is never clobbered), so it is safe to call unconditionally after a drain.
func (*Service) FireNow ¶
FireNow delegates to the embedded scheduleManager. The manager distinguishes the no-scheduler states: a nil manager (no ScheduleStore at all) → ErrNoScheduleStore here; a non-nil manager with no scheduler wired → ErrSchedulerNotRunning (the manager's own FireNow). A wired scheduler's sentinels (ErrScheduleDisabled / ErrFireNowOverlap / ErrScheduleExhausted / ErrScheduleNotLeader) are mapped by the manager.
func (*Service) ForkSessionSuccessor ¶ added in v0.0.24
func (s *Service) ForkSessionSuccessor(ctx context.Context, req ForkSuccessorRequest) (session.SessionID, error)
ForkSessionSuccessor creates a history-carrying peer on inherited exact placement or a freshly matched source-scoped worktree.
func (*Service) GenerateDream ¶
func (s *Service) GenerateDream(ctx context.Context, target DreamTarget) (DreamReview, error)
GenerateDream creates an opaque, bounded-lifetime review plan for a closed target.
func (*Service) GetFire ¶
GetFire delegates to the embedded scheduleManager, which resolves and authorizes the stored physical parent key before returning the fire.
func (*Service) GetGuardrailReviewDetail ¶ added in v0.0.41
func (s *Service) GetGuardrailReviewDetail(ctx context.Context, ref session.SessionID, reviewID string) (GuardrailReviewDetail, error)
GetGuardrailReviewDetail reads only live process-local detail. It first owner- authorizes the presented root/child session handle, then requires the registry's exact root relation, and finally reauthorizes the root. Foreign, stale, and arbitrary child handles are concealed identically.
func (*Service) GetLearnedSkill ¶
func (s *Service) GetLearnedSkill(ctx context.Context, request *mecatlv1.GetLearnedSkillRequest) (*mecatlv1.GetLearnedSkillResponse, error)
func (*Service) GetLearningAttempt ¶ added in v0.0.24
func (s *Service) GetLearningAttempt(ctx context.Context, id string) (*mecatlv1.LearningAttempt, error)
GetLearningAttempt returns one content-free projection from the verified caller's private attempt partition.
func (*Service) GetLearningProposal ¶
func (s *Service) GetLearningProposal(ctx context.Context, id, project string) (*mecatlv1.LearningProposal, error)
GetLearningProposal returns one proposal from the caller's selected partition.
func (*Service) GetMcpPrompt ¶
func (s *Service) GetMcpPrompt(ctx context.Context, server, name string, args map[string]string) (mcp.PromptResult, error)
GetMcpPrompt expands a named prompt with args on the named server. server and name must be non-empty; a nil provider yields ErrNoMCPProvider; an unknown server name yields ErrInvalidArgument; an unknown prompt, missing required arg, or other expansion fault on a known server yields ErrInternal.
func (*Service) GetSchedule ¶
GetSchedule returns an owned schedule by name. A mismatch deliberately has the same port-level not-found result as an absent schedule.
func (*Service) GetSession ¶
GetSession returns the persisted session under id, or ErrNotFound.
Absence, foreign ownership, and a broken store are deliberately ONE caller-visible answer, so a caller cannot probe for another owner's ids. That concealment is owed to the CALLER only: an infrastructure failure is logged for the operator, because otherwise a storage outage is indistinguishable from mass deletion from both sides at once. A genuine not-found is the normal case and stays silent.
func (*Service) GetSoul ¶
GetSoul returns the resolved soul (persona) snapshot (the build-time projection injected via Config.Soul). It is a pure read of that snapshot; no live re-read. When no soul source is wired it returns an empty snapshot (present=false), never nil, so the wire adapters always have a SoulInfo to serialize.
func (*Service) GetTranscript ¶
func (s *Service) GetTranscript(ctx context.Context, id session.SessionID) (*SessionTranscript, error)
GetTranscript performs exactly one ownership-checked SessionStore load and returns its current Conversation. It deliberately bypasses run entry: no environment resolution, engine rehydration, lease, or persistence occurs.
func (*Service) GetUserModel ¶
GetUserModel returns the CURRENT user-model entries (a live read of the wired lister) plus aggregate size + hash over the rendered "key — description" rows. A nil lister (user model disabled) yields an empty response. A store fault is returned as ErrInternal so the wire adapters surface it distinctly.
func (*Service) GetUserModelDetail ¶
func (s *Service) GetUserModelDetail(ctx context.Context, key string) (*mecatlv1.UserModelDetail, error)
GetUserModelDetail returns one exact entry without exposing a mutation path. Base-only listers honestly return nil detail.
func (*Service) GracefulDrain ¶ added in v0.0.24
GracefulDrain settles locally-owned runs after closing admission. Executing runs are cancelled and must be joined by their relay (FinishRun) before their terminal aggregate is persisted and their lease is explicitly released. Awaiting runs are cancelled only in memory: preserveDurable prevents the relay from replacing the already-persisted PendingAsk handoff point. A context timeout invalidates local mutation capability and stops renewal, but never explicitly releases an unjoined run's lease; TTL then governs takeover.
func (*Service) HasScheduler ¶
HasScheduler reports whether a scheduler was wired into the embedded scheduleManager. It is the read-side companion to SetScheduler: nil-safe (the byte-identical default wires no scheduler, and a store with no ScheduleStore has no manager at all).
func (*Service) IsDraining ¶
IsDraining reports whether the drain gate is armed. It is the read-side companion to Drain: a cmd binary's dynamic ReadyFunc (mecak8s /readyz) closes over it so readiness flips to not-ready the moment Drain is armed, without coupling the probe to the Service's internal atomic. It is the ReadyFunc's read; ActiveRuns is the "how many in flight" figure. Safe to call from a signal handler / HTTP handler goroutine.
func (*Service) IsLive ¶
IsLive reports whether a top-level Service run or an engine-owned delegation child is currently in flight in this process. The two registries share one predicate so stale reconciliation and every destructive maintenance path see the same process-local exclusion. Cross-process liveness is protected by the separately configured SessionLease.
func (*Service) LeaseSweepDisabled ¶
LeaseSweepDisabled reports whether SessionStale has stickily disabled the staleness sweep for the process lifetime (an ErrLeaseUnsupported backend). Exported for internal/app's Step 4 sweep to check before scanning, mirroring SessionStale/IsLive/Diagnostics.
func (*Service) ListAgents ¶
ListAgents returns the resolved agent-definition snapshot (possibly empty). It is a pure read of the injected snapshot; no live discovery.
func (*Service) ListCommandsForSession ¶ added in v0.0.24
func (s *Service) ListCommandsForSession(ctx context.Context, id session.SessionID) ([]Command, error)
ListCommandsForSession owner-authorizes the session and borrows its independent command source binding without reattaching execution.
func (*Service) ListExecutionTemplates ¶ added in v0.0.48
func (s *Service) ListExecutionTemplates(ctx context.Context) ([]ExecutionTemplateInfo, string, error)
ListExecutionTemplates returns a filtered, bounded inventory for the verified owner.
func (*Service) ListGuardrailCoverage ¶ added in v0.0.41
func (s *Service) ListGuardrailCoverage(ctx context.Context, id session.SessionID) (GuardrailCoverage, error)
ListGuardrailCoverage owner-authorizes before asking composition for the exact session-specific catalog/rule projection.
func (*Service) ListLearnedSkills ¶
func (s *Service) ListLearnedSkills(ctx context.Context, request *mecatlv1.ListLearnedSkillsRequest) (*mecatlv1.ListLearnedSkillsResponse, error)
func (*Service) ListLearningAttempts ¶ added in v0.0.24
func (s *Service) ListLearningAttempts(ctx context.Context, stateValue, cursor string, limit int) (*mecatlv1.ListLearningAttemptsResponse, error)
ListLearningAttempts returns one bounded page from the verified caller's private attempt partition. The repository's opaque next ID is the cursor.
func (*Service) ListLearningProposals ¶
func (s *Service) ListLearningProposals(ctx context.Context, statusValue, cursor string, limit int, project string) (*mecatlv1.ListLearningProposalsResponse, error)
ListLearningProposals returns one bounded partition page.
func (*Service) ListMcpPrompts ¶
ListMcpPrompts returns the prompt snapshots for server (empty = union of all servers). Returns nil with no provider configured.
func (*Service) ListMcpResources ¶
ListMcpResources returns the resource snapshots for server (empty = union of all servers). Returns nil with no provider configured.
func (*Service) ListMcpSources ¶
func (s *Service) ListMcpSources(_ context.Context) MCPSourceStatus
ListMcpSources returns a detached cached published/pre-shadow inventory and reconciler status. It never consults an upstream source.
func (*Service) ListModelSnapshot ¶ added in v0.0.41
func (s *Service) ListModelSnapshot(ctx context.Context) ModelSnapshot
ListModelSnapshot refreshes once, then captures models and statuses together.
func (*Service) ListModels ¶
ListModels returns the resolved selectable-model inventory snapshot (possibly empty) — every available provider's catalog models, secret-free. When an on-demand refresher is installed (issue #262, R1.4) it is invoked FIRST (self-guarded: it decides which providers are stale and enforces its own cooldown) so a provider that just came back up is reflected on THIS call, with no restart; with no refresher installed (the byte-identical default) this is a pure read of the injected snapshot, exactly as before.
func (*Service) ListSchedules ¶
ListSchedules filters before returning the collection so an ownerless or foreign record cannot affect caller-visible list metadata.
func (*Service) ListSessionMcpConnectors ¶ added in v0.0.34
func (s *Service) ListSessionMcpConnectors(ctx context.Context, id session.SessionID) (brokercontract.ConnectorInventory, error)
ListSessionMcpConnectors reads broker-local publication under the exact saved binding. In particular, it never opens an attachment or observes enrollment.
func (*Service) ListSessionPage ¶
func (s *Service) ListSessionPage(ctx context.Context, request ListSessionsPageRequest) (ListSessionsPage, error)
ListSessionPage returns one bounded keyset page. The optional pager is a deployment capability: unsupported stores fail honestly instead of falling back to an unbounded response. Ownership criteria are sent to the store so filtering occurs before page formation and TotalCount.
func (*Service) ListSessions ¶
func (s *Service) ListSessions(ctx context.Context) ([]SessionSummary, error)
ListSessions returns the stored-session inventory — the picker metadata a client renders to let an operator open an EXISTING session by id (issue #245). It is backed by port.PrunableStore.List (type-asserted on the configured store); a store that does not implement PrunableStore, or one that returns ErrPruneUnsupported, degrades to an EMPTY slice — never an error — so a no-persistence/cloud server honestly reports "no sessions".
Each row carries only picker metadata (id, timestamps, state, turn count, model id); NO conversation content is loaded. For each PrunableStore row the service best-effort loads the snapshot to populate State/Turns/CreatedAtUnix and ModelID from the session's own PERSISTED sess.ModelID (NOT Service.ResolvedModel, which falls back to the shared default engine's model for a non-live session — that would misreport every session that was ever run on a non-default model); a Load failure leaves those fields zeroed but still returns the row (a corrupt snapshot file is surfaced in the picker with its id/mtime, so the operator can see it exists even if it can't be opened). Rows are sorted most-recently-active first (modified_at descending). Read-only.
Cost: each row does a Store.Load (jsonlstore: reads the last snapshot line). Acceptable for a picker; there is no pagination.
FAST PATH: when the store implements port.MetaLister (jsonlstore does), ListSessions uses MetaList — a CHEAP last-line read that skips the full conversation — instead of a full Load per row. This keeps listing N sessions O(N × last-line-read) rather than O(N × filesize) for large histories. The MetaLister path is the same latest-line-wins source Load trusts; a store that does NOT implement MetaLister falls back to the Load-per-row path (correct, just slower; memstore/redisstore/grpcdriver use it until they implement MetaList). The Title from MetaList is the snapshot Title ONLY — the lazy deriveTitle fallback (walking the conversation) is NOT available on the fast path; a session whose Title was never seeded shows "" on the fast path. That is acceptable for a picker (the snapshot Title is seeded by the loop on the first genuine prompt, so the common case is populated).
func (*Service) ListSkillChanges ¶
func (s *Service) ListSkillChanges(ctx context.Context, r *mecatlv1.ListSkillChangesRequest) (*mecatlv1.ListSkillChangesResponse, error)
func (*Service) ListSkillFiles ¶ added in v0.0.48
func (s *Service) ListSkillFiles(ctx context.Context, name string) ([]*mecatlv1.SkillFileInfo, error)
ListSkillFiles lists the readable files of one skill in the caller's skill view: SKILL.md first, then the bundled assets sorted by logical name.
func (*Service) ListSkills ¶
ListSkills returns the current skills inventory (possibly empty).
func (*Service) ListTeam ¶
func (s *Service) ListTeam(ctx context.Context, teamID string) ([]team.Member, []team.Task, bool, error)
ListTeam returns the team roster, the shared task list, and whether the team has reached quiescence.
func (*Service) ListToolHiveGroups ¶
ListToolHiveGroups derives the distinct, non-empty ToolHive groups from the same cached inventory as ListMcpSources. It considers only sources whose Kind is "toolhive". Output is sorted for deterministic results.
func (*Service) ListWorktreesForSession ¶ added in v0.0.24
func (s *Service) ListWorktreesForSession(ctx context.Context, id session.SessionID) ([]ScopedWorktree, error)
ListWorktreesForSession owner-authorizes and exactly reattaches before enumeration, then issues caller/source-scoped selectors without retaining them. A no-FS source is an empty result and invokes no lister.
func (*Service) LoadACPSession ¶ added in v0.0.24
func (s *Service) LoadACPSession(ctx context.Context, id session.SessionID, cwd string, specs []mcp.ServerConfig, overlay ACPEnvironmentOverlay) (*session.Session, error)
LoadACPSession owner-authorizes the snapshot, reattaches its exact persisted EnvironmentRef, and only then checks cwd. It never binds a current default or constructs an environment from cwd.
func (*Service) LoadSession ¶
LoadSession resumes a previously-persisted session so a subsequent StartRun continues it. It loads the latest snapshot from the store and, if the session is in a terminal state, REOPENS/INTERRUPTS/RECOVERS it to StateIdle (preserving the conversation history) and re-persists, so the next prompt's BeginTurn is legal. A cleanly COMPLETED session is reopened via Reopen; a CANCELLED session (an interrupted turn) is recovered via Interrupt, which also repairs the history (closing out any orphaned tool calls); a FAILED session (a transient provider failure) is recovered via Recover, the same history repair (issue #51) — recovery makes retry possible, not guaranteed. A session already idle is returned unchanged.
It returns ErrNotFound when the store has no snapshot for id (including the in-memory store after a process restart, or when no store-dir is configured and the id was never created in this process).
func (*Service) LoadSessionWithMCP ¶
func (s *Service) LoadSessionWithMCP(ctx context.Context, id session.SessionID, specs []mcp.ServerConfig) (*session.Session, error)
LoadSessionWithMCP resumes a previously-persisted session AND re-mounts the client-provided streaming-HTTP MCP servers (specs) for the lifetime of that session, via a PER-SESSION engine. It is the ACP session/load entry for an editor that re-supplies mcpServers on resume — the symmetric sibling of CreateSessionWithMCP (session/new).
- With NO specs it delegates to LoadSession: the resumed session uses the SHARED engine, with zero per-session overhead and no registry entry.
- With specs it REQUIRES Config.SessionEngine (else ErrInvalidArgument: "client MCP not supported"); it loads + reopens-if-completed FIRST (so an unknown id fails fast — ErrNotFound — without a wasted MCP connect), then builds the per-session engine via that factory and, on success, registers it under the session id so StartRun routes the session's runs to it. A factory error is returned as-is (the caller maps it).
The per-session engine's MCP manager is torn down by CloseSession (editor disconnect) or by the Service's Close.
func (*Service) LookupRun ¶
LookupRun returns the in-flight run for a session and true, or false if no run is currently registered for it.
func (*Service) LostOwnershipCandidates ¶ added in v0.0.36
LostOwnershipCandidates returns the ids this process currently holds a lease-loss tombstone for (lostOwnership, set by onLeaseLost). It is an in-memory snapshot of Service's OWN bookkeeping, NOT a store-wide scan: lostOwnership is already scoped to exactly the ids this process itself definitively lost, so there is no risk of the unbounded Acquire fan-out a store-wide scan of every awaiting/cancelled session would cause — those are the STEADY STATE for huge numbers of ordinary finished sessions (issue #1334). Exported for internal/app's composition-level sweep, mirroring StaleRunningCandidates.
func (*Service) MCPAuthorizationPresentation ¶ added in v0.0.26
func (s *Service) MCPAuthorizationPresentation(ctx context.Context, id session.SessionID, control MCPAuthorizationControl) (string, error)
MCPAuthorizationPresentation returns a live browser URL only after owner authorization and an authoritative lock/lease protected reload.
func (*Service) MaintenanceMutationAvailable ¶
MaintenanceMutationAvailable reports whether destructive maintenance can currently obtain the required process/cross-process exclusion. Composition consults it before starting automatic retention and again before each sweep.
func (*Service) ManualDreamCapabilities ¶
func (s *Service) ManualDreamCapabilities() DreamCapabilities
ManualDreamCapabilities returns a defensive copy of the composition snapshot.
func (*Service) MaybeAutoApprovePlan ¶
MaybeAutoApprovePlan fires the plan-mode auto-approve (issue #206) when the Service observes a parked plan-approval ask on a headless deployment. It is called by the gRPC/HTTP relay loops alongside appendEvent+Persist for every EvPermissionAsk, and by tests simulating the relay. It is a NO-OP unless ALL of the following hold:
- cfg.PlanModeAutoApprove is true (the OPT-IN operator flag — DEFAULT OFF).
- The ask is plan-originated (session.AskOriginPlan — a PresentPlan call).
- The deployment is headless (no interactive human approver — the engine's Deps.Interactive is false). An interactive deployment surfaces the ask to the human instead; auto-approve must NOT pre-empt a human.
When all three hold, an opted-in live run uses exact plan resolution and its reserved server continuation. Legacy live and restored runs keep their existing auto-approve choreography. The loud diagnostic tells the operator that no human reviewed the plan. This never resolves an ordinary ask and does not bypass the PresentPlan gate.
func (*Service) OwnershipEnforced ¶
OwnershipEnforced reports whether caller ownership is active. Composition uses it only where ownerless persisted metadata must fail closed before reconstructing a caller context; resource decisions still flow through ownsResource/authorizeSession.
func (*Service) PauseSchedule ¶
PauseSchedule delegates to the embedded scheduleManager. The manager calls SetEnabled — the dedicated atomic flag update — because Save CANNOT mutate Enabled (Save preserves the existing State half on a Spec overwrite).
func (*Service) Persist ¶
Persist saves the current state of the session backing id, if a run is registered for it. It is the seam the adapters call when a run enters the awaiting state (so a persisted awaiting session is loadable for re-attach after a restart) and at run end (so the terminal state is durable). The engine mutates the session in place, so this captures whatever state it is in now. A best-effort no-op when no run is registered.
When the session is StateAwaiting, Persist also marks the runState.awaiting flag. Close uses that signal to protect the durable awaiting snapshot before cancelling the local run in memory, preventing the terminal relay from overwriting the awaiting resume point with cancelled. Persist is called by the relay/test AFTER observing an event (EvPermissionAsk → loop parked, or EvResult → loop done), so reading sess.State here races no concurrent loop write (the loop is parked or exited; the state write happened-before the event the caller observed). The flag is a server-layer atomic, never read by the engine loop.
func (*Service) PlanSessionCleanup ¶
func (s *Service) PlanSessionCleanup(ctx context.Context, scope CleanupScope) (CleanupPlan, error)
PlanSessionCleanup performs no writes. The explicit management gate runs before the store-wide pager, so tenants cannot form pages or aggregate counts.
func (*Service) ProviderCapabilities ¶
func (s *Service) ProviderCapabilities() port.ProviderCapabilities
ProviderCapabilities reports the DEFAULT provider+model's multimodal input support, so a surface adapter can advertise it (e.g. ACP promptCapabilities) and loud-reject unsupported prompt content. It returns the composition-computed DefaultCapabilities — the catalog ∩ adapter INTERSECTION for the default provider+cfg.Model — NOT the bare engine.Capabilities() (adapter-only, which would over-advertise a model the adapter can transmit to but the catalog says cannot take image). This is the SAME value the CreateSessionResponse echoes for a default-engine session, so the ACP gate and the wire echo cannot disagree.
ACP carries NO per-session provider/model selector (session/new passes only mcpServers, never a selector), so every ACP session rides the DEFAULT engine and the Agent's capture-once a.caps = svc.ProviderCapabilities() is correct for every ACP session. A per-session ACP capability gate is needed only if ACP gains a per-session selector.
func (*Service) ProviderStatuses ¶
func (s *Service) ProviderStatuses() []*mecatlv1.ProviderStatus
ProviderStatuses is the status-only projection for Go callers. Wire handlers use ListModelSnapshot so models and statuses share one captured generation.
func (*Service) PublishSessionEvent ¶
PublishSessionEvent fans the event to every subscriber registered for the given session id. It is NON-BLOCKING: a full subscriber channel drops the event (the subscriber is dead/disconnected — drain-to-discard without wedging the producer). Events published here are the SAME events the run's own Events() channel carries (projection equivalence); the subscriber receives the raw session.Event, never a proto type. The loop stays storage-agnostic — it never calls this; the relay or the delivery driver (deliverFireResult) publishes.
func (*Service) ReadMcpResource ¶
func (s *Service) ReadMcpResource(ctx context.Context, server, uri string) (mcp.ResourceContents, error)
ReadMcpResource reads a single resource by URI from the named server. server and uri must be non-empty; a nil provider yields ErrNoMCPProvider; an unknown server name yields ErrInvalidArgument; a read/transport fault on a known server yields ErrInternal.
func (*Service) ReadSkillFile ¶ added in v0.0.48
ReadSkillFile returns the text of one file of a skill in the caller's skill view.
func (*Service) ReattachPlacement ¶ added in v0.0.24
func (s *Service) ReattachPlacement(ctx context.Context, ref session.EnvironmentRef) (PlacementBinding, error)
ReattachPlacement authorizes and resolves the exact persisted environment identity. It never invokes Bind and therefore cannot follow a changed default.
func (*Service) ReattachPlacementForBinding ¶ added in v0.0.42
func (s *Service) ReattachPlacementForBinding(ctx context.Context, ref session.EnvironmentRef, bindingID session.SessionID) (PlacementBinding, error)
ReattachPlacementForBinding supplies the durable session reference identity required by allocating remote providers.
func (*Service) ReattachPlacementInScope ¶ added in v0.0.24
func (s *Service) ReattachPlacementInScope(ctx context.Context, ref session.EnvironmentRef, scope string) (PlacementBinding, error)
ReattachPlacementInScope requires the durable schedule scope to match this deployment before reauthorizing and resolving the exact persisted ref.
func (*Service) RecheckMCPAuthorization ¶ added in v0.0.26
func (s *Service) RecheckMCPAuthorization(ctx context.Context, id session.SessionID, control MCPAuthorizationControl) (MCPAuthorizationResult, error)
RecheckMCPAuthorization observes the exact broker transaction. Pending is inert; granted and terminal outcomes have exactly one continuation winner.
func (*Service) ReconcileLeaseLossTombstone ¶ added in v0.0.36
func (s *Service) ReconcileLeaseLossTombstone(ctx context.Context, id session.SessionID) (bool, error)
ReconcileLeaseLossTombstone is StaleRunningCandidates/SettleIfStale's counterpart for the OTHER shape issue #1334 fixes: onLeaseLost drives the session OUT of StateRunning as part of handling the loss — to awaiting via the preserveAwaiting branch, or eventually to cancelled via run.Cancel() — so the StateRunning-only staleness sweep above can never rediscover it, and the lostOwnership tombstone (by design a PERMANENT fail-fast for every ordinary caller, see lostOwnership's own doc comment) would otherwise clear only via CloseSession or a process restart, regardless of whether the original loss was a genuine takeover or a false positive.
Unlike SettleIfStale/acquireMutationLeaseForStaleSettle this performs NO session-state repair and installs NO renewer: an awaiting/cancelled session has no run currently driving it (HOLD-FOR-SESSION-LIFE is tied to an active run), so re-acquiring and holding the lease here would leak it. Instead this is a bounded TRIAL Acquire immediately released — proof the lease is genuinely free, nothing ever held across the call — mirroring SessionStale's own trial-lease refinement (same owner suffix, same fail-safe-on-any- ambiguity posture: ErrLeaseHeld, a real Acquire error, or an unsupported backend all leave the tombstone untouched; only a successful trial proves the backend record is free, whether because a peer genuinely released it or because it simply expired once this process's renewer stopped ticking after the loss — Renew's ErrLeaseHeld cannot distinguish the two, so real time passing is what makes a re-Acquire safe, exactly as acquireMutationLeaseForStaleSettle's doc explains for the StateRunning case). Clearing the tombstone only unblocks the NEXT genuine run-entry (StartRunContent / ApproveRun's resumeFromAwaiting); that entry's own loadAndReopen/resumeFromAwaiting still performs the actual session-state repair (Interrupt for cancelled; the awaiting resume machinery for awaiting) exactly as it always has — this function never touches session state, only the local lease bookkeeping that was blocking it.
Reports whether it actually cleared the tombstone (false, nil is the honest no-op for "still held" / "already cleared by a concurrent caller"/"no tombstone for this id"). Exported for internal/app's composition-level sweep, mirroring SessionStale/SettleIfStale/StaleRunningCandidates.
CloseSession can no longer interleave WITHIN this call: closeSessionLocal (its one tombstone-clearing chokepoint) now also takes leaseLossMu for id, so a concurrent close either completes entirely before this call starts or blocks until this call's whole trial (Acquire + Release + tombstone-clear) has finished — never mid-trial (issue #1334 panel follow-up; closeSessionLocal's own doc comment has the lock-order rationale). The pre-trial and post-trial re-checks of s.lostOwnership below are kept anyway as defense in depth (e.g. a concurrent caller that legitimately re-acquired for real between the checks), each still re-reading under s.mu, the same "last write wins, re-verified under the lock" posture SettleIfStale documents for its own TOCTOU window.
The trial Acquire below is additionally serialized against onLeaseLost's real Release for the same id via leaseLossMu (its own doc comment has the full rationale): held for this function's ENTIRE body, so the trial can never overlap a same-id Release still in flight.
func (*Service) ReconcileReferenceIntents ¶ added in v0.0.42
ReconcileReferenceIntents resolves the provider's bounded, client-scoped ambiguous publication and deletion outcomes against exact durable sessions.
func (*Service) RecoverNotice ¶
RecoverNotice returns the pre-flight advisory message for session id when the last loadAndReopen recovered a PERMANENTLY-failed session. It returns "" when there is no pending notice (the common case: a freshly-created session, a transient failure, or a follow-up prompt on the same recovered session). Each notice is consumed on the first call — a subsequent call for the same id returns "" — so the advisory is emitted ONCE per recovery and never repeats.
It is called by the relay adapters (gRPC Converse, HTTP relayRunSSE) right after StartRunContent to inject an EvRecoverNotice synthetic event BEFORE the main event loop, so the client sees the warning before the provider call burns tokens on the same unrecoverable error.
func (*Service) ReflectSession ¶
func (s *Service) ReflectSession(ctx context.Context, id session.SessionID) (*mecatlv1.ReflectionReceipt, error)
ReflectSession explicitly reflects a completed caller-owned session.
func (*Service) RefreshMcpSources ¶ added in v0.0.41
func (s *Service) RefreshMcpSources(ctx context.Context, id session.SessionID) (MCPRefreshResult, error)
RefreshMcpSources reconciles direct MCP sources and stable-unions missing active direct names into one eligible owner-controlled ordinary root.
func (*Service) RejectLearnedSkill ¶
func (s *Service) RejectLearnedSkill(ctx context.Context, r *mecatlv1.MutateLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*Service) RenameSession ¶
func (s *Service) RenameSession(ctx context.Context, id session.SessionID, title string) (*session.Session, error)
RenameSession applies an explicit operator title change to an owned main session. Authorization, kind/state/liveness checks, and lease acquisition are serialized under the same per-session mutex used by prompt starts.
func (*Service) ResolveApprovalRun ¶ added in v0.0.41
func (s *Service) ResolveApprovalRun(ctx context.Context, id session.SessionID, resolution agent.ApprovalResolution, expectedRunID string) (*agent.Run, error)
ResolveApprovalRun atomically validates guardrail purpose and review identity before submitting a verdict. Validation failures leave the pending hold intact.
func (*Service) ResolvePlanAsk ¶ added in v0.0.41
func (s *Service) ResolvePlanAsk(ctx context.Context, id session.SessionID, expectedRunID, askID string, verdict session.ApprovalVerdict) (RunAskAcknowledgement, error)
ResolvePlanAsk resolves one plan-originated ask on the exact authorized run. It acknowledges acceptance only; durable activity carries both terminals.
func (*Service) ResolveRunAsk ¶ added in v0.0.39
func (s *Service) ResolveRunAsk(ctx context.Context, id session.SessionID, expectedRunID, askID string, verdict session.ApprovalVerdict) (RunAskAcknowledgement, error)
ResolveRunAsk resolves exactly one ordinary ask on one exact run. A restored awaiting run is accepted under the caller context, then driven and relayed by the Service lifecycle independently of the unary request.
func (*Service) ResolveScopedRunAsk ¶ added in v0.0.41
func (s *Service) ResolveScopedRunAsk(ctx context.Context, id session.SessionID, expectedRunID string, resolution agent.ApprovalResolution) (RunAskAcknowledgement, error)
ResolveScopedRunAsk resolves one guardrail-scoped ask on one exact run while preserving the purpose acknowledgement displayed to the operator.
func (*Service) ResolvedModel ¶
func (s *Service) ResolvedModel(id session.SessionID) ResolvedModel
ResolvedModel reports the EFFECTIVE provider+model for an in-memory session engine registration, or the composition-computed shared-engine default when no registration exists. Snapshot-aware transport and run-entry paths use resolvedModelFor so persisted selector labels and mode-specific slots remain authoritative across restart.
MODE→MODEL RE-EMIT: the identity is read from the REGISTERED per-session engine (se.providerID/se.modelID). After a plan↔execute switch triggers the run-entry rebuild (engineAndEnvironmentFor swaps the registered engine on the next StartRun), ResolvedModel AUTOMATICALLY returns the re-resolved model — no change here. The ORDERING is deliberate: a SetMode response echoes the still-CURRENT (pre-rebuild) model (the model is fixed per turn; the rebuild happens at the NEXT run-entry, not on the SetMode call itself), so a client reads the new model from GetSession or the next CreateSession-style echo AFTER the mode-changed turn begins — never mid-turn.
The provider/model IDENTITY never recomputes within a single engine generation (the per-session-engine value was computed ONCE in composition; the default-path ids are the baked DefaultResolvedModel ids), so the wire echo cannot drift from the engine the session actually runs on. The ContextWindow SCALAR is resolved LIVE-FIRST at call time for BOTH branches via the injected Config.ResolveContextWindow (so a GetSession after the live model-catalog swap reflects the live window, not the curated-catalog floor a live-only model lacks) — mirroring the live-first modality input SessionCapabilities already consumes. The injected resolver is the ECHO resolver (echoWindowResolver): blocked discovery without positive exact metadata returns 0, whereas the engine always has a defensive 128k floor. A wired zero is authoritative even over a positive seed; a nil resolver retains the supplied value. Policy-admitted unknown windows echo 128k.
func (*Service) ResumeSchedule ¶
ResumeSchedule delegates to the embedded scheduleManager. See PauseSchedule.
func (*Service) RetryFailedRun ¶
RetryFailedRun resumes the failed model step from the persisted conversation state without submitting another prompt. Live system instructions and operator context are resolved again for the retry. The caller owns draining the returned run and calling FinishRun, exactly as for StartRunContent. Eligibility is derived exclusively from the persisted typed terminal metadata and is consumed only after every fallible setup step has succeeded and the recovered idle snapshot has been saved.
func (*Service) RetryLearningAttempt ¶ added in v0.0.24
func (s *Service) RetryLearningAttempt(ctx context.Context, id, expectedVersion string) (*mecatlv1.LearningAttempt, error)
RetryLearningAttempt performs only the repository's failed-to-queued CAS transition. Scheduling and downstream artifacts are deliberately untouched.
func (*Service) RetryWorkspaceEnrollment ¶ added in v0.0.26
func (s *Service) RetryWorkspaceEnrollment(ctx context.Context, id session.SessionID, enrollmentID session.WorkspaceEnrollmentID) (WorkspaceEnrollmentProjection, error)
RetryWorkspaceEnrollment cancels one exact bundle before beginning a replacement, holding runEntryMu continuously across both so no prompt can enter between the cancellation and the replacement begin (a single acquire-then-release pair per call, rather than composing the two public methods, each of which independently acquires and releases the lock).
func (*Service) RollbackLearnedSkill ¶
func (s *Service) RollbackLearnedSkill(ctx context.Context, r *mecatlv1.RollbackLearnedSkillRequest) (*mecatlv1.MutateLearnedSkillResponse, error)
func (*Service) RunTeam ¶
func (s *Service) RunTeam(ctx context.Context, teamID string, sink func(agent.TeamEvent)) (agent.TeamOutcome, error)
RunTeam drives the team to quiescence, invoking sink for every member event, and returns the outcome. It blocks for the team's lifetime; the gRPC handler runs it on the request goroutine and forwards events to the stream.
Like the per-session run-entry funnel (acquireLease), RunTeam honours the drain gate (mecak8s): once Drain is armed a draining replica refuses a NEW team run BEFORE the phase flip / team claim so a shutting-down pod steers team traffic to a survivor. An in-flight RunTeam is NOT cancelled by Drain itself (that is the bounded GracefulStop's job). The gate starts false — byte-identical default when Drain has not been called.
func (*Service) ScheduleFirePlacement ¶ added in v0.0.49
func (s *Service) ScheduleFirePlacement(ctx context.Context, spec port.ScheduleSpec, fireID session.SessionID) (PlacementBinding, error)
ScheduleFirePlacement reauthorizes the stored placement; a borrowed native schedule additionally reserves a distinct reference for the fire session. Session creation owns rollback and commit of the returned binding.
func (*Service) ScheduleManager ¶
func (s *Service) ScheduleManager() port.ScheduleManager
ScheduleManager returns the consumer-local port.ScheduleManager the model-facing Schedule tool drives: the embedded scheduleManager (the single truth) — NOT the Service itself. It returns nil UNLESS the configured Store backs a port.ScheduleStore (the manager constructor returns nil in that case) — the SAME conditional gate the capabilities echo (Scheduling) uses, so the tool registration and the capability bit agree and a store-less deployment gets the honest absent-tool path, never a stub. Composition calls it AFTER NewService (the manager is constructed before buildEngine and handed to the Service via Config.ScheduleManager, or self-constructed by the Service from cfg.Store for the legacy test path) and injects the result into the catalog assets for the Schedule tool's registration.
func (*Service) SendTeammateMessage ¶
SendTeammateMessage posts a message into a member's inbox, delivered at that member's next turn boundary. An empty from defaults to the reserved operator identity (team.OperatorSender); a non-empty from is authenticated by team.Send, which rejects any value that is neither a current member nor the operator (ErrUnknownSender → InvalidArgument) so the wire path cannot forge a sender.
func (*Service) SessionCapabilities ¶
func (s *Service) SessionCapabilities(id session.SessionID) port.ProviderCapabilities
SessionCapabilities reports the resolved input capability (catalog ∩ adapter) for the session under id: the per-session engine's precomputed neutral caps when a per-session engine is registered (a non-default provider/model selector or client MCP), else the composition-computed DefaultCapabilities (the shared-engine path). The value was computed ONCE in composition (modelCapability) and stored; SessionCapabilities never recomputes it, so the wire echo cannot drift from the ListModels view. It backs the CreateSessionResponse.session_capabilities echo.
func (*Service) SessionCleanupJob ¶
SessionCleanupJob returns one caller-bound sanitized maintenance projection.
func (*Service) SessionStale ¶
SessionStale reports whether meta's persisted StateRunning snapshot is a crash-orphan (issue #475) rather than a genuinely in-flight run. It decides; it does not write — SettleIfStale performs the actual repair once a caller has decided a candidate is stale. Exported for internal/app's composition- level sweep (Step 4) to consume, mirroring IsLive/Diagnostics.
The order matters and mirrors internal/adapter/scheduler/scheduler.go's shouldReconcileStaleFire/isPriorFireLive (age gate first, lease as a secondary refinement, trial lease released immediately, never held across a write) — an earlier draft of this fix inverted that order and is why the design history in the accompanying plan calls this out explicitly:
- Age horizon (staleSessionWindow) is a HARD PRECONDITION: a fresh snapshot is never stale, no matter what liveness/lease signals say.
- IsLive(id): a same-process live run is never stale.
- If a port.SessionLease is wired, a bounded TRIAL Acquire is the secondary refinement: - ErrLeaseHeld, but s.heldLeases[id] shows THIS process already holds the REAL lease for id: that is the self-held-lease correction — a run that died without releasing its own lease is evidence of staleness, not liveness. Treat it as stale. - ErrLeaseHeld otherwise (a genuinely different, live owner holds it): not stale. - success (nobody held it): release the trial immediately (this function only decides; it never holds a lease across the caller's later write) and report stale. - ErrLeaseUnsupported: sticky-disable the WHOLE sweep for the process lifetime (see LeaseSweepDisabled) rather than silently falling back to local-only liveness for this one candidate — the fallback would reintroduce the exact cross-replica unsoundness the lease branch exists to prevent, for the one backend where this error is actually reachable. Report not stale. - any other error/timeout: fail-safe, not stale.
- No lease wired at all: age + IsLive is the complete policy — a not-live, past-window candidate IS stale (the single-process/file- storage default path).
func (*Service) SetMode ¶
func (s *Service) SetMode(ctx context.Context, id session.SessionID, mode session.PermissionMode) (*session.Session, error)
SetMode changes the permission posture of the session under id and persists the change, returning the updated session. It is the out-of-band mode-switch seam (ACP session/set_mode). It applies to the LIVE session when a run is registered (so the change takes effect immediately for an idle-between-prompts session held in the registry) and otherwise to the stored snapshot.
It returns ErrNotFound for an unknown session, ErrInvalidArgument for an empty mode, and propagates session.ErrIllegalTransition (wrapped as ErrInvalidArgument) when the session is mid-turn (running/awaiting) — the aggregate refuses a mode change while a turn is in flight, so the caller must defer it to the next prompt. The one exception is cancelRefusedAwaiting's recovery for a stored awaiting session whose mode this server refuses. A change to the mode the session already has is a no-op success.
func (*Service) SetModels ¶
SetModels swaps the standalone inventory when Config.ModelInventory is nil. It cannot write a Build-owned inventory. Nil stores an empty slice.
func (*Service) SetModelsRefresher ¶
SetModelsRefresher installs the optional bounded demand callback. Composition owns provider eligibility, active attempts and cooldown; nil leaves list reads pure. The callback is wired once when any available provider has a lister.
func (*Service) SetProviderStatus ¶
func (s *Service) SetProviderStatus(status []*mecatlv1.ProviderStatus)
SetProviderStatus swaps standalone status rows when ModelInventory is nil. It cannot write a Build-owned publication. Nil stores an empty slice.
func (*Service) SetScheduleMinInterval ¶
SetScheduleMinInterval injects the scheduler cadence floor the create-seam enforces (AC1.3). Delegated to the embedded manager: the floor guards the SHARED validateScheduleSpec — the Schedule tool's create AND the REST/gRPC create — whether or not the tick loop runs (a --no-scheduler deployment still manages schedules manually). 0 disables the floor. Called once by composition before serving. No-op when no manager is wired (no schedule create-seam to guard).
func (*Service) SetScheduler ¶
SetScheduler wires a scheduler onto the embedded scheduleManager (the late-bind seam). It is the delegated setter: composition builds the scheduler AFTER NewService (the FireFunc closes over the Service) and attaches it here; the manager holds the atomic scheduler pointer FireNow reads. Nil-safe (no manager wired → no-op, the no-scheduling path). The Service's own s.mu is not involved (the manager's atomic pointer is the single truth); Close/Drain read s.schedMgr.HasScheduler() instead of a Service-held scheduler field.
func (*Service) SetSessionEnvironment ¶
func (s *Service) SetSessionEnvironment(id session.SessionID, env tool.Environment)
SetSessionEnvironment registers a per-session Environment OVERRIDE for id, so a subsequent StartRun uses env as the COMPLETE execution environment (Workspace + optional bound CommandRunner + accurate ref) instead of building one from the shared factories. It is the seam the ACP adapter uses to route a session's file I/O through the editor's fs/* buffers: the ACP adapter constructs a complete shell-less Environment (a real-filesystem Workspace rooted at the session cwd with a local ref, but NO command runner — the editor provides no shell) and registers it here. A second call for the same id replaces the override. The override is evicted by CloseSession (and drained by Close), so the caller MUST pair it with CloseSession on the owning connection's teardown (the ACP adapter tracks the session and does this on disconnect). The gRPC/HTTP surfaces never call this, so their environment path is unchanged (issue #462 phase-2 finding #2).
func (*Service) SettleIfStale ¶
SettleIfStale repairs a session id that a caller has ALREADY decided is stale (via SessionStale): it loads the raw snapshot, re-checks State==StateRunning and !IsLive(id) (closing the TOCTOU between whatever decided staleness and this load — the snapshot may have moved on since, or a genuinely live run may have started in the gap), and if it is genuinely still running and not locally live, abandons it via Session.Abandon() and persists the repair. It performs NO staleness decision of its own.
This is the SWEEP's (Step 4) repair path ONLY: the sweep discovers a candidate id from a metadata scan with no in-memory session for it, so it must Load fresh from the store. A caller that already holds an in-memory *session.Session (Step 3's run-entry funnel, `loadAndReopen`) must NOT call this function — repairing the on-disk copy via a fresh Load would leave the funnel's OWN in-memory sess (already loaded, about to be handed to engine.Run) untouched and still carrying its unpaired tool_use, so the HTTP-400 this whole fix exists to prevent would survive unnoticed. The funnel instead calls sess.Abandon() + Store.Save directly on the session it already holds.
Returns whether it actually settled something (false, nil is the honest no-op result for a session that already moved on, e.g. a race with a genuinely live re-entry or a peer's own settle).
func (*Service) SpawnTeammate ¶
func (s *Service) SpawnTeammate(ctx context.Context, teamID string, spec agent.MemberSpec) (team.Member, error)
SpawnTeammate enrols a member in a team (before RunTeam) and returns its roster entry. A Mutating member requires a configured Forker. It is rejected with ErrTeamRunning once the team has started running: AddMember mutates the Supervisor's unsynchronised member maps, which the in-flight RunTeam is reading.
func (*Service) StaleRunningCandidates ¶
StaleRunningCandidates returns only the metadata needed by the dedicated stale-session reconciler. It is store-wide infrastructure enumeration, not a caller-owned list operation, and accepts only that worker's system root.
func (*Service) StartInteractiveRunContent ¶ added in v0.0.26
func (s *Service) StartInteractiveRunContent(ctx context.Context, id session.SessionID, text string, parts []session.Content) (*agent.Run, error)
StartInteractiveRunContent starts a public HTTP/gRPC run whose transport can present and control browser authorization. Non-interactive adapters must use StartRunContent so protected calls fail without parking.
func (*Service) StartInteractiveRunContentWithPlanContinuation ¶ added in v0.0.41
func (s *Service) StartInteractiveRunContentWithPlanContinuation(ctx context.Context, id session.SessionID, text string, parts []session.Content) (*agent.Run, error)
StartInteractiveRunContentWithPlanContinuation opts a public run into daemon-owned continuation for an exact plan ask. Existing callers retain their client-owned proceed path through StartInteractiveRunContent.
func (*Service) StartRun ¶
func (s *Service) StartRun(ctx context.Context, id session.SessionID, text string) (*agent.Run, error)
StartRun loads the session, builds its workspace, starts a run on the shared engine and registers the *agent.Run so Approve/Cancel can reach it. The caller is responsible for draining run.Events() AND, once the channel closes, for calling FinishRun(id, run) to remove the run from the registry (each wire adapter `defer`s FinishRun after the drain — see grpc.go/http.go/the ACP adapter). It returns ErrNotFound if the session does not exist.
func (*Service) StartRunContent ¶
func (s *Service) StartRunContent(ctx context.Context, id session.SessionID, text string, parts []session.Content) (*agent.Run, error)
StartRunContent is the multimodal sibling of StartRun: it starts a run with a prompt carrying flattened text PLUS non-text media parts (image/audio). text may be "" when parts carries the content; at least one of text/parts must be non-empty (else ErrInvalidArgument). StartRun delegates here with nil parts. The media passes through to the engine untouched — command expansion and the UserPromptSubmit hook operate on the TEXT only (see Engine.Run). All other behaviour (workspace/engine selection, registration, drain contract) is identical to StartRun.
It reopens-if-completed (via loadAndReopen) so a follow-up prompt on a session that cleanly finished a prior turn continues it — the in-process multi-turn counterpart to the cross-process LoadSession resume path. StartRunContent is the public chat-purpose multimodal sibling of StartRun. Only explicitly-stamped main sessions are admitted; delegation children, scheduled sessions, unknown metadata, and every historical child/fire prefix fail closed. The trusted scheduler uses StartScheduledRunContent instead.
func (*Service) StartScheduledRunContent ¶
func (s *Service) StartScheduledRunContent(ctx context.Context, id session.SessionID, text string, parts []session.Content) (*agent.Run, error)
StartScheduledRunContent is the trusted scheduler-purpose entry. It admits explicitly-stamped scheduled sessions and the historical sched-- fallback for legacy unknown snapshots. It is intentionally absent from public transports; scheduler composition calls it directly.
func (*Service) Steer ¶
func (s *Service) Steer(ctx context.Context, id session.SessionID, text string, parts []session.Content, messageID, expectedRunID string) (agent.SteerOutcome, bool, *agent.Run, error)
Steer routes an operator steer (mid-run injected input, issue #512) for a session to the right home. It is the Service-level routing decision the wire-facing steer handler drives: the steer NEVER drops silently.
- LIVE run: if a run is registered AND its steer inbox still accepts it, the text enqueues to that run's steer inbox (the run drains it at the next turn boundary) and the function reports the engine's authoritative outcome (accepted / appended) with promoted=false.
- LOST TERMINAL RACE: no live run, or the live run's inbox already closed (the engine reported too_late — the run went terminal behind the caller's "still running" belief): the steer is PROMOTED into a fresh follow-up run through the EXISTING hardened run-entry funnel — StartRunContent (loadAndReopen + the lease + recover-if-completed / interrupt-if-cancelled / recover-if-failed / abandon-if-crash-orphaned-running) — exactly like a normal follow-up prompt, and reported as (agent.SteerTooLate, true).
The returned promotedRun (non-nil only when promoted) is the registered follow-up run the caller must drain + FinishRun, exactly as StartRunContent's caller does. An unknown session id yields ErrNotFound (via the funnel); a terminal-state repair failure surfaces as the funnel's error.
messageID is the client-minted correlation id of the Steer frame ("" when the caller supplied none). The engine parks it atomically with the pending content so the EvSteer drain echo carries the exact bundle watermark. The ACK-side echo is the caller's own frame field.
func (*Service) SteerRun ¶ added in v0.0.39
func (s *Service) SteerRun(ctx context.Context, id session.SessionID, expectedRunID, text string, parts []session.Content, messageID string) (RunSteerAcknowledgement, error)
SteerRun enqueues only on the exact addressed live run and never promotes.
func (*Service) StorageHealth ¶
func (s *Service) StorageHealth(ctx context.Context) (StorageHealth, error)
StorageHealth returns aggregate storage measurements only after management authorization. Unsupported backends are represented as unavailable data, not measured zero and not an error.
func (*Service) StorageReady ¶
StorageReady reports whether the session store is reachable. It is the readiness probe the cmd binary's ReadyFunc closes over, so /readyz tests the SAME store the Service serves traffic through (not a second client opened in the binary). A non-pinging store (memstore, jsonlstore, grpcdriver — no Ping method) is treated as always ready; a Redis store's Ping determines readiness. The caller should bound ctx (e.g. 2s) so a stalled backend fails the probe quickly rather than wedging readiness.
func (*Service) StreamSessionEvents ¶
func (s *Service) StreamSessionEvents(ctx context.Context, id session.SessionID) (iter.Seq2[session.Event, error], error)
StreamSessionEvents replays a session's durable event log as a lazy iterator over the recorded events. It is the service-layer surface over port.EventLog.Read that the gRPC/HTTP handlers stream to a client opening an existing session (issue #245).
A nil EventLog (no durable log configured) returns ErrNoEventLog so the wire adapters map to UNIMPLEMENTED (HTTP 501) — honestly reporting the surface is absent rather than pretending an unknown id. An unknown/pruned session id yields an EMPTY iterator (absence is data): port.EventLog.Read is defined to return an empty stream for an unknown id, so the service surfaces that verbatim. The loop stays storage-agnostic — this method never starts a run or makes a model call. Read-only.
The returned iterator yields the events the relay PERSISTED — including the three log-only kinds (EvApproval/EvCompactionArchive/EvUserPrompt) a LIVE Converse relay skips on the client wire. The caller (the gRPC/HTTP handler) relays ALL of them: a client opening a PAST session wants the verdicts and user prompts, as they ARE the transcript. They are already metadata-only / redacted by construction (gauntlet #7: no raw args/deny-reason bodies/child content ever cross), so no extra filter applies at this layer.
func (*Service) Subscribe ¶
func (s *Service) Subscribe(ctx context.Context, id session.SessionID) (<-chan session.Event, func(), error)
Subscribe registers a new per-session live event subscriber and returns a receive-only channel of session.Event plus an unsubscribe function. Every call to PublishSessionEvent for the given session id fans the event to ALL currently- registered subscribers. The channel carries a buffer of 64 events (matching a Run's own event buffer). When the channel is full, PublishSessionEvent DROPS the event (non-blocking drain-to-discard — a dead client never wedges the producer). The returned unsubscribe func is IDEMPOTENT (safe to call more than once, e.g. an explicit call plus a deferred one): it removes this subscription and closes the channel exactly once so the subscriber goroutine can exit cleanly.
Subscribe's sole entry point is the gRPC StreamSessionLive wire handler — an UNTRUSTED boundary, not a trusted in-process caller. When OwnershipEnforced is set it authorizes via GetSession (issue #368) before registering a subscriber, so a caller who cannot load the session cannot observe its live events either; the check mirrors StreamSessionEvents exactly.
func (*Service) UndoLearningPromotion ¶
func (s *Service) UndoLearningPromotion(ctx context.Context, id, expected, project string) (*mecatlv1.LearningProposal, error)
UndoLearningPromotion compensates the current linked promotion using version CAS.
func (*Service) UpdateSchedule ¶
func (s *Service) UpdateSchedule(ctx context.Context, spec port.ScheduleSpec) (port.Schedule, error)
UpdateSchedule delegates to the embedded scheduleManager. The manager re-validates the spec (the shared create-seam) and overwrites the Spec half while preserving the State half (firing progress) + the CreatedAt timestamp.
func (*Service) WatchSessionEvents ¶ added in v0.0.22
func (s *Service) WatchSessionEvents(ctx context.Context, id session.SessionID, after port.Cursor, runID string) (iter.Seq2[WatchEnvelope, error], error)
WatchSessionEvents is the DURABLE replay-then-follow read: it replays a session's log from after the given cursor, announces the transition, and follows the tail until the caller stops (issue #821).
It is ONE operation on purpose. The two existing read paths cannot be composed into it without a hole: port.EventLog.Read is a complete durable replay with no position and no follow, and Service.Subscribe is a live in-memory registry with no history and no durability — so "read everything, then subscribe" silently loses whatever was appended between the two steps. A cursor closes that window, because the follow resumes from exactly where the replay stopped.
Both transports (gRPC WatchSessionEvents, SSE GET /v1/sessions/{id}/watch) consume THIS method, which is what makes their envelope sequences identical rather than merely similar (AC7.3). Put transport framing in the handlers and delivery semantics here.
The returned iterator yields at most one error, as its last item, per the port.EventLog convention. A caller that breaks out early releases the watch.
func (*Service) WithAuthorizedSession ¶
func (s *Service) WithAuthorizedSession(ctx context.Context, id session.SessionID, effect func(*session.Session) error) (*session.Session, error)
WithAuthorizedSession serializes a caller-owned side effect with session run entry. It performs an ownership-only preflight before taking caller-selected coordination, then reloads and reauthorizes under runEntryMu immediately before effect. The callback must not call another operation that locks the same session id.
type SessionContextEngineFactory ¶ added in v0.0.41
type SessionContextEngineFactory func(context.Context, session.SessionID, *session.Principal, ExecutionWorkspaceAcquirer, ProviderSelector, []mcp.ServerConfig, SessionProfile, string, session.PermissionMode, []tool.Tool, []string, session.SessionID) (SessionEngineResult, error)
SessionContextEngineFactory builds a session engine with its stored source identity. AgentDefSessionSelectionFromContext selects a bounded agent root, when present. The trailing source ID is set only while constructing a same-placement successor carrying a live instruction snapshot; ordinary builds and rehydration receive empty. sessionToolKeys carries the exact frozen registration names; nil means derive keys from the tools, while a non-nil empty slice requests a frozen empty set.
type SessionEngineFactory ¶
type SessionEngineFactory func(ctx context.Context, sel ProviderSelector, specs []mcp.ServerConfig, profile SessionProfile, workspace string, mode session.PermissionMode) (SessionEngineResult, error)
SessionEngineFactory builds a PER-SESSION agent engine over a non-default provider/model selector AND/OR the client-provided streaming-HTTP MCP servers (specs), returning a SessionEngineResult (engine + per-session capabilities + close func) and an error. It is the seam the ACP adapter uses to mount an editor's session/new mcpServers AND the seam the gRPC/HTTP CreateSession path uses to bind a per-session provider/model — both WITHOUT leaking those tools (or the registry/catalog) into the shared engine every other session uses. A session needing BOTH a non-default model and client MCP gets ONE engine over ONE catalog from a single call (sel + specs are orthogonal inputs). The factory returns an error wrapping ErrInvalidArgument for an unknown/unavailable provider id. The composition root (internal/app) supplies it via Config.SessionEngine; when nil, a non-default selector or non-empty specs are rejected with ErrInvalidArgument. It mirrors MemberEngineFactory: the Service references the type in its signatures but never builds managers itself.
profile is the session's tool-surface profile (issue #55), flowing exactly as the selector does: ProfileDefault keeps today's catalog byte-identical; ProfileNoFS makes the factory assemble the NO-FILESYSTEM catalog (no file tools, no Shell, no Parallel, no SkillDraft; file-less Subagent/Team children) and apply the no-FS prompt posture. A no-FS session ALWAYS routes through this factory — the shared engine has the FS tools baked in.
governanceRoot is the SESSION's trusted host project-composition root (issue #32): the factory pins the per-session engine's CHILD permission resolver to it, so a per-session engine's subagents/members/branches resolve project permission rules from THEIR session's pre-fork base root — never the execution environment's guest root, the server flag's root, or a fork root. Empty (a no-fs session) pins no project root (user/CLI rules only).
mode is the session's PermissionMode (the mode→model re-resolution): when it is session.ModePlan the composition factory re-resolves the engine's model through the `plan` slot (within the SAME provider — the provider stays fixed per session), so a planning turn runs on a strong-reasoning model and an executing turn on the session model (the opusplan pattern). ModeDefault/ModeAccept keep the session-selected model (byte-identical). The factory echoes the mode back as SessionEngineResult.BuiltForMode so the Service can detect a stale engine across a mode change and rebuild via THIS same path (the run-entry/rehydration seam), never resolving a model itself.
type SessionEngineResult ¶
type SessionEngineResult struct {
// Engine is the built per-session engine. Required (non-nil on a nil error).
Engine *agent.Engine
// AgentDefinitionName acknowledges the named root actually resolved by the
// factory. This internal composition contract is not a wire field: a context
// selection alone cannot prove that a custom factory built the bounded catalog.
AgentDefinitionName string
// Capabilities is the session's resolved input capability (catalog ∩ adapter),
// computed in composition. The server echoes it verbatim; it never recomputes.
Capabilities port.ProviderCapabilities
// ProviderID/ModelID are the EFFECTIVE provider+model IDENTITY this session
// resolved to (the empty-selector default, an explicit selector, or a passthrough
// id), computed ONCE in composition from the SAME resolved locals that feed the
// engine — the server echoes them verbatim on CreateSessionResponse.resolved_model
// and never recomputes. Same single-source discipline as Capabilities. The context
// WINDOW is NOT a frozen field: Service.ResolvedModel resolves it live-first at echo
// time via Config.ResolveContextWindow (the SAME source the engine reads), so the
// echo and the running engine agree after a live-catalog swap with no rebuild.
ProviderID string
ModelID string
// ReasoningEffort is the EFFECTIVE, normalised + per-provider-clamped reasoning
// effort this session resolved to: "" when unset (provider default),
// else the neutral token actually sent to the adapter (e.g. openai + "max" echoes
// "high"). Computed ONCE in composition from the SAME resolved value that re-mints
// (or reuses) the engine's adapter; the server echoes it verbatim on
// CreateSessionResponse.resolved_model and never recomputes — the SAME single-
// source discipline as ProviderID/ModelID.
ReasoningEffort string
// BuiltForMode is the session PermissionMode the factory RESOLVED THE MODEL FOR
// (the mode→model re-resolution). The factory echoes back the
// mode it was handed — the SAME single-source discipline as ProviderID/ModelID —
// so the Service can stamp sessionEngine.builtForMode from this one value and later
// detect a stale engine (sess.Mode != se.builtForMode) without re-resolving any
// model itself. The empty value (a factory that predates the mode axis) is
// session.ModeDefault-equivalent: the Service treats "" as "no mode pin" and the
// stale check degrades to never-rebuild-on-mode.
BuiltForMode session.PermissionMode
// DebugMCPTools is the exact direct-tool ceiling resolved by a debug factory.
// It contains model-facing tool names only and is persisted on the session.
DebugMCPTools []string
// MountedClientMCP names the client-provided MCP servers that ACTUALLY
// CONNECTED for this session — never an echo of what was requested. It is nil
// when no specs were passed, and SHORTER than the request when some server was
// unreachable (mcp.NewManager keeps only successful connections).
//
// It exists because connecting is best-effort in composition and that is the
// right default for ONE of the two callers, not both. The ACP adapter wants a
// usable session even when an editor's MCP server is down; a gRPC/HTTP
// CreateSession caller cannot see composition's WARN and would otherwise be
// handed a session ID for a session missing tools it asked for, with no way to
// detect it. So the factory reports the mounted set and the Service enforces
// all-or-nothing on the wire path only (see verifyClientMCPMounted).
//
// A factory reached through the WIRE path MUST populate it. Leaving it empty
// while servers were requested is treated as "nothing mounted" and fails the
// create, rather than as "no claim made" — a guarantee a factory can silently
// opt out of by forgetting a field is not a guarantee. Only WithClientMCP
// (the wire-only option) turns the check on, so the ACP path and every
// selector-only factory are unaffected.
MountedClientMCP []string
// MountedClientMCPTools names the individual model-facing tools (e.g.
// "mcp__sdk__get_diagnostics") exposed by the servers in MountedClientMCP —
// the same per-tool granularity DebugMCPTools already gets for a debug
// session. Without this, a client-registered callback tool (SDK client.tool())
// mounts and dispatches correctly (it is already part of this session's
// Catalog) but every call is refused by the authority evaluator: root
// authority is minted once, per session KIND, from the static build-time
// catalog + the operator-global MCP manager — it has no way to see a
// per-session client-supplied tool that did not exist until THIS session was
// created. setPerSessionLabels folds this into the minted authority's
// CapabilitySet the same way it already does for DebugMCPTools, so a tool
// this session's own client just mounted is authorized to actually run.
//
// A factory MUST derive this from the exact same tool snapshot it put in
// the session's Catalog (internal/app's assembleCatalog does, via a
// before/after name diff), never from a second independent read of the
// client MCP manager: a manager's tool list can change (a
// tools/list_changed notification) between catalog assembly and this
// value being read, which would authorize a DIFFERENT tool than the one
// the model was actually offered.
MountedClientMCPTools []string
// RuntimeRevision is the immutable direct-MCP runtime revision used to build
// this engine. Zero keeps compatibility for compositions without live MCP
// publication. Engines do not hold runtime pins; run admission compares this
// tag with the operation pin and rebuilds before use.
RuntimeRevision uint64
// Authority is the per-session session.Authority the factory minted
// DIRECTLY from THIS session's own resolved catalog + resource-capability
// list (ADR 0353) — set only by a factory whose Authority must NOT be
// derived from Config.RootAuthority's deployment-default closure (today:
// AgentDefSessionEngine). The zero value means "the caller derives
// Authority the ordinary way" (Config.RootAuthority / carried-authority-
// on-fork); every other factory leaves this zero and setPerSessionLabels
// ignores it.
Authority session.Authority
// Limits is the ADR-0353 tighten-only clamped run-limit ceiling this
// agent-bound create or successor must persist. A live runtime rebuild must
// match the session's fixed limits or be refused. Set only by
// AgentDefSessionEngine, which knows the bound def's configured limits;
// nil leaves the caller's limits unchanged.
Limits *session.Limits
// BrokerRegistrationKeys are the exact registration keys successfully mounted
// from the candidate broker bundle. NonBrokerRegistrationKeys is the complete
// final-catalog partition excluding that bundle. Both are Catalog.Names metadata.
BrokerRegistrationKeys []string
NonBrokerRegistrationKeys []string
// Close tears down the session's MCP manager. Never nil (a no-op when no specs).
Close func() error
}
SessionEngineResult is what a SessionEngineFactory returns: the built per-session engine, the per-session resolved input Capabilities (a NEUTRAL port.ProviderCapabilities computed in composition as the catalog ∩ adapter intersection for the session's resolved provider+model — see internal/app modelCapability), and the Close func that tears down that session's MCP manager (a no-op when no specs). A struct (not a 4-tuple) keeps the two interface-typed members readable and leaves room for future per-session metadata without another signature churn. The Service echoes Capabilities back on CreateSessionResponse (session_capabilities) and never recomputes it — the composition is the single source so the wire echo and the ListModels view cannot disagree.
type SessionEngineWithToolsFactory ¶ added in v0.0.26
type SessionEngineWithToolsFactory func(ctx context.Context, sel ProviderSelector, specs []mcp.ServerConfig, profile SessionProfile, workspace string, mode session.PermissionMode, sessionTools []tool.Tool, sessionToolKeys []string) (SessionEngineResult, error)
SessionEngineWithToolsFactory is the explicit per-session catalogue seam used for host-owned wrapper tools. Tools are ordinary arguments: catalogue assembly must not recover them from context values or a process-global fallback.
type SessionInventoryActionReasons ¶
type SessionInventoryActionReasons struct {
PublicChat CapabilityReason
Inspect CapabilityReason
CopyID CapabilityReason
ViewTranscript CapabilityReason
Fork CapabilityReason
Rename CapabilityReason
Delete CapabilityReason
}
SessionInventoryActionReasons carries one closed reason for each disabled action.
type SessionInventoryCapabilities ¶
type SessionInventoryCapabilities struct {
PublicChat bool
Inspect bool
AuthoritativeTranscript bool
ActivityReplay bool
CopyID bool
ViewTranscript bool
Fork bool
Rename bool
Delete bool
}
SessionInventoryCapabilities is the proto-free action posture for one row.
type SessionMutationCapability ¶ added in v0.0.24
type SessionMutationCapability struct {
// contains filtered or unexported fields
}
SessionMutationCapability is the process-local proof that this Service may start a durable mutation for a session. It is deliberately not a backend fencing token: admission and invalidation are atomic locally, while a backend call admitted before invalidation may finish.
func NewSessionMutationCapability ¶ added in v0.0.24
func NewSessionMutationCapability(enabled bool) *SessionMutationCapability
NewSessionMutationCapability constructs the local mutation gate. When leasing is not configured, enabled is false and the gate is a byte-identical pass-through.
func (*SessionMutationCapability) Disable ¶ added in v0.0.24
func (c *SessionMutationCapability) Disable()
Disable permanently turns the capability into the no-lease pass-through mode. It is used when an optional lease backend reports ErrLeaseUnsupported.
func (*SessionMutationCapability) Grant ¶ added in v0.0.24
func (c *SessionMutationCapability) Grant(id session.SessionID)
Grant marks id as owned by this process.
func (*SessionMutationCapability) GuardStore ¶ added in v0.0.24
func (c *SessionMutationCapability) GuardStore(next port.SessionStore) port.SessionStore
GuardStore gates engine-owned snapshot saves at operation admission. Loads are read-only and pass through. Creation remains on Service's unwrapped store path.
func (*SessionMutationCapability) GuardToolCallRecorder ¶ added in v0.0.24
func (c *SessionMutationCapability) GuardToolCallRecorder(next port.ToolCallRecorder) port.ToolCallRecorder
GuardToolCallRecorder drops audit-sidecar mutations that begin after local lease capability invalidation. The recorder port has no error return.
func (*SessionMutationCapability) Invalidate ¶ added in v0.0.24
func (c *SessionMutationCapability) Invalidate(id session.SessionID)
Invalidate denies new mutations for id after ownership loss.
func (*SessionMutationCapability) Remove ¶ added in v0.0.24
func (c *SessionMutationCapability) Remove(id session.SessionID)
Remove forgets a normally released capability. It is safe only after every owner using the capability has settled.
type SessionMutationClass ¶ added in v0.0.24
type SessionMutationClass uint8
SessionMutationClass classifies application code that can touch a durable session family. It is deliberately separate from caller authorization: ownership is proved before coordination, while this inventory records the coordination required before storage mutation.
const ( // SessionMutationLeaseOwned acquires the session lease after runEntryMu and // keeps it through the backend call. SessionMutationLeaseOwned SessionMutationClass = iota // SessionMutationLeaseProven runs only for a registered run whose Service-owned // session lease is already held; lease loss invalidates that proof. SessionMutationLeaseProven // SessionMutationNewFamily is the creation-only exception: a caller-owned // identity is published with atomic create/reservation before any session can // have an existing lease owner. Every later mutation uses the lease classes. SessionMutationNewFamily // SessionMutationReadOnly reads session state without changing its family. SessionMutationReadOnly // SessionMutationComposition changes process-local composition state only. SessionMutationComposition )
type SessionMutationEntry ¶ added in v0.0.24
type SessionMutationEntry struct {
Class SessionMutationClass
Rationale string
}
SessionMutationEntry is one reviewed source-level inventory row.
type SessionProfile ¶
type SessionProfile string
SessionProfile is the session's TOOL-SURFACE profile, enum-as-string on the wire (CreateSessionRequest.profile — the Event.type/Result.stop idiom: a string field, additive values, no proto enum). It is a NEUTRAL value object owned by the server adapter, like ProviderSelector: the composition root (internal/app) interprets it when building the per-session engine; the adapter only validates and routes it. The profile is FIXED for the session lifetime.
const ( // ProfileDefault is the full filesystem profile. Composition binds the // server-owned deployment default before constructing this tool surface. ProfileDefault SessionProfile = "" // ProfileNoFS is the NO-FILESYSTEM profile (issue #55): no workspace, no // file tools (Read/ListDir/Edit/Write/Copy/Move/Remove/Grep/Glob), no Shell, no Parallel, no // SkillDraft — the agent works through MCP tools, memory, web fetch, Skill // bodies, and file-less delegation. It binds an exact no-FS EnvironmentRef and // requires a per-session engine because the shared engine has FS tools. ProfileNoFS SessionProfile = "no-fs" )
func ParseSessionProfile ¶
func ParseSessionProfile(s string) (SessionProfile, error)
ParseSessionProfile validates a wire profile string. "" is the default profile; "no-fs" is the no-filesystem profile; anything else is a loud ErrInvalidArgument — never a silent fallback to the default profile (an operator asking for a constrained surface must not silently get the full one).
type SessionSummary ¶
type SessionSummary struct {
// SessionID is the stored session's id.
SessionID string
// ModifiedAtUnix is the last-write timestamp in Unix seconds (the
// PrunableStore row mtime; the sort key for the picker).
ModifiedAtUnix int64
// State is the persisted lifecycle state (idle/running/awaiting/completed/...).
// Empty when the snapshot could not be loaded (a corrupt store row still
// surfaces its id/mtime).
State string
// Turns is the persisted model-call count. Zero when the snapshot could not
// be loaded.
Turns int
// ModelID is the resolved model id this session ran on (bare string, no
// provider context). Empty when the session never resolved a model or the
// snapshot could not be loaded.
ModelID string
// CreatedAtUnix is the creation timestamp in Unix seconds. Zero when the
// snapshot could not be loaded.
CreatedAtUnix int64
// Title is the human-readable session label (seeded once from the first
// genuine user prompt, clamped to 120 runes). Populated from the snapshot
// Title, or — when that is empty — from the lazy deriveTitle fallback
// (walks the conversation for the first genuine user prompt). Empty for a
// session with no genuine prompt.
Title string
// TitleProvenance reports whether the title is prompt-derived, operator-authored,
// or legacy/unknown.
TitleProvenance session.TitleProvenance
// TitleMetadata is the bounded source-free title lifecycle projection.
TitleMetadata session.TitlePayload
// TokenUsage is the canonical durable accounting ledger for this row.
TokenUsage map[session.UsageKind]session.TokenUsage
// Placement is bounded display-only placement metadata.
Placement session.PlacementMetadata
// Owner is the verified caller the session is attributed to.
Owner *session.Principal
// Kind and Relationship are the durable trusted-producer taxonomy.
Kind session.SessionKind
Relationship session.SessionRelationship
// Activity is the content-free persisted-history projection, present only
// when the configured pager proves it can round-trip atomically.
Activity session.ActivityState
// Capabilities and Reasons describe each public action valid for this row.
// ReasonCode is the legacy aggregate public-chat reason.
Capabilities SessionInventoryCapabilities
Reasons SessionInventoryActionReasons
ReasonCode CapabilityReason
}
SessionSummary is one stored session's picker metadata — id, timestamps, state, turn count, and the resolved model id. It carries NO conversation content: it is the cheap row a client renders in an "open existing session" picker. The Service exposes its own proto-free type so the wire adapters (toProtoSessionSummaries) and any in-process consumer need not import the proto package. `model_id` is a bare opaque string (NOT a full ResolvedModel) to keep the picker row cheap and provider-neutral.
type SessionTitleGenerator ¶ added in v0.0.26
type SessionTitleGenerator interface {
Generate(context.Context, []string) TitleGenerationResult
}
SessionTitleGenerator is the server-private seam for one bounded, server-owned title call. It has no routing, credential, persistence, or session-mutation authority.
func NewSessionTitleGenerator ¶ added in v0.0.26
func NewSessionTitleGenerator(provider port.LLMProvider, model string) (SessionTitleGenerator, error)
NewSessionTitleGenerator binds the generator to one composition-selected, provider-scoped provider and resolved model. It accepts no client routing, credentials, store, or session authority.
func NewSessionTitleGeneratorWithAttribution ¶ added in v0.0.26
func NewSessionTitleGeneratorWithAttribution(provider port.LLMProvider, providerID, model string) (SessionTitleGenerator, error)
NewSessionTitleGeneratorWithAttribution binds the opaque composition-selected provider/model attribution used by canonical token accounting.
type SessionTranscript ¶
type SessionTranscript struct {
SessionID session.SessionID
Messages []session.Message
Complete bool
Activity ActivityReplayStatus
Kind session.SessionKind
Relationship session.SessionRelationship
}
SessionTranscript is the coherent, human-displayable projection of one loaded session aggregate. Harness control continuations are omitted; a successful load is complete even when Messages is empty.
type StorageHealth ¶
type StorageHealth struct {
port.SessionStorageHealth
Ownerless OwnerlessCutoverInventory
Policy RetentionPolicy
LastSweep time.Time
LastSweepAvailable bool
NextSweep time.Time
NextSweepAvailable bool
ActiveJob string
LastFailure string
}
StorageHealth is the authenticated, content-free management projection.
type StorageMaintenanceEvent ¶
type StorageMaintenanceEvent struct {
Kind, Key string
State StorageMaintenanceState
Failure string
Resumable bool
}
StorageMaintenanceEvent contains only closed kinds, opaque internal keys, and stable sanitized failures. It must never carry backend errors or paths.
type StorageMaintenanceState ¶
type StorageMaintenanceState string
StorageMaintenanceState is a closed lifecycle vocabulary shared with the composition-owned health projection.
const ( // StorageMaintenanceStarted marks an active execution or durable reattachment. StorageMaintenanceStarted StorageMaintenanceState = "started" // StorageMaintenanceProgress refreshes an active job after a checkpoint. StorageMaintenanceProgress StorageMaintenanceState = "progress" // StorageMaintenanceCompleted removes a successfully terminal job. StorageMaintenanceCompleted StorageMaintenanceState = "completed" // StorageMaintenanceCancelled removes a forward-cancelled job. StorageMaintenanceCancelled StorageMaintenanceState = "cancelled" // StorageMaintenanceFailed records a sanitized failure; Resumable controls activity. StorageMaintenanceFailed StorageMaintenanceState = "failed" )
type StorageMaintenanceStatus ¶
type StorageMaintenanceStatus struct {
LastSweep, NextSweep time.Time
LastSweepAvailable, NextSweepAvailable bool
ActiveJob, LastFailure string
}
StorageMaintenanceStatus is the content-free lifecycle of retention, migration, and cleanup. ActiveJob is a deterministic comma-separated set of closed job kinds (with counts for concurrent same-kind jobs).
type SuccessorPlacement ¶ added in v0.0.24
SuccessorPlacement selects exact inheritance when empty or one freshly matched source-scoped worktree when Selector is present.
type TitleGenerationResult ¶ added in v0.0.26
type TitleGenerationResult struct {
Title string
Outcome session.TitleAttemptOutcome
Usage session.Usage
ProviderID string
ModelID string
Err error
Retryable bool
FailureClass titleFailureClass
FailureStage titleFailureStage
}
TitleGenerationResult is the source-free result of one physical title call. The Service owns persistence, lifecycle transitions, and any retry policy.
type UserModelEntry ¶
type UserModelEntry struct {
// Key is the entry's stable key.
Key string
// Description is the entry's one-line description.
Description string
}
UserModelEntry is the surface-agnostic listing metadata for one user-model fact (key + description, value omitted), mirroring tool.MemoryEntry's index shape. The Service exposes its own type so the wire adapters and the composition seam (UserModelLister) need not import the memory adapter.
type UserModelInspector ¶
type UserModelInspector interface {
Inspect(ctx context.Context, key string) (tool.MemoryRecord, bool, error)
}
UserModelInspector is the optional exact-entry detail capability. Keeping it separate preserves base-only/old remote list compatibility.
type UserModelLister ¶
type UserModelLister interface {
// List returns the user-model entries, key-sorted, or an error on a genuine
// store fault.
List(ctx context.Context) ([]UserModelEntry, error)
}
UserModelLister enumerates the CURRENT user-model entries (key + description, value omitted). It is the composition-injected seam backing GetUserModel: the composition root closes over the user-model store's Index so a fetch reflects the live store state. It is read-only.
type WatchEnvelope ¶ added in v0.0.22
type WatchEnvelope struct {
// Event is the recorded event, or nil on a phase-only frame.
Event *session.Event
// Cursor is the opaque resume token positioned AFTER this envelope.
//
// It is SCOPED TO THE run_id IT WAS ISSUED UNDER. A filtered watch advances
// its internal position over records the filter dropped, so a cursor handed
// back on a DIFFERENT filter — or on none — resumes past events that filter
// would have delivered, silently. Resume with the same run_id, or start over
// from the beginning.
Cursor port.Cursor
// Phase is one of the WatchPhase* values, as an open string.
Phase string
}
WatchEnvelope is ONE unit of watch delivery: what happened, where the client now is, and which phase of the watch it arrived in.
Event is nil on a PHASE-ONLY frame. There are exactly two: the single replay→live transition marker, and every gap. Both are delivery facts with no event behind them, which is why the phase — not a synthetic event — carries them.
type WorkspaceEnrollmentCollisionError ¶ added in v0.0.49
type WorkspaceEnrollmentCollisionError struct{ Key string }
WorkspaceEnrollmentCollisionError is the presentation-safe collision result exchanged only between root-internal composition and server seams.
func (*WorkspaceEnrollmentCollisionError) Error ¶ added in v0.0.49
func (e *WorkspaceEnrollmentCollisionError) Error() string
func (*WorkspaceEnrollmentCollisionError) Unwrap ¶ added in v0.0.49
func (*WorkspaceEnrollmentCollisionError) Unwrap() error
type WorkspaceEnrollmentProjection ¶ added in v0.0.26
type WorkspaceEnrollmentProjection struct {
Ref brokercontract.WorkspaceEnrollmentRef
Status brokercontract.WorkspaceEnrollmentStatus
URL string
}
WorkspaceEnrollmentProjection is the presentation-safe state returned to a client.
type WorkspaceFactory ¶
WorkspaceFactory builds the session-scoped tool.Workspace for a session root. The server is workspace-agnostic: the composition root injects memfs (tests) or osfs (production) via this seam.
type Worktree ¶
type Worktree struct {
// Path is the absolute working-tree path (the value handed to
// CreateSessionRequest.workspace to bind a session to this worktree).
Path string
// Branch is the checked-out ref name; empty for a detached HEAD.
Branch string
// Head is the commit SHA the worktree is at.
Head string
// Bare is true for a bare worktree.
Bare bool
}
Worktree is one discovered git worktree of a repo, mirroring the proto Worktree message (a `git worktree list --porcelain` record). The Service exposes its own proto-free type so the wire adapters and the composition seam (WorktreeLister) need not import the proto package directly.
type WorktreeLister ¶
type WorktreeLister interface {
// List returns the worktrees of the repo at root (the main worktree first, in
// `git worktree list` order), or an error on a genuine discovery fault. An
// untrusted/non-repo root yields an empty slice, NOT an error (fail-soft).
List(ctx context.Context, root string) ([]Worktree, error)
}
WorktreeLister enumerates the git worktrees of the repo rooted at root. It is the composition-injected discovery seam backing ListWorktrees (the client's /worktrees overlay): the composition root supplies an osfs-backed implementation that shells out to `git worktree list --porcelain` with a scrubbed env, trust-gated; a no-FS/cloud deployment (or an untrusted workspace) leaves it nil. It is read-only and nil-safe: when nil, ListWorktrees returns an empty list and ServerCapabilities.worktrees is false. It NEVER performs a live model/network call and never mutates anything.
type WorktreeSelectorIssuer ¶ added in v0.0.24
type WorktreeSelectorIssuer struct {
// contains filtered or unexported fields
}
WorktreeSelectorIssuer issues opaque process-local selectors without keeping a registry. Matching recomputes every candidate against current inventory.
func NewWorktreeSelectorIssuer ¶ added in v0.0.24
func NewWorktreeSelectorIssuer(key []byte) (*WorktreeSelectorIssuer, error)
NewWorktreeSelectorIssuer constructs an issuer from one random process key.
func (*WorktreeSelectorIssuer) Issue ¶ added in v0.0.24
func (i *WorktreeSelectorIssuer) Issue(principal *session.Principal, source session.SessionID, choice Worktree) string
Issue derives one opaque caller/source/current-choice selector.
func (*WorktreeSelectorIssuer) Match ¶ added in v0.0.24
func (i *WorktreeSelectorIssuer) Match(selector string, principal *session.Principal, source session.SessionID, current []Worktree) (Worktree, error)
Match checks every current candidate in constant time. It deliberately does not decode the selector or retain issued values.
Source Files
¶
- acp_placement.go
- attempts.go
- authn.go
- classification.go
- cleanup.go
- connector_status.go
- cors.go
- doc.go
- dreamreview.go
- dreamwire.go
- errorcodes.go
- errors.go
- event_recorder.go
- exact_plan_ask.go
- execution_templates.go
- execution_templates_grpc.go
- execution_templates_http.go
- execution_templates_json.go
- execution_templates_proto.go
- features.go
- grpc.go
- grpc_approveplan.go
- grpc_schedule.go
- grpc_team.go
- guardrails_status.go
- health.go
- http.go
- identity_broker.go
- learnedskills.go
- learning.go
- local_session_context.go
- mapper.go
- mcp_authorization.go
- mcp_broker.go
- mcp_refresh.go
- mutation_capability.go
- ownership.go
- placement.go
- placement_discovery.go
- placement_successor.go
- problem.go
- profile.go
- protected_resource.go
- runid.go
- schedule.go
- schedule_manager.go
- serverinfo.go
- service.go
- session_mutation_inventory.go
- skill_files.go
- stale_maintenance.go
- storage_health.go
- storage_management.go
- team.go
- title_coordinator.go
- title_generator.go
- transcript.go
- watch.go
- workspace_enrollment.go
- worktree_selector.go