afclient

package
v0.39.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package afclient provides the AgentFactory coordinator API client and types.

Package afclient daemon_client.go — thin HTTP client for the local daemon's status/control API. The daemon listens on HTTP at 127.0.0.1:<port> from ~/.donmai/daemon.yaml. All paths are relative to that base URL.

Package afclient daemon_config.go — read/write ~/.donmai/daemon.yaml.

The file is the source-of-truth for the daemon's project allowlist and credential configuration. The running daemon reloads on SIGHUP or restart; af project commands write atomically (tmp file + rename) to avoid corrupting the file while the daemon is live.

Package afclient kit_client.go — DaemonClient methods for the /api/daemon/kits* and /api/daemon/kit-sources* surfaces. Wave-9 A2 ships the canonical HTTP implementation against the route contract locked in ADR-2026-05-07-daemon-http-control-api.md § D1.

Package afclient kit_types.go — wire types for the daemon's /api/daemon/kits* and /api/daemon/kit-sources* operator surfaces. The contract is locked in donmai-architecture/ADR-2026-05-07-daemon-http-control-api.md (D4) and follows the manifest schema in 005-kit-manifest-spec.md.

Package afclient provider_client.go — DaemonClient methods for the /api/daemon/providers* surface. The wire types live in provider_types.go; this file holds the HTTP method bodies. The contract is locked in donmai-architecture/ADR-2026-05-07-daemon-http-control-api.md (D1).

Package afclient provider_types.go — wire types for the daemon's /api/daemon/providers* operator surface. The contract is locked in donmai-architecture/ADR-2026-05-07-daemon-http-control-api.md (D4) and matches the eight Provider Family vocabulary from 002-provider-base-contract.md.

Package afclient routing_client.go — DaemonClient methods for the /api/daemon/routing/* surface. The contract is locked in donmai-architecture/ADR-2026-05-07-daemon-http-control-api.md (D1, D2, D4) and the wire types live in routing_types.go.

Package afclient routing_types.go — wire types for the daemon's /api/daemon/routing/* operator surface. The contract is locked in donmai-architecture/ADR-2026-05-07-daemon-http-control-api.md (D4) and surfaces the cross-provider scheduler decisions described in 004-sandbox-capability-matrix.md and the capability-matrix reframe.

Package afclient workarea_client.go — DaemonClient methods for the /api/daemon/workareas* surface. Wave-9 Track A3 implementation.

The four methods cover the full Layer-3 Workarea operator surface: list, inspect, restore, and diff. Diff is the only non-trivial wire path — the daemon switches between a single JSON envelope and NDJSON streaming based on entry count vs the daemon-configured threshold. This client method handles both shapes via Content-Type discrimination and presents one unified WorkareaDiffResult to callers.

Package afclient workarea_types.go — wire types for the daemon's /api/daemon/workareas* operator surface. The contract is locked in donmai-architecture/ADR-2026-05-07-daemon-http-control-api.md (D4 + D4a) and follows the pool-member state machine + archive semantics in 003-workarea-provider.md.

Index

Constants

View Source
const TrustOverrideAllowedThisOnce = "allowed-this-once"

TrustOverrideAllowedThisOnce is the only accepted value of KitInstallRequest.TrustOverride. Mirrors the 'trustOverride: "allowed-this-once"' contract above.

Variables

View Source
var (
	ErrNotAuthenticated = errors.New("not authenticated")
	ErrNotFound         = errors.New("not found")
	ErrUnauthorized     = errors.New("unauthorized")
	ErrRateLimited      = errors.New("rate limited")
	ErrTimeout          = errors.New("request timeout")
	ErrServerError      = errors.New("server error")
	// ErrConflict indicates the server returned 409 Conflict — the
	// requested operation collides with existing state (e.g. a workarea
	// restore targeting a session id that's already in use).
	ErrConflict = errors.New("conflict")
	// ErrUnavailable indicates the server returned 503 Service
	// Unavailable — capacity is exhausted; the caller should honour the
	// Retry-After header if present.
	ErrUnavailable = errors.New("service unavailable")
	// ErrBadRequest indicates the server returned 400 Bad Request — the
	// request payload was malformed, or referenced corrupted state (e.g.
	// a corrupted workarea archive). The wrapped error chain carries any
	// reason string the server attached.
	ErrBadRequest = errors.New("bad request")

	// ErrUnimplemented is returned by client methods whose wire shape is
	// canonical (the request/response types are stable) but whose
	// implementation has not yet landed. Used as a placeholder during
	// staged migrations so downstream consumers compile against the
	// final signature without depending on a half-finished call site.
	ErrUnimplemented = errors.New("unimplemented")
)

Sentinel errors for expected API failure modes.

AllProviderFamilies lists the eight families in display order.

Functions

func CredentialsFromDataSource

func CredentialsFromDataSource(ds DataSource) (baseURL, token string, ok bool)

CredentialsFromDataSource attempts to recover the platform base URL and rsk_ Bearer token from a DataSource. Returns ok=false when the underlying value isn't an *afclient.Client (e.g. MockClient in tests), when the token is empty, or when the base URL is empty.

Used by callers that need to dispatch through a sibling platform surface — for example the linear subcommand tree at `afcli/linear.go` routes GraphQL through `/api/cli/linear/graphql` when an authenticated platform client is available (per ADR-2026-05-12-cli-linear-proxy). Callers that get ok=false should fall back to their direct-API auth path.

Pure read-only access — no copies made; the strings live on the same `*Client` the DataSource wraps.

func DefaultDaemonYAMLPath

func DefaultDaemonYAMLPath() string

DefaultDaemonYAMLPath returns the canonical path to daemon.yaml, expanding ~.

func DeriveProjectID

func DeriveProjectID(repoURL string) string

DeriveProjectID returns a stable, daemon-acceptable id derived from a repo URL. The daemon validates that projects[i].id is non-empty; the CLI did not historically write this field, so daemon.yaml files written by `rensei project allow` were rejected at next read with "projects[0].id is required".

Heuristics:

Output is lowercased, ASCII-safe (a-z0-9-) and trimmed of leading/trailing hyphens. An empty input yields "project".

func WriteDaemonYAML

func WriteDaemonYAML(path string, cfg *DaemonYAML) error

WriteDaemonYAML atomically writes cfg to path (tmp file + rename). The parent directory is created with 0o700 if it does not exist.

The writer preserves any unknown top-level keys present in the existing file (e.g. apiVersion, kind, machine, orchestrator, autoUpdate, observability) by parsing the on-disk file as a yaml.Node tree, replacing only the `projects` and `capacity` mappings, and re-marshalling. This is the v0.4.1 follow-up: the previous writer marshalled the minimal DaemonYAML struct directly, which clobbered every key the project command tree did not model. After a single `rensei project allow` the daemon would refuse to load the resulting file (machine.id missing, orchestrator.url missing).

If the file does not exist a fresh document is written from cfg. Callers that want a fully-populated daemon.yaml should run the wizard first or hand-author the file before calling this writer.

Types

type ActivityEvent

type ActivityEvent struct {
	ID        string       `json:"id"`
	Type      ActivityType `json:"type"`
	Content   string       `json:"content"`
	ToolName  *string      `json:"toolName,omitempty"`
	Timestamp string       `json:"timestamp"`
}

ActivityEvent represents a single activity from the streaming API.

type ActivityListResponse

type ActivityListResponse struct {
	Activities    []ActivityEvent `json:"activities"`
	Cursor        *string         `json:"cursor,omitempty"`
	SessionStatus SessionStatus   `json:"sessionStatus"`
}

ActivityListResponse matches GET /api/public/sessions/:id/activities.

type ActivityType

type ActivityType string

ActivityType represents the type of an agent activity event.

const (
	ActivityThought  ActivityType = "thought"
	ActivityAction   ActivityType = "action"
	ActivityResponse ActivityType = "response"
	ActivityError    ActivityType = "error"
	ActivityProgress ActivityType = "progress"
)

Activity type values for agent activity events.

type AgentCard

type AgentCard struct {

	// ID is the platform-generated identifier (e.g. "ag_…").
	ID string `json:"id"`
	// MetadataID is the user-facing stable identifier (e.g. "backlog-writer").
	MetadataID string `json:"metadataId"`
	// Name is the human-readable display name.
	Name string `json:"name"`
	// Description is a short prose description of what the agent does.
	Description string `json:"description"`
	// Version is the monotonic integer version per MetadataID (D2).
	Version int `json:"version"`
	// Scope is one of: system | org | project | workflow (D3, D5).
	Scope string `json:"scope"`
	// ScopeOwnerID is null for scope=system; otherwise the owning org/project ID.
	ScopeOwnerID *string `json:"scopeOwnerId"`

	// SourceProviderID identifies the ARP that materialized this card.
	// Values: 'db:internal' | 'kit:<kitId>' | 'a2a:<peer>' | 'tessl:<owner/name>'
	//         | 'github:<repo>' | 'openai-assistant:<orgId>' | …
	SourceProviderID string `json:"sourceProviderId"`
	// SourceLocator is the ARP-specific pointer to the upstream source
	// (e.g. "<owner/name>@<version>", "asst_xxx"). Null for db:internal cards.
	SourceLocator *string `json:"sourceLocator,omitempty"`
	// LastReconciledAt is the RFC3339 timestamp of the most recent ARP sync.
	// Null for author-time-only cards (reconcileTTLSec = null).
	LastReconciledAt *string `json:"lastReconciledAt,omitempty"`
	// ReconcileTTLSec is the reconciler refresh interval in seconds.
	// Null means the card is author-time-only and never auto-refreshed.
	ReconcileTTLSec *int `json:"reconcileTtlSec,omitempty"`

	// Partials is the ordered list of partial references assembled at dispatch.
	Partials []PartialRef `json:"partials,omitempty"`
	// Capabilities is the flat-typed boolean capability struct.
	Capabilities map[string]bool `json:"capabilities,omitempty"`

	// Runtimes is the ordered list of runtime paths (≥1 entry required).
	// The resolver picks the first satisfiable path.
	Runtimes []RuntimePath `json:"runtimes"`
	// Auth is the cross-cutting auth requirements applying to ALL runtime paths.
	Auth []AuthRequirement `json:"auth"`
	// Requires declares substrate requirements beyond the runtime path itself.
	Requires []SubstrateRequirement `json:"requires"`
	// Trust carries security posture consumed by Cedar policy gates at dispatch.
	Trust TrustClaims `json:"trust"`

	// WorkType is the SDLC-pathway classification for this agent.
	// Required at dispatch; ARP imports classify heuristically; operators
	// override at /admin/agents/<id>.
	// System-seeded values: research | backlog-writing | development |
	// coordination | qa | acceptance | other.
	// Per-org extension via org_work_types table (D22).
	WorkType string `json:"workType"`

	// Tools declares the allow/disallow tool permission lists.
	Tools AgentCardToolSurface `json:"tools"`

	// ModelProfileID references the model_profiles table entry for this card (D23).
	ModelProfileID *string `json:"modelProfileId,omitempty"`
	// PublishedAt is the RFC3339 timestamp when this version was published.
	// Null means draft.
	PublishedAt *string `json:"publishedAt,omitempty"`
	// DeprecatedAt is the RFC3339 timestamp when this card was deprecated.
	// Null means active.
	DeprecatedAt *string `json:"deprecatedAt,omitempty"`
	// Tags is the free-form tag list for operator filtering.
	Tags []string `json:"tags,omitempty"`
}

AgentCard is the canonical materialized form of an agent in the agent_cards table, as defined by 11-runtime-binding-strategy.md §1 and ADR-2026-05-12-agentcard-schema-and-scope.md.

The struct mirrors the TypeScript interface exactly so JSON round-trips are lossless. All TS optional fields are represented as pointer types or omitempty slices to preserve the original zero-vs-absent distinction.

Field count: 24 exported fields (identity × 7, provenance × 4, composition × 3, ontology axes × 4, workType × 1, tool surface × 1, lifecycle × 4).

type AgentCardScope

type AgentCardScope = string

AgentCardScope is the four-scope enum (D3, D5). Visibility cascades: system → org → project → workflow. workflow-scope cards are inline-only (no DB row until "Promote to project").

const (
	// AgentCardScopeSystem is visible to all orgs, projects, and workflows.
	AgentCardScopeSystem AgentCardScope = "system"
	// AgentCardScopeOrg is visible to all projects and workflows within the org.
	AgentCardScopeOrg AgentCardScope = "org"
	// AgentCardScopeProject is visible to all workflows within the project.
	AgentCardScopeProject AgentCardScope = "project"
	// AgentCardScopeWorkflow is inline in a workflow definition; no DB row.
	AgentCardScopeWorkflow AgentCardScope = "workflow"
)

type AgentCardToolSurface

type AgentCardToolSurface struct {
	Allow    []string `json:"allow"`
	Disallow []string `json:"disallow"`
}

AgentCardToolSurface declares the tool allow/disallow lists.

type AgentListResponse

type AgentListResponse struct {
	Agents    []AgentCard `json:"agents"`
	Count     int         `json:"count"`
	Timestamp string      `json:"timestamp"`
}

AgentListResponse matches GET /api/agents.

type AgentScopeQuery

type AgentScopeQuery struct {
	// Scope restricts results to a specific scope tier.
	// Empty returns the natural union visible to the caller's (org, project).
	Scope string `json:"scope,omitempty"`
	// OrgID restricts results to cards owned by this org (scope=org rows).
	OrgID string `json:"orgId,omitempty"`
	// ProjectID restricts results to cards owned by this project (scope=project rows).
	ProjectID string `json:"projectId,omitempty"`
	// WorkType filters results to a specific workType classification.
	WorkType string `json:"workType,omitempty"`
}

AgentScopeQuery carries the scope parameters for /api/agents list calls. At most one of OrgID and ProjectID should be set; both empty returns system-scope cards visible to all callers.

type AgentWorkType

type AgentWorkType = string

AgentWorkType is the classification of work an agent performs (D21, D22). System-seeded values; per-org extension via org_work_types table.

const (
	WorkTypeResearch       AgentWorkType = "research"
	WorkTypeBacklogWriting AgentWorkType = "backlog-writing"
	WorkTypeDevelopment    AgentWorkType = "development"
	WorkTypeCoordination   AgentWorkType = "coordination"
	WorkTypeQA             AgentWorkType = "qa"
	WorkTypeAcceptance     AgentWorkType = "acceptance"
	WorkTypeOther          AgentWorkType = "other"
)

AgentWorkType enum values; see D21/D22.

type Attestation

type Attestation struct {
	// KeyAlgorithm is the signing algorithm.
	KeyAlgorithm AttestationKeyAlgorithm `json:"keyAlgorithm"`
	// KeyFingerprint is the truncated public key fingerprint for display (e.g. "abc1234…d4f2").
	KeyFingerprint string `json:"keyFingerprint"`
	// Signature is the base64-encoded signature over the audit entry payload.
	Signature string `json:"signature"`
	// SignedAt is the RFC3339 timestamp of signing.
	SignedAt string `json:"signedAt"`
	// Verified is true when the host has verified the signature at observation time.
	Verified bool `json:"verified"`
}

Attestation is a signed proof-of-provenance attached to an audit chain entry. Format: `<algorithm>:<base64-signature>` with a truncated fingerprint for display. Chosen form cites the `format.AttestationFingerprint` helper in 014 ("ed25519:abc1234…d4f2").

type AttestationKeyAlgorithm

type AttestationKeyAlgorithm string

AttestationKeyAlgorithm is the signing algorithm used for an attestation.

const (
	// AttestationEd25519 is the EdDSA attestation algorithm.
	AttestationEd25519 AttestationKeyAlgorithm = "ed25519"
	// AttestationECDSA is the ECDSA P-256 attestation algorithm.
	AttestationECDSA AttestationKeyAlgorithm = "ecdsa-p256"
)

type AuditChainEntry

type AuditChainEntry struct {
	// Sequence is the monotonic index of this entry within the session's chain.
	Sequence uint64 `json:"sequence"`
	// EventKind is the Layer 6 event type (e.g. "session-accepted", "workarea-acquired").
	EventKind string `json:"eventKind"`
	// SessionID is the session this event belongs to.
	SessionID string `json:"sessionId"`
	// ActorID is the principal that caused the event (agent ID, daemon ID, user ID, etc.).
	ActorID string `json:"actorId"`
	// Payload is the event-specific data encoded as a JSON object.
	Payload map[string]any `json:"payload,omitempty"`
	// PreviousHash is the Merkle hash of the preceding chain entry, enabling integrity verification.
	PreviousHash string `json:"previousHash"`
	// EntryHash is the Merkle hash of this entry (covering Sequence + EventKind + Payload + PreviousHash).
	EntryHash string `json:"entryHash"`
	// Attestation is the optional cryptographic proof attached to this entry.
	Attestation *Attestation `json:"attestation,omitempty"`
	// OccurredAt is the RFC3339 timestamp of the event.
	OccurredAt string `json:"occurredAt"`
}

AuditChainEntry is a single entry in a session's Layer 6 audit chain. Matches the "AuditEntry" TUI primitive in 014 and the Merkle-log row shape referenced in the 009 reframe.

type AuthRequirement

type AuthRequirement struct {
	// Kind is one of: api-key | oauth | service-account | host-session | none.
	Kind string `json:"kind"`
	// EnvVar is the environment variable name for api-key auth (e.g. "ELEVENLABS_API_KEY").
	EnvVar *string `json:"envVar,omitempty"`
	// OAuthProvider names the OAuth provider for oauth auth (e.g. "linear", "notion", "github").
	OAuthProvider *string `json:"oauthProvider,omitempty"`
	// VaultRef is resolved at dispatch time from the credential store.
	VaultRef *string `json:"vaultRef,omitempty"`
}

AuthRequirement declares a single auth obligation that crosses all runtime paths. Multiple entries are AND-combined (all must be satisfied).

type CapabilityFilter

type CapabilityFilter struct {
	// Field is the capability field name (e.g. "os", "arch", "region").
	Field string `json:"field"`
	// Op is the operator: "eq", "in", "lte", "gte".
	Op string `json:"op"`
	// Value is the filter value (string, number, or array serialised to
	// string).
	Value string `json:"value"`
}

CapabilityFilter is a single hard constraint applied before scoring.

type CapacityConfig

type CapacityConfig struct {
	// MaxConcurrentSessions is the maximum number of sessions the local
	// daemon accepts concurrently. 0 means do not accept new sessions.
	MaxConcurrentSessions int `yaml:"maxConcurrentSessions,omitempty" json:"maxConcurrentSessions,omitempty"`
	// PoolMaxDiskGb is the maximum total disk usage (in GiB) for the workarea
	// pool before the daemon starts LRU-evicting cold members.  0 means no limit.
	PoolMaxDiskGb int `yaml:"poolMaxDiskGb,omitempty" json:"poolMaxDiskGb,omitempty"`
}

CapacityConfig holds the configurable capacity limits written into daemon.yaml under the `capacity` key. `poolMaxDiskGb` drives automatic LRU eviction of the workarea pool once the disk threshold is hit.

type ChatSessionRequest

type ChatSessionRequest struct {
	Prompt string `json:"prompt"`
}

ChatSessionRequest is the body of POST /api/public/sessions/:id/prompt.

type ChatSessionResponse

type ChatSessionResponse struct {
	Delivered     bool          `json:"delivered"`
	PromptID      string        `json:"promptId"`
	SessionID     string        `json:"sessionId"`
	SessionStatus SessionStatus `json:"sessionStatus"`
}

ChatSessionResponse matches POST /api/public/sessions/:id/prompt.

type Client

type Client struct {
	BaseURL    string
	APIToken   string // Bearer token for authenticated requests (rsk_...)
	HTTPClient *http.Client

	// OrgScope, when non-empty, is sent as `X-Rensei-Org` on every
	// request. Accepts the platform org id (`org_…`), org slug, or
	// the WorkOS org id — the server resolves whichever is supplied.
	OrgScope string
	// ProjectScope, when non-empty, is sent as `X-Rensei-Project` on
	// every request. Accepts the project slug or platform project id.
	// Server-side honoring is route-by-route (not all routes are
	// project-scoped).
	ProjectScope string
}

Client is the HTTP implementation of DataSource.

Scope fields (OrgScope, ProjectScope) carry per-invocation routing context. When non-empty they are sent on EVERY request as `X-Rensei-Org` and `X-Rensei-Project`. The platform's CLI auth path treats `X-Rensei-Org` as authoritative (after membership check), so these headers eliminate the org-resolution drift that bites when multiple humans + agents on a host share a WorkOS access token whose `org_id` claim is frozen to whichever org the user happened to be in at token-mint time. Empty = don't send the header (server falls back to its own resolution).

func NewAuthenticatedClient

func NewAuthenticatedClient(baseURL, apiToken string) *Client

NewAuthenticatedClient creates an API client with Bearer token auth.

func NewClient

func NewClient(baseURL string) *Client

NewClient creates a new API client pointing at the given server URL.

func (*Client) ChatSession

func (c *Client) ChatSession(id string, req ChatSessionRequest) (*ChatSessionResponse, error)

ChatSession forwards a prompt to the given session's agent and returns the delivery confirmation.

func (*Client) ForwardPrompt

func (c *Client) ForwardPrompt(req ForwardPromptRequest) (*ForwardPromptResponse, error)

ForwardPrompt forwards a message to a running agent session.

func (*Client) GetActivities

func (c *Client) GetActivities(sessionID string, afterCursor *string) (*ActivityListResponse, error)

GetActivities fetches activity events for a session, optionally after a cursor.

The endpoint changed from a path-segment shape (`/api/public/sessions/<id>/activities`) to a query-parameter shape (`/api/public/session-activities?sessionId=<id>[&sessionHash=<hash>]`) when the activity reader was ported into the platform's app-router REST surface. Older servers that still expose the legacy path- segment route will respond with a 404 to the query-param URL — clients targeting those need to pin a version of this package that pre-dates this commit.

Auth model: when the client carries an APIToken (rsk_ key) it sends the token in the Authorization header and omits sessionHash, so the server takes its rsk_/cookie auth branch. That branch accepts both the raw linearSessionId and the hashed id form returned by /api/public/sessions list/detail, doing a reverse-lookup if needed. When the client is unauthenticated (no APIToken — typically a TUI viewer with the raw linearSessionId from a shared link) it sends sessionHash so the server's public-hash branch admits it; that branch only accepts the raw linearSessionId.

func (*Client) GetAgent

func (c *Client) GetAgent(id string) (*AgentCard, error)

GetAgent fetches a single AgentCard by its platform-generated ID ("ag_…").

TODO(lane-H): /api/agents/<id> is not yet implemented server-side (pending Lane A1 in the agentcard schema-and-scope ADR). Returns ErrUnimplemented until the endpoint lands on main.

func (*Client) GetAuditChain

func (c *Client) GetAuditChain(sessionID string) ([]AuditChainEntry, error)

GetAuditChain fetches the Layer 6 audit chain for a session.

func (*Client) GetCostReport

func (c *Client) GetCostReport() (*CostReportResponse, error)

GetCostReport fetches the fleet-wide cost report.

func (*Client) GetKitContributions

func (c *Client) GetKitContributions(sessionID string) ([]KitContribution, error)

GetKitContributions fetches kit contribution summaries for a session.

func (*Client) GetKitDetections

func (c *Client) GetKitDetections(sessionID string) ([]KitDetection, error)

GetKitDetections fetches kit detection results for a session.

func (*Client) GetMachineStats

func (c *Client) GetMachineStats() ([]MachineStats, error)

GetMachineStats fetches per-machine capacity and status snapshots.

func (*Client) GetSandboxProviderStats

func (c *Client) GetSandboxProviderStats() ([]SandboxProviderStats, error)

GetSandboxProviderStats fetches runtime snapshots for all registered SandboxProviders.

func (*Client) GetSessionDetail

func (c *Client) GetSessionDetail(id string) (*SessionDetailResponse, error)

GetSessionDetail fetches detailed info for a single session.

func (*Client) GetSessions

func (c *Client) GetSessions() (*SessionsListResponse, error)

GetSessions fetches the list of all sessions (fleet-wide).

func (*Client) GetSessionsFiltered

func (c *Client) GetSessionsFiltered(project string) (*SessionsListResponse, error)

GetSessionsFiltered fetches sessions optionally scoped to a project. An empty project returns fleet-wide sessions (same as GetSessions). Non-empty project values are passed as the `project` query parameter; the platform accepts either a project slug or ID.

func (*Client) GetStats

func (c *Client) GetStats() (*StatsResponse, error)

GetStats fetches fleet-wide statistics.

func (*Client) GetStatsV2

func (c *Client) GetStatsV2() (*StatsResponseV2, error)

GetStatsV2 fetches fleet statistics extended with per-machine and per-provider breakdowns from the /api/public/stats/v2 endpoint.

func (*Client) GetWorkareaPoolStats

func (c *Client) GetWorkareaPoolStats(machineID MachineID) (*WorkareaPoolStats, error)

GetWorkareaPoolStats fetches the local workarea pool snapshot. An empty machineID returns the aggregate across all machines.

func (*Client) ListAgents

func (c *Client) ListAgents(scope AgentScopeQuery) ([]AgentCard, error)

ListAgents fetches the AgentCards visible under the given scope query. Empty ScopeQuery returns all cards visible to the caller's (org, project).

TODO(lane-H): /api/agents is not yet implemented server-side (pending Lane A1 in the agentcard schema-and-scope ADR §3). Wire shape is canonical; the method returns ErrUnimplemented until the endpoint lands on main.

func (*Client) ListFleet

func (c *Client) ListFleet() (*ListFleetResponse, error)

ListFleet fetches a list of agents with optional filtering.

func (*Client) ReconnectSession

func (c *Client) ReconnectSession(id string, req ReconnectSessionRequest) (*ReconnectSessionResponse, error)

ReconnectSession resumes an activity stream for the given session.

func (*Client) StopAgent

func (c *Client) StopAgent(req StopAgentRequest) (*StopAgentResponse, error)

StopAgent requests to stop a running agent.

func (*Client) StopSession

func (c *Client) StopSession(id string) (*StopSessionResponse, error)

StopSession sends a stop request for the given session and returns the coordinator's response describing the status transition.

func (*Client) SubmitTask

func (c *Client) SubmitTask(req SubmitTaskRequest) (*SubmitTaskResponse, error)

SubmitTask submits a new task to the fleet work queue.

func (*Client) WhoAmI

func (c *Client) WhoAmI() (*WhoAmIResponse, error)

WhoAmI verifies the API key and returns org context.

type CloneStrategy

type CloneStrategy string

CloneStrategy controls how the daemon clones a repo for session workareas.

const (
	// CloneShallow performs a depth-1 clone (fast; no history).
	CloneShallow CloneStrategy = "shallow"
	// CloneFull performs a full clone (slower; full history).
	CloneFull CloneStrategy = "full"
	// CloneReference clones from an existing local mirror.
	CloneReference CloneStrategy = "reference-clone"
)

type CostReportRequest

type CostReportRequest struct {
	TaskID string `json:"taskId,omitempty"`
}

CostReportRequest matches GET /api/mcp/cost-report.

type CostReportResponse

type CostReportResponse struct {
	TotalSessions        int     `json:"totalSessions"`
	SessionsWithCostData int     `json:"sessionsWithCostData"`
	TotalCostUsd         float64 `json:"totalCostUsd"`
	TotalInputTokens     int     `json:"totalInputTokens"`
	TotalOutputTokens    int     `json:"totalOutputTokens"`
}

CostReportResponse matches the cost-report response (fleet-wide).

type CredentialHelper

type CredentialHelper struct {
	Kind       CredentialHelperKind `yaml:"kind,omitempty"       json:"kind,omitempty"`
	SSHKeyPath string               `yaml:"sshKeyPath,omitempty" json:"sshKeyPath,omitempty"`
	EnvVarName string               `yaml:"envVarName,omitempty" json:"envVarName,omitempty"`
}

CredentialHelper is the per-project credential configuration written into daemon.yaml under projects[].credentialHelper.

Exactly one of the helper-specific fields is set, matching the Kind:

  • osxkeychain: no extra fields needed; git handles it natively.
  • ssh: SSHKeyPath is the absolute path to the private key.
  • pat: EnvVarName is the env-var whose value is the PAT.
  • gh: no extra fields needed; `gh auth` is invoked.

When Kind is empty the helper is unconfigured; the daemon will refuse work for this project until credentials are added via `donmai project credentials`.

type CredentialHelperKind

type CredentialHelperKind string

CredentialHelperKind enumerates the supported per-project credential sources.

const (
	// CredentialHelperOSXKeychain uses the macOS osxkeychain git credential helper.
	CredentialHelperOSXKeychain CredentialHelperKind = "osxkeychain"
	// CredentialHelperSSH uses a filesystem SSH key for git authentication.
	CredentialHelperSSH CredentialHelperKind = "ssh"
	// CredentialHelperPAT stores the name of an env-var containing the PAT.
	CredentialHelperPAT CredentialHelperKind = "pat"
	// CredentialHelperGH delegates to the `gh` CLI via `gh auth status`.
	CredentialHelperGH CredentialHelperKind = "gh"
)

type DaemonActionResponse

type DaemonActionResponse struct {
	// OK is true when the action was accepted.
	OK bool `json:"ok"`
	// Message is a human-readable description of the outcome.
	Message string `json:"message"`
}

DaemonActionResponse is the response from action endpoints (pause, resume, drain, stop, update).

type DaemonClient

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

DaemonClient is an HTTP client for the local daemon's control API. Construct with NewDaemonClient. All methods are safe for concurrent use.

func NewDaemonClient

func NewDaemonClient(cfg DaemonConfig) *DaemonClient

NewDaemonClient constructs a DaemonClient pointing at the daemon derived from cfg. The HTTP timeout is set to 10 seconds.

func NewDaemonClientFromURL

func NewDaemonClientFromURL(baseURL string) *DaemonClient

NewDaemonClientFromURL constructs a DaemonClient pointing at an arbitrary base URL. Primarily used in tests with httptest.Server.

func (*DaemonClient) DiffWorkareas

func (c *DaemonClient) DiffWorkareas(idA, idB string) (*WorkareaDiffResult, error)

DiffWorkareas returns a structured per-path delta between two archived workareas via GET /api/daemon/workareas/<idA>/diff/<idB>. Both ids MUST resolve to archives (diffing live members is out of scope per ADR D4a).

The daemon switches between a single JSON envelope and NDJSON streaming based on entry count vs its configured threshold. This method consumes both shapes into the same WorkareaDiffResult:

  • application/json → decode WorkareaDiffEnvelope
  • application/x-ndjson → stream-decode entries one line at a time, accumulate into Result.Entries, and read the trailing {"summary": {...}} line into Result.Summary.

func (*DaemonClient) DisableKit

func (c *DaemonClient) DisableKit(id string) (*Kit, error)

DisableKit deactivates an active kit via POST /api/daemon/kits/<id>/disable.

func (*DaemonClient) DisableKitSource

func (c *DaemonClient) DisableKitSource(name string) (*KitSourceToggleResult, error)

DisableKitSource disables the named registry source via POST /api/daemon/kit-sources/<name>/disable.

func (*DaemonClient) Drain

func (c *DaemonClient) Drain(timeoutSeconds int) (*DaemonActionResponse, error)

Drain initiates a graceful drain. timeoutSeconds=0 uses the daemon default.

func (*DaemonClient) EnableKit

func (c *DaemonClient) EnableKit(id string) (*Kit, error)

EnableKit activates a previously-disabled kit via POST /api/daemon/kits/<id>/enable.

func (*DaemonClient) EnableKitSource

func (c *DaemonClient) EnableKitSource(name string) (*KitSourceToggleResult, error)

EnableKitSource enables the named registry source via POST /api/daemon/kit-sources/<name>/enable.

func (*DaemonClient) EvictPool

func (c *DaemonClient) EvictPool(req EvictPoolRequest) (*EvictPoolResponse, error)

EvictPool posts an eviction request to the daemon. Pool members matching repoURL and older than the threshold in req are scheduled for destruction. The daemon emits a Layer 6 hook event whose correlation ID is echoed back.

func (*DaemonClient) ExplainRouting

func (c *DaemonClient) ExplainRouting(sessionID string) (*RoutingExplainResponse, error)

ExplainRouting fetches the full decision trace for a session from GET /api/daemon/routing/explain/<sessionID>. Returns ErrNotFound when the session id has no recorded routing decision.

func (*DaemonClient) GetKit

func (c *DaemonClient) GetKit(id string) (*KitManifestEnvelope, error)

GetKit fetches the full manifest for a single kit from GET /api/daemon/kits/<id>. Returns ErrNotFound when the id is not registered.

func (*DaemonClient) GetPoolStats

func (c *DaemonClient) GetPoolStats() (*WorkareaPoolStats, error)

GetPoolStats fetches the full workarea pool state, including per-member detail and aggregate counts. The daemon response includes Layer 6 correlation IDs so observability subscribers can correlate events.

func (*DaemonClient) GetProvider

func (c *DaemonClient) GetProvider(id string) (*ProviderEnvelope, error)

GetProvider fetches a single provider by id from GET /api/daemon/providers/<id>. Returns ErrNotFound when the id is not registered.

func (*DaemonClient) GetRoutingConfig

func (c *DaemonClient) GetRoutingConfig() (*RoutingConfigResponse, error)

GetRoutingConfig fetches the daemon's current routing config snapshot from GET /api/daemon/routing/config. The response carries Thompson-Sampling state for both LLM and sandbox dimensions plus the last N decisions.

func (*DaemonClient) GetStats

func (c *DaemonClient) GetStats(withPool, byMachine bool) (*DaemonStatsResponse, error)

GetStats fetches the daemon's capacity and pool statistics.

func (*DaemonClient) GetStatus

func (c *DaemonClient) GetStatus() (*DaemonStatusResponse, error)

GetStatus fetches the daemon's current status snapshot.

func (*DaemonClient) GetWorkarea

func (c *DaemonClient) GetWorkarea(id string) (*WorkareaEnvelope, error)

GetWorkarea fetches a single workarea by id from GET /api/daemon/workareas/<id>. The id may be either an active pool member id or an archive id; the response Workarea.Kind disambiguates. Returns ErrNotFound when the id is not registered.

func (*DaemonClient) InstallKit

func (c *DaemonClient) InstallKit(id string, req KitInstallRequest) (*KitInstallResult, error)

InstallKit installs the named kit via POST /api/daemon/kits/<id>/install.

func (*DaemonClient) ListKitSources

func (c *DaemonClient) ListKitSources() (*ListKitSourcesResponse, error)

ListKitSources fetches the registry-source federation order from GET /api/daemon/kit-sources.

func (*DaemonClient) ListKits

func (c *DaemonClient) ListKits() (*ListKitsResponse, error)

ListKits fetches all installed kits from GET /api/daemon/kits.

func (*DaemonClient) ListProviders

func (c *DaemonClient) ListProviders() (*ListProvidersResponse, error)

ListProviders fetches the daemon's known provider registry from GET /api/daemon/providers.

func (*DaemonClient) ListWorkareas

func (c *DaemonClient) ListWorkareas() (*ListWorkareasResponse, error)

ListWorkareas fetches the daemon's active pool members and on-disk archives from GET /api/daemon/workareas. The response splits the two kinds into Active and Archived arrays per ADR D4a.

func (*DaemonClient) Pause

func (c *DaemonClient) Pause() (*DaemonActionResponse, error)

Pause sends a pause command to the daemon (stops accepting new sessions).

func (*DaemonClient) RestoreWorkarea

func (c *DaemonClient) RestoreWorkarea(archiveID string, req WorkareaRestoreRequest) (*WorkareaRestoreResult, error)

RestoreWorkarea materialises the named archive into a fresh active pool member via POST /api/daemon/workareas/<archiveID>/restore. The new id in the response is distinct from the archive id; archives are immutable per ADR D4a.

Server responses worth distinguishing in client error wrapping:

  • 409: IntoSessionID conflict — session id already in use → ErrConflict.
  • 503: pool saturation — Retry-After header names the wait → ErrUnavailable.
  • 400: archive corrupted or unreadable → ErrBadRequest.

func (*DaemonClient) Resume

func (c *DaemonClient) Resume() (*DaemonActionResponse, error)

Resume sends a resume command to the daemon (re-enables accepting sessions).

func (*DaemonClient) SetCapacityConfig

func (c *DaemonClient) SetCapacityConfig(key, value string) (*SetCapacityResponse, error)

SetCapacityConfig posts a capacity key-value update to the daemon. The daemon writes the change to ~/.donmai/daemon.yaml atomically and reloads the affected subsystem (e.g. the LRU eviction trigger for poolMaxDiskGb).

func (*DaemonClient) Stop

func (c *DaemonClient) Stop() (*DaemonActionResponse, error)

Stop sends a stop command to the daemon. In-flight sessions are interrupted.

func (*DaemonClient) Update

func (c *DaemonClient) Update() (*DaemonActionResponse, error)

Update triggers a manual daemon update check.

func (*DaemonClient) VerifyKitSignature

func (c *DaemonClient) VerifyKitSignature(id string) (*KitSignatureResult, error)

VerifyKitSignature triggers signature verification for the named kit via GET /api/daemon/kits/<id>/verify-signature.

type DaemonConfig

type DaemonConfig struct {
	// Port is the HTTP port the daemon is listening on (default 7734).
	Port int `json:"port" yaml:"port"`
	// Host is the bind address (default "127.0.0.1").
	Host string `json:"host" yaml:"host"`
}

DaemonConfig holds the minimal daemon connection config read from ~/.donmai/daemon.yaml (or overridden by env/flag).

func DefaultDaemonConfig

func DefaultDaemonConfig() DaemonConfig

DefaultDaemonConfig returns a DaemonConfig with sane defaults.

func (DaemonConfig) BaseURL

func (c DaemonConfig) BaseURL() string

BaseURL returns the base URL for the daemon API derived from cfg.

type DaemonDrainRequest

type DaemonDrainRequest struct {
	// TimeoutSeconds is the max time to wait for in-flight work to drain.
	// 0 means use the daemon's configured default.
	TimeoutSeconds int `json:"timeoutSeconds,omitempty"`
}

DaemonDrainRequest is the optional body for POST /api/daemon/drain.

type DaemonRegistrationStats

type DaemonRegistrationStats struct {
	// Status is the registration status reported in the most recent
	// heartbeat: idle / busy / draining / stub / unregistered.
	Status string `json:"status,omitempty"`
	// LastHeartbeatAt is the RFC3339 timestamp of the last heartbeat
	// payload composed by the daemon. Empty when no heartbeat has run.
	LastHeartbeatAt string `json:"lastHeartbeatAt,omitempty"`
	// HeartbeatRunning reports whether the heartbeat goroutine is active.
	HeartbeatRunning bool `json:"heartbeatRunning,omitempty"`
	// PollRunning reports whether the poll goroutine is active.
	PollRunning bool `json:"pollRunning,omitempty"`
}

DaemonRegistrationStats summarises the daemon's connection to the platform for `daemon stats` consumers.

type DaemonStatsResponse

type DaemonStatsResponse struct {
	// Capacity is the machine capacity envelope.
	Capacity MachineCapacity `json:"capacity"`
	// ActiveSessions is the count of currently running sessions.
	ActiveSessions int `json:"activeSessions"`
	// QueueDepth is the number of tasks waiting for a session slot.
	QueueDepth int `json:"queueDepth"`
	// Pool is the workarea pool snapshot (populated with --pool).
	Pool *WorkareaPoolStats `json:"pool,omitempty"`
	// ByMachine is the per-machine breakdown (populated with --by-machine).
	ByMachine []MachineStats `json:"byMachine,omitempty"`
	// Timestamp is the RFC3339 time of this snapshot.
	Timestamp string `json:"timestamp"`

	// WorkerID is the platform-assigned worker id (or stub fallback). Empty
	// if registration has not yet completed.
	WorkerID string `json:"workerId,omitempty"`
	// Registration carries the human-readable registration status and the
	// timestamp of the most recent successful heartbeat.
	Registration *DaemonRegistrationStats `json:"registration,omitempty"`
	// AllowedProjects is the list of repositories in the daemon's allowlist
	// (from daemon.yaml). May be empty when no projects have been
	// configured.
	AllowedProjects []string `json:"allowedProjects,omitempty"`
}

DaemonStatsResponse is the response from GET /api/daemon/stats.

type DaemonStatus

type DaemonStatus string

DaemonStatus is the lifecycle state reported by a running rensei-daemon. Values mirror the wire format emitted in NDJSON daemon logs and the registered-status field the orchestrator observes.

const (
	// DaemonReady indicates the daemon is running and accepting new work.
	DaemonReady DaemonStatus = "ready"
	// DaemonDraining indicates the daemon is finishing in-flight work before restart.
	DaemonDraining DaemonStatus = "draining"
	// DaemonPaused indicates the daemon is running but not accepting new sessions.
	DaemonPaused DaemonStatus = "paused"
	// DaemonStopped indicates the daemon process is not running.
	DaemonStopped DaemonStatus = "stopped"
	// DaemonUpdating indicates the daemon is applying an auto-update.
	DaemonUpdating DaemonStatus = "updating"
)

type DaemonStatusResponse

type DaemonStatusResponse struct {
	// Status is the lifecycle state of the daemon.
	Status DaemonStatus `json:"status"`
	// Version is the rensei-daemon binary version.
	Version string `json:"version"`
	// MachineID is the configured machine identifier.
	MachineID string `json:"machineId"`
	// PID is the daemon process ID.
	PID int `json:"pid"`
	// UptimeSeconds is how long the daemon has been running.
	UptimeSeconds int64 `json:"uptimeSeconds"`
	// ActiveSessions is the count of sessions currently running.
	ActiveSessions int `json:"activeSessions"`
	// MaxSessions is the declared capacity ceiling.
	MaxSessions int `json:"maxSessions"`
	// ProjectsAllowed is the number of projects in the allowlist.
	ProjectsAllowed int `json:"projectsAllowed"`
	// Timestamp is the RFC3339 time of this snapshot.
	Timestamp string `json:"timestamp"`
}

DaemonStatusResponse is the response from GET /api/daemon/status.

type DaemonYAML

type DaemonYAML struct {
	// Projects is the allowlist of repos the daemon will accept work for.
	Projects []ProjectEntry `yaml:"projects,omitempty"`
	// Capacity holds the configurable resource limits for the daemon.
	Capacity CapacityConfig `yaml:"capacity,omitempty"`
}

DaemonYAML is the in-memory representation of ~/.donmai/daemon.yaml. Only the fields relevant to the project command tree are modelled here; unknown top-level keys are preserved via the yaml decoder's pass-through.

func ReadDaemonYAML

func ReadDaemonYAML(path string) (*DaemonYAML, error)

ReadDaemonYAML reads and parses daemon.yaml from path. If the file does not exist an empty DaemonYAML is returned without error, so callers can treat first-run as a no-op read followed by a write.

func (*DaemonYAML) AddOrUpdateProject

func (d *DaemonYAML) AddOrUpdateProject(entry ProjectEntry)

AddOrUpdateProject upserts a ProjectEntry by RepoURL. If a matching entry exists it is replaced; otherwise the entry is appended.

func (*DaemonYAML) FindProject

func (d *DaemonYAML) FindProject(repoURL string) int

FindProject returns the index of the first ProjectEntry whose RepoURL matches repoURL, or -1 if not found.

func (*DaemonYAML) RemoveProject

func (d *DaemonYAML) RemoveProject(repoURL string) bool

RemoveProject removes the entry matching repoURL. Returns true if an entry was removed, false if none matched.

type DataSource

type DataSource interface {
	GetStats() (*StatsResponse, error)
	GetSessions() (*SessionsListResponse, error)
	GetSessionsFiltered(project string) (*SessionsListResponse, error)
	GetSessionDetail(id string) (*SessionDetailResponse, error)
	GetActivities(sessionID string, afterCursor *string) (*ActivityListResponse, error)
	StopSession(id string) (*StopSessionResponse, error)
	ChatSession(id string, req ChatSessionRequest) (*ChatSessionResponse, error)
	ReconnectSession(id string, req ReconnectSessionRequest) (*ReconnectSessionResponse, error)
	SubmitTask(req SubmitTaskRequest) (*SubmitTaskResponse, error)
	StopAgent(req StopAgentRequest) (*StopAgentResponse, error)
	ForwardPrompt(req ForwardPromptRequest) (*ForwardPromptResponse, error)
	GetCostReport() (*CostReportResponse, error)
	ListFleet() (*ListFleetResponse, error)

	// GetStatsV2 fetches fleet statistics extended with per-machine and
	// per-provider breakdowns.
	GetStatsV2() (*StatsResponseV2, error)

	// GetMachineStats fetches the per-machine capacity and status snapshot for
	// the registered daemon fleet (014 FleetGrid + MachinePivot primitives).
	GetMachineStats() ([]MachineStats, error)

	// GetWorkareaPoolStats fetches the local workarea pool snapshot for a given
	// machine. An empty machineID returns the aggregate across all machines.
	// Corresponds to `donmai daemon stats --pool` (011-local-daemon-fleet §Observability).
	GetWorkareaPoolStats(machineID MachineID) (*WorkareaPoolStats, error)

	// GetSandboxProviderStats fetches the runtime snapshot for all registered
	// SandboxProviders (004-sandbox-capability-matrix §Capacity snapshots).
	GetSandboxProviderStats() ([]SandboxProviderStats, error)

	// GetKitDetections fetches the kit detection results for a session.
	// Corresponds to the KitDetectResult TUI primitive in 014.
	GetKitDetections(sessionID string) ([]KitDetection, error)

	// GetKitContributions fetches the kit contribution summary for a session.
	// Corresponds to the KitContributionDiff TUI primitive in 014.
	GetKitContributions(sessionID string) ([]KitContribution, error)

	// GetAuditChain fetches the Layer 6 audit chain for a session.
	// Corresponds to the AuditChain TUI primitive in 014.
	GetAuditChain(sessionID string) ([]AuditChainEntry, error)

	// ListAgents fetches the AgentCards visible under the given scope query.
	// Empty ScopeQuery returns all cards visible to the caller's (org, project).
	// TODO: platform /api/agents endpoint is not yet implemented; this client
	// method is wired but returns ErrUnimplemented until the server-side
	// Lane A1 lands on main.
	ListAgents(scope AgentScopeQuery) ([]AgentCard, error)

	// GetAgent fetches a single AgentCard by its platform-generated ID ("ag_…").
	// TODO: platform /api/agents/<id> endpoint is not yet implemented; returns
	// ErrUnimplemented until Lane A1 lands.
	GetAgent(id string) (*AgentCard, error)
}

DataSource is the interface both Client and MockClient implement.

type EliminatedProvider

type EliminatedProvider struct {
	ProviderID string `json:"providerId"`
	Reason     string `json:"reason"`
	Detail     string `json:"detail,omitempty"`
}

EliminatedProvider captures a provider that was eliminated at a trace step.

type EvictPoolRequest

type EvictPoolRequest struct {
	// RepoURL restricts eviction to pool members cloned from this repository.
	// Required — the daemon refuses a request that omits it.
	RepoURL string `json:"repoUrl"`
	// OlderThanSeconds evicts members whose LastAcquiredAt (or CreatedAt when
	// never acquired) is older than this duration.  Must be > 0.
	OlderThanSeconds int64 `json:"olderThanSeconds"`
}

EvictPoolRequest is the body for POST /api/daemon/pool/evict. Exactly one eviction selector must be set.

type EvictPoolResponse

type EvictPoolResponse struct {
	// Evicted is the count of pool members scheduled for destruction.
	Evicted int `json:"evicted"`
	// Message is a human-readable summary.
	Message string `json:"message"`
	// CorrelationID is the Layer 6 hook event correlation ID emitted by the
	// daemon's observability subscriber. Consumers can match this
	// against the pool-stats-evict hook stream.
	CorrelationID string `json:"correlationId,omitempty"`
}

EvictPoolResponse is the response from POST /api/daemon/pool/evict.

type ForwardPromptRequest

type ForwardPromptRequest struct {
	TaskID  string `json:"taskId"`
	Message string `json:"message"`
}

ForwardPromptRequest matches POST /api/mcp/forward-prompt.

type ForwardPromptResponse

type ForwardPromptResponse struct {
	Forwarded     bool   `json:"forwarded"`
	PromptID      string `json:"promptId"`
	TaskID        string `json:"taskId"`
	IssueID       string `json:"issueId"`
	SessionStatus string `json:"sessionStatus"`
}

ForwardPromptResponse matches the forward-prompt response.

type Kit

type Kit struct {
	// Identity (from [kit] block in TOML manifest)
	ID          string `json:"id"`
	Name        string `json:"name"`
	Version     string `json:"version"`
	Description string `json:"description,omitempty"`
	Author      string `json:"author,omitempty"`
	AuthorID    string `json:"authorId,omitempty"` // did:web: identity
	License     string `json:"license,omitempty"`
	Homepage    string `json:"homepage,omitempty"`
	Repository  string `json:"repository,omitempty"`
	Priority    int    `json:"priority,omitempty"`

	// Runtime state
	Status KitStatus `json:"status"`
	Source KitSource `json:"source"`
	Scope  KitScope  `json:"scope"`

	// Trust / signature
	Trust    KitTrustState `json:"trust"`
	SignerID string        `json:"signerId,omitempty"`
	SignedAt string        `json:"signedAt,omitempty"`

	// Detect summary — shows what the kit detects without running detect.
	DetectFiles []string `json:"detectFiles,omitempty"`
	DetectExec  string   `json:"detectExec,omitempty"`

	// Contribution summary — concise view of what the kit provides.
	ProvidesCommands   bool `json:"providesCommands"`
	ProvidesPrompts    bool `json:"providesPrompts"`
	ProvidesTools      bool `json:"providesTools"`
	ProvidesMCPServers bool `json:"providesMcpServers"`
	ProvidesSkills     bool `json:"providesSkills"`
	ProvidesAgents     bool `json:"providesAgents"`
	ProvidesA2ASkills  bool `json:"providesA2aSkills"`
	ProvidesExtractors bool `json:"providesExtractors"`
}

Kit is the API representation of an installed kit as returned by GET /api/daemon/kits and GET /api/daemon/kits/<id>. Maps to the manifest schema in 005-kit-manifest-spec.md.

type KitContribution

type KitContribution struct {
	// KitID is the namespaced identifier of the contributing kit.
	KitID KitID `json:"kitId"`
	// KitVersion is the semver version string from the kit manifest.
	KitVersion string `json:"kitVersion"`
	// Commands is the set of build/test/validate commands contributed by this kit.
	// Keys are command names (e.g. "build", "test"); values are shell strings.
	Commands map[string]string `json:"commands,omitempty"`
	// PromptFragmentCount is the number of prompt fragments contributed.
	PromptFragmentCount int `json:"promptFragmentCount,omitempty"`
	// ToolPermissionCount is the number of tool permission grants contributed.
	ToolPermissionCount int `json:"toolPermissionCount,omitempty"`
	// MCPServerNames lists the names of MCP servers registered by this kit.
	MCPServerNames []string `json:"mcpServerNames,omitempty"`
	// SkillRefs lists the SKILL.md skill references contributed.
	SkillRefs []string `json:"skillRefs,omitempty"`
	// WorkareaCleanDirs is the union of clean_dirs declared by this kit.
	WorkareaCleanDirs []string `json:"workareaCleanDirs,omitempty"`
	// AppliedAt is the RFC3339 timestamp when this kit's provide() ran.
	AppliedAt string `json:"appliedAt"`
}

KitContribution summarises what an applied kit added to a session. Corresponds to KitContribution in 005 and the "KitContributionDiff" TUI primitive in 014-tui-operator-surfaces.md.

type KitDetection

type KitDetection struct {
	// KitID is the namespaced identifier of the detected kit.
	KitID KitID `json:"kitId"`
	// KitVersion is the semver version string from the kit manifest.
	KitVersion string `json:"kitVersion"`
	// Applies indicates whether the kit matched the workarea.
	Applies bool `json:"applies"`
	// Confidence is the match confidence score in the range [0, 1].
	Confidence float64 `json:"confidence"`
	// Reason is a human-readable explanation of the detection outcome.
	Reason string `json:"reason,omitempty"`
	// ToolchainDemand is the toolchain spec the kit would impose if applied.
	// Keys are toolchain names (e.g. "java", "node"); values are semver ranges.
	ToolchainDemand map[string]string `json:"toolchainDemand,omitempty"`
	// DetectPhase records which detection phase produced this result.
	// "declarative" means file-pattern match only; "executable" means the kit's
	// detect binary also ran.
	DetectPhase string `json:"detectPhase,omitempty"`
}

KitDetection is the result of running kit detection against a workarea. Corresponds to KitDetectResult in 005 and the "KitDetectResult" TUI primitive in 014-tui-operator-surfaces.md.

type KitHookEntry added in v0.10.0

type KitHookEntry struct {
	PostAcquire string `json:"postAcquire,omitempty"`
	PreRelease  string `json:"preRelease,omitempty"`
}

KitHookEntry is one OS-keyed hook overlay inside KitHooks.OS.

type KitHooks added in v0.10.0

type KitHooks struct {
	PostAcquire string                  `json:"postAcquire,omitempty"`
	PreRelease  string                  `json:"preRelease,omitempty"`
	OS          map[string]KitHookEntry `json:"os,omitempty"`
}

KitHooks carries the [provide.hooks] lifecycle scripts from a kit manifest (005:216-223). PostAcquire/PreRelease are the generic single-command forms; OS holds the OS-keyed overlay ([provide.hooks.os.<os>]). Most-specific (OS-keyed) wins at compose time.

type KitID

type KitID = string

KitID is the namespaced kit identifier as declared in the kit manifest (e.g. "spring/java", "ts/nextjs").

type KitInstallRequest

type KitInstallRequest struct {
	Version string            `json:"version,omitempty"`
	Source  *KitInstallSource `json:"source,omitempty"`
	// TrustOverride bypasses the configured trust gate for this single
	// install. The only accepted value is "allowed-this-once" (per
	// 002-provider-base-contract.md § "Signing and trust").
	// When set the daemon emits a structured slog audit log with the
	// kitId, signerId, actor, and timestamp. The override is single-shot:
	// not persisted; subsequent re-installs re-evaluate the gate. Empty
	// string = no override.
	TrustOverride string `json:"trustOverride,omitempty"`
}

KitInstallRequest is the request body for POST /api/daemon/kits/<id>/install.

type KitInstallResult

type KitInstallResult struct {
	Kit     Kit    `json:"kit"`
	Message string `json:"message,omitempty"`
}

KitInstallResult is returned by POST /api/daemon/kits/<id>/install.

type KitInstallSource

type KitInstallSource struct {
	// Kind selects the fetcher. Wave 12: "git" only.
	Kind string `json:"kind"`
	// URL is the fetcher-specific source URL (e.g., a git remote).
	URL string `json:"url"`
	// Ref is the optional git ref (branch/tag/commit). Default: HEAD.
	Ref string `json:"ref,omitempty"`
	// ManifestPath is the optional path inside the source to the kit
	// manifest. Default: registry walks the source root for *.kit.toml.
	ManifestPath string `json:"manifestPath,omitempty"`
}

KitInstallSource identifies where the daemon should fetch a kit from at install time. The wire shape is anchored in ADR-2026-05-07-daemon-http-control-api.md § D6 (Wave 12 amendment).

Wave 12 ships only `kind: "git"`; the remaining federation kinds (`tessl`, `agentskills`) return ErrKitSourceFederationUnimplemented in the registry. The descriptor list returned by /api/daemon/kit-sources continues to surface them so operators can see the federation order, but Install against them is unimplemented.

type KitManifest

type KitManifest struct {
	Kit

	// [supports]
	SupportedOS   []string `json:"supportedOs,omitempty"`
	SupportedArch []string `json:"supportedArch,omitempty"`

	// [requires]
	RequiresRensei       string   `json:"requiresRensei,omitempty"`
	RequiresCapabilities []string `json:"requiresCapabilities,omitempty"`

	// [composition]
	ConflictsWith []string `json:"conflictsWith,omitempty"`
	ComposesWith  []string `json:"composesWith,omitempty"`
	Order         string   `json:"order,omitempty"`

	// [detect] detail
	DetectToolchain map[string]string `json:"detectToolchain,omitempty"`

	// [provide.commands]
	Commands map[string]string `json:"commands,omitempty"`

	// [provide.commands_override.<os>] — OS-keyed command overlays.
	CommandsOverride map[string]map[string]string `json:"commandsOverride,omitempty"`

	// [provide.toolchain_install.<os>] — OS-keyed base-toolchain install
	// scripts (005:196-208). os → {key: shell command}. Surfaced so the
	// daemon HTTP detail (GET /api/daemon/kits/<id>) exposes the demand a
	// platform KitManifestSource can resolve into a ToolchainDemand.
	ToolchainInstall map[string]map[string]string `json:"toolchainInstall,omitempty"`

	// [provide.hooks] — post_acquire / pre_release lifecycle scripts
	// (005:216-223), with an optional OS-keyed overlay. Single command
	// string per hook.
	Hooks *KitHooks `json:"hooks,omitempty"`

	// Provide arrays — names/ids only for summary.
	MCPServerNames []string `json:"mcpServerNames,omitempty"`
	SkillFiles     []string `json:"skillFiles,omitempty"`
	AgentIDs       []string `json:"agentIds,omitempty"`
	A2ASkillIDs    []string `json:"a2aSkillIds,omitempty"`
	ExtractorNames []string `json:"extractorNames,omitempty"`
}

KitManifest is the full manifest detail for a kit, as returned by GET /api/daemon/kits/<id>. Richer view used by `kit show`.

type KitManifestEnvelope

type KitManifestEnvelope struct {
	Kit KitManifest `json:"kit"`
}

KitManifestEnvelope wraps the full manifest returned by GET /api/daemon/kits/<id>.

type KitRegistrySource

type KitRegistrySource struct {
	Name     string `json:"name"`
	URL      string `json:"url"`
	Enabled  bool   `json:"enabled"`
	Priority int    `json:"priority"` // federation order — lower = higher priority
	Kind     string `json:"kind"`     // "bundled" | "tessl" | "agentskills" | "community"
}

KitRegistrySource is a kit registry source descriptor.

type KitScope

type KitScope string

KitScope is the activation scope level, mirroring ProviderScope.

const (
	KitScopeProject KitScope = "project"
	KitScopeOrg     KitScope = "org"
	KitScopeTenant  KitScope = "tenant"
	KitScopeGlobal  KitScope = "global"
)

Kit activation scope levels (mirror of ProviderScope).

type KitSignatureResult

type KitSignatureResult struct {
	KitID    string        `json:"kitId"`
	Trust    KitTrustState `json:"trust"`
	SignerID string        `json:"signerId,omitempty"`
	SignedAt string        `json:"signedAt,omitempty"`
	OK       bool          `json:"ok"`
	Details  string        `json:"details,omitempty"`
}

KitSignatureResult is returned by GET /api/daemon/kits/<id>/verify-signature.

type KitSource

type KitSource string

KitSource identifies where a kit originated, per the federation order defined in 005-kit-manifest-spec.md § "Registry sources".

const (
	KitSourceLocal       KitSource = "local"       // .donmai/kits/*.kit.toml
	KitSourceBundled     KitSource = "bundled"     // shipped with OSS execution layer
	KitSourceTessl       KitSource = "tessl"       // registry.tessl.io
	KitSourceAgentSkills KitSource = "agentskills" // agentskills.io
	KitSourceCommunity   KitSource = "community"   // tenant-declared community/enterprise registries
)

Kit registry sources from the federation order in 005-kit-manifest-spec.md.

type KitSourceToggleResult

type KitSourceToggleResult struct {
	Source  KitRegistrySource `json:"source"`
	Message string            `json:"message,omitempty"`
}

KitSourceToggleResult is the response from POST /api/daemon/kit-sources/<name>/{enable,disable}.

type KitStatus

type KitStatus string

KitStatus is the activation status of an installed kit.

const (
	KitStatusActive   KitStatus = "active"
	KitStatusDisabled KitStatus = "disabled"
	KitStatusError    KitStatus = "error"
)

Kit activation statuses.

type KitTrustState

type KitTrustState string

KitTrustState encodes the three trust states visible in the operator surface, mirroring ProviderTrustState for consistency.

const (
	KitTrustSignedVerified   KitTrustState = "signed-verified"
	KitTrustSignedUnverified KitTrustState = "signed-unverified"
	KitTrustUnsigned         KitTrustState = "unsigned"
)

Kit trust states (mirror of ProviderTrustState).

type LLMProviderState

type LLMProviderState struct {
	ProviderID     string   `json:"providerId"`
	Model          string   `json:"model,omitempty"`
	Alpha          float64  `json:"alpha"`
	Beta           float64  `json:"beta"`
	RecentScore    *float64 `json:"recentScore,omitempty"`
	SelectionCount int      `json:"selectionCount"`
}

LLMProviderState is the Thompson-Sampling state for one LLM provider.

type ListFleetRequest

type ListFleetRequest struct {
	Status []string `json:"status,omitempty"`
	Limit  int      `json:"limit,omitempty"`
}

ListFleetRequest matches GET /api/mcp/list-fleet.

type ListFleetResponse

type ListFleetResponse struct {
	Total    int               `json:"total"`
	Returned int               `json:"returned"`
	Sessions []SessionResponse `json:"sessions"`
}

ListFleetResponse matches the list-fleet response.

type ListKitSourcesResponse

type ListKitSourcesResponse struct {
	Sources []KitRegistrySource `json:"sources"`
}

ListKitSourcesResponse matches GET /api/daemon/kit-sources.

type ListKitsResponse

type ListKitsResponse struct {
	Kits []Kit `json:"kits"`
}

ListKitsResponse matches GET /api/daemon/kits.

type ListProvidersResponse

type ListProvidersResponse struct {
	// Providers is the populated set across all covered families.
	Providers []Provider `json:"providers"`

	// PartialCoverage is true when CoveredFamilies is a strict subset of
	// AllProviderFamilies.
	PartialCoverage bool `json:"partialCoverage"`

	// CoveredFamilies enumerates the families this daemon currently
	// surfaces. In Wave 9 this is exactly ["agent-runtime"].
	CoveredFamilies []ProviderFamily `json:"coveredFamilies"`
}

ListProvidersResponse matches GET /api/daemon/providers.

Per ADR-2026-05-07-daemon-http-control-api.md § D4, the Wave-9 ship of the daemon's provider registry exposes only the AgentRuntime family (claude/codex/ollama/opencode/gemini/amp/stub). The remaining seven families return as empty until their per-family registries land in a future wave. Consumers MUST honour PartialCoverage when rendering — the "other families coming" caveat is sourced from the flag, not from sniffing for emptiness.

type ListWorkareasResponse

type ListWorkareasResponse struct {
	Active   []WorkareaSummary `json:"active"`
	Archived []WorkareaSummary `json:"archived"`
}

ListWorkareasResponse matches GET /api/daemon/workareas. Per ADR D4a, the daemon returns active pool members and on-disk archives in two arrays.

type MachineCapacity

type MachineCapacity struct {
	MaxConcurrentSessions int `json:"maxConcurrentSessions"`
	MaxVCpuPerSession     int `json:"maxVCpuPerSession,omitempty"`
	MaxMemoryMbPerSession int `json:"maxMemoryMbPerSession,omitempty"`
	ReservedVCpu          int `json:"reservedVCpu,omitempty"`
	ReservedMemoryMb      int `json:"reservedMemoryMb,omitempty"`
}

MachineCapacity describes the resource envelope for a single daemon machine. Field names match the capacity block in daemon.yaml (camelCase in wire format).

type MachineID

type MachineID = string

MachineID is a provider-namespaced opaque identifier for a registered machine (local daemon host). Matches the `machine.id` field in daemon.yaml.

type MachineStats

type MachineStats struct {
	// ID is the daemon-configured machine identifier (e.g. "mac-studio-marks-office").
	ID MachineID `json:"id"`
	// Region is the locality hint declared in daemon.yaml (e.g. "home-network").
	Region string `json:"region"`
	// Status is the current daemon lifecycle state.
	Status DaemonStatus `json:"status"`
	// Version is the rensei-daemon binary version string.
	Version string `json:"version"`
	// ActiveSessions is the count of sessions currently running on this machine.
	ActiveSessions int `json:"activeSessions"`
	// Capacity holds the declared resource envelope for this daemon.
	Capacity MachineCapacity `json:"capacity"`
	// UptimeSeconds is how long the daemon process has been running.
	UptimeSeconds int64 `json:"uptimeSeconds"`
	// LastSeenAt is an RFC3339 timestamp of the most recent heartbeat.
	LastSeenAt string `json:"lastSeenAt"`
}

MachineStats is the per-machine snapshot surfaced by the orchestrator for multi-machine fleet views (014-tui-operator-surfaces §Worker+Fleet section). Extended into StatsResponse.Machines to enable the "MachinePivot" TUI primitive.

type MockClient

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

MockClient returns realistic mock data matching the public API shapes.

func NewMockClient

func NewMockClient() *MockClient

NewMockClient creates a mock data source with 12 sample sessions.

func (*MockClient) ChatSession

func (m *MockClient) ChatSession(id string, _ ChatSessionRequest) (*ChatSessionResponse, error)

ChatSession returns a mock chat delivery response for a known session.

func (*MockClient) ForwardPrompt

func (m *MockClient) ForwardPrompt(req ForwardPromptRequest) (*ForwardPromptResponse, error)

ForwardPrompt returns a mock prompt-forwarding response.

func (*MockClient) GetActivities

func (m *MockClient) GetActivities(sessionID string, afterCursor *string) (*ActivityListResponse, error)

GetActivities returns mock activity events for a session.

func (*MockClient) GetAgent

func (m *MockClient) GetAgent(id string) (*AgentCard, error)

GetAgent returns the mock AgentCard for the given ID, or ErrNotFound.

func (*MockClient) GetAuditChain

func (m *MockClient) GetAuditChain(sessionID string) ([]AuditChainEntry, error)

GetAuditChain returns mock Layer 6 audit chain entries for a session.

func (*MockClient) GetCostReport

func (m *MockClient) GetCostReport() (*CostReportResponse, error)

GetCostReport returns a mock cost report.

func (*MockClient) GetKitContributions

func (m *MockClient) GetKitContributions(_ string) ([]KitContribution, error)

GetKitContributions returns mock kit contribution summaries for a session.

func (*MockClient) GetKitDetections

func (m *MockClient) GetKitDetections(_ string) ([]KitDetection, error)

GetKitDetections returns mock kit detection results for a session.

func (*MockClient) GetMachineStats

func (m *MockClient) GetMachineStats() ([]MachineStats, error)

GetMachineStats returns mock per-machine capacity and status snapshots.

func (*MockClient) GetSandboxProviderStats

func (m *MockClient) GetSandboxProviderStats() ([]SandboxProviderStats, error)

GetSandboxProviderStats returns mock runtime snapshots for registered SandboxProviders.

func (*MockClient) GetSessionDetail

func (m *MockClient) GetSessionDetail(id string) (*SessionDetailResponse, error)

GetSessionDetail returns mock detail for a single session.

func (*MockClient) GetSessions

func (m *MockClient) GetSessions() (*SessionsListResponse, error)

GetSessions returns the mock session list (fleet-wide).

func (*MockClient) GetSessionsFiltered

func (m *MockClient) GetSessionsFiltered(_ string) (*SessionsListResponse, error)

GetSessionsFiltered returns the mock session list. The project argument is accepted for interface compatibility but has no effect on mock data — all sessions are returned regardless of scope.

func (*MockClient) GetStats

func (m *MockClient) GetStats() (*StatsResponse, error)

GetStats returns mock fleet statistics.

func (*MockClient) GetStatsV2

func (m *MockClient) GetStatsV2() (*StatsResponseV2, error)

GetStatsV2 returns mock fleet statistics extended with per-machine and per-provider breakdowns. Returns realistic-but-empty slices so callers can safely introspect length and field structure without nil-pointer panics.

func (*MockClient) GetWorkareaPoolStats

func (m *MockClient) GetWorkareaPoolStats(_ MachineID) (*WorkareaPoolStats, error)

GetWorkareaPoolStats returns a mock workarea pool snapshot. The machineID argument is accepted for interface compatibility but has no effect on mock data — the same pool is returned regardless.

func (*MockClient) ListAgents

func (m *MockClient) ListAgents(_ AgentScopeQuery) ([]AgentCard, error)

ListAgents returns a small set of mock AgentCards covering the system-seeded workType taxonomy. The scope argument is accepted for interface compatibility but has no effect — all cards are returned regardless of scope.

func (*MockClient) ListFleet

func (m *MockClient) ListFleet() (*ListFleetResponse, error)

ListFleet returns a mock fleet listing.

func (*MockClient) ReconnectSession

ReconnectSession returns a mock reconnect response for a known session.

func (*MockClient) StopAgent

func (m *MockClient) StopAgent(req StopAgentRequest) (*StopAgentResponse, error)

StopAgent returns a mock stop-agent response.

func (*MockClient) StopSession

func (m *MockClient) StopSession(id string) (*StopSessionResponse, error)

StopSession returns a mock stop response for a known session, or ErrNotFound.

func (*MockClient) SubmitTask

func (m *MockClient) SubmitTask(req SubmitTaskRequest) (*SubmitTaskResponse, error)

SubmitTask returns a mock task submission response.

type PartialRef

type PartialRef struct {
	// ID is the platform-assigned partial identifier (e.g. "par_…").
	ID string `json:"id"`
	// MetadataID is the user-facing stable name (e.g. "code-review-guidelines").
	MetadataID string `json:"metadataId"`
	// Scope is the scope at which this partial was resolved.
	Scope string `json:"scope"`
	// Order is the insertion position within the assembled prompt; lower = earlier.
	Order *int `json:"order,omitempty"`
}

PartialRef is a reference to a named Partial in the partials catalog. Partials are prose-overlay fragments that the runtime assembles into the agent's system prompt before dispatch.

type ProjectEntry

type ProjectEntry struct {
	// ID is the daemon-side project identifier. The daemon reader requires
	// projects[i].id (see daemon/config.go validateConfig); DeriveProjectID
	// derives it automatically from the repo URL when the caller does not
	// set one (DeriveProjectID).
	ID string `yaml:"id,omitempty" json:"id,omitempty"`
	// RepoURL is the canonical remote URL, e.g. "github.com/foo/bar".
	RepoURL string `yaml:"repository" json:"repository"`
	// CloneStrategy controls how the daemon clones the repo. Default: shallow.
	CloneStrategy CloneStrategy `yaml:"cloneStrategy,omitempty" json:"cloneStrategy,omitempty"`
	// CredentialHelper is the credential source for this project.
	// A nil pointer means no credentials are configured (--no-credentials).
	CredentialHelper *CredentialHelper `yaml:"credentialHelper,omitempty" json:"credentialHelper,omitempty"`
}

ProjectEntry is one entry in the daemon.yaml `projects` list.

The yaml key for the repo URL is `repository`, matching the daemon-side reader (daemon.ProjectConfig). A past release renamed this from `repoUrl` to align writer + reader after a schema-drift bug where the writer emitted `repoUrl` but the reader looked for `repository`, causing `rensei daemon stats` to report `Projects: 0 allowed` after a successful `rensei project allow`. The Go field is still RepoURL for source-compat.

On read, ProjectEntry tolerates the legacy `repoUrl` key for one cycle (see UnmarshalYAML below) so pre-fix files in the wild still load.

func (*ProjectEntry) UnmarshalYAML

func (p *ProjectEntry) UnmarshalYAML(node *yaml.Node) error

UnmarshalYAML accepts either the canonical `repository` key or the legacy `repoUrl` key. When the legacy key is found a one-line warning is logged via slog so operators know to rewrite the file (the next write will use the canonical key automatically).

type Provider

type Provider struct {
	// Identity
	ID      string         `json:"id"`
	Name    string         `json:"name"`
	Version string         `json:"version"`
	Family  ProviderFamily `json:"family"`

	// Runtime state
	Scope  ProviderScope  `json:"scope"`
	Status ProviderStatus `json:"status"`
	Source ProviderSource `json:"source"`

	// Trust
	Trust      ProviderTrustState `json:"trust"`
	SignerID   string             `json:"signerId,omitempty"`
	SignedAt   string             `json:"signedAt,omitempty"`
	ManifestOK bool               `json:"manifestOk"`

	// Capabilities is the family-typed capability struct serialised as a
	// free-form JSON object. The typed shape varies per family; consumers
	// inspect Family to deserialise correctly. map[string]any lets the
	// CLI display and pass through the JSON without hardcoding every
	// family's struct.
	Capabilities map[string]any `json:"capabilities"`
}

Provider is the API representation of a registered provider, as returned by GET /api/daemon/providers and GET /api/daemon/providers/<id>. Maps to the base contract in 002-provider-base-contract.md.

type ProviderCost

type ProviderCost struct {
	Provider string  `json:"provider"`
	CostUsd  float64 `json:"costUsd"`
	Sessions int     `json:"sessions"`
}

ProviderCost is the per-provider cost breakdown entry used to extend StatsResponse. Provider is the sandbox/LLM provider name (e.g. "anthropic", "vercel", "e2b"). CostUsd is the accrued cost for the current reporting period.

type ProviderEnvelope

type ProviderEnvelope struct {
	Provider Provider `json:"provider"`
}

ProviderEnvelope wraps a single provider returned by GET /api/daemon/providers/<id>.

type ProviderFamily

type ProviderFamily string

ProviderFamily is one of the eight plugin families defined in 002-provider-base-contract.md. Values match the canonical string identifiers from the architecture corpus.

const (
	FamilySandbox       ProviderFamily = "sandbox"
	FamilyWorkarea      ProviderFamily = "workarea"
	FamilyAgentRuntime  ProviderFamily = "agent-runtime"
	FamilyVCS           ProviderFamily = "vcs"
	FamilyIssueTracker  ProviderFamily = "issue-tracker"
	FamilyDeployment    ProviderFamily = "deployment"
	FamilyAgentRegistry ProviderFamily = "agent-registry"
	FamilyKit           ProviderFamily = "kit"
)

Family identifiers for the eight Provider Family contracts in 002-provider-base-contract.md.

type ProviderScope

type ProviderScope string

ProviderScope is the activation scope level from 002-provider-base-contract.md.

const (
	ScopeProject ProviderScope = "project"
	ScopeOrg     ProviderScope = "org"
	ScopeTenant  ProviderScope = "tenant"
	ScopeGlobal  ProviderScope = "global"
)

Provider activation scope levels.

type ProviderSource

type ProviderSource string

ProviderSource is where the provider originated.

const (
	SourceBundled  ProviderSource = "bundled"
	SourceRegistry ProviderSource = "registry"
	SourceLocal    ProviderSource = "local"
)

Provider sources — where the registered provider originated.

type ProviderStatus

type ProviderStatus string

ProviderStatus is the current activation status.

const (
	StatusReady     ProviderStatus = "ready"
	StatusDegraded  ProviderStatus = "degraded"
	StatusUnhealthy ProviderStatus = "unhealthy"
	StatusInactive  ProviderStatus = "inactive"
)

Provider activation statuses.

type ProviderTrustState

type ProviderTrustState string

ProviderTrustState encodes the three trust states visible in the operator surface.

const (
	TrustSignedVerified   ProviderTrustState = "signed-verified"
	TrustSignedUnverified ProviderTrustState = "signed-unverified"
	TrustUnsigned         ProviderTrustState = "unsigned"
)

Provider trust states surfaced in the operator view.

type ReconnectSessionRequest

type ReconnectSessionRequest struct {
	Cursor      *string `json:"cursor,omitempty"`
	LastEventID *string `json:"lastEventId,omitempty"`
}

ReconnectSessionRequest is the body of POST /api/public/sessions/:id/reconnect. Cursor and LastEventID are both optional resume hints for the activity stream; callers may send either, neither, or both depending on what they have cached.

type ReconnectSessionResponse

type ReconnectSessionResponse struct {
	Reconnected   bool          `json:"reconnected"`
	SessionID     string        `json:"sessionId"`
	SessionStatus SessionStatus `json:"sessionStatus"`
	MissedEvents  int           `json:"missedEvents"`
}

ReconnectSessionResponse matches POST /api/public/sessions/:id/reconnect.

type RejectedCandidate

type RejectedCandidate struct {
	ProviderID string `json:"providerId"`
	// Dimension is the routing dimension: "sandbox" or "llm".
	Dimension string `json:"dimension"`
	// Reason categories from 004: "capability-filter", "tenant-policy",
	// "capacity-filter", "score-loss".
	Reason string `json:"reason"`
	Detail string `json:"detail,omitempty"`
}

RejectedCandidate is a provider that was considered but not chosen.

type RoutingConfig

type RoutingConfig struct {
	// CapabilityFilters are the active hard-filter constraints the
	// scheduler enforces before scoring (e.g. region, OS, arch, GPU
	// requirements).
	CapabilityFilters []CapabilityFilter `json:"capabilityFilters"`

	// Weights holds the tenant-level scoring bias between cost and
	// latency. Values sum to 1.0; default is {Cost: 0.7, Latency: 0.3}
	// per 004.
	Weights RoutingWeights `json:"weights"`

	// SandboxProviders lists the known sandbox provider IDs and their
	// Thompson-Sampling state (alpha, beta, recent scores).
	SandboxProviders []SandboxProviderState `json:"sandboxProviders"`

	// LLMProviders lists the known LLM provider IDs and their
	// Thompson-Sampling state.
	LLMProviders []LLMProviderState `json:"llmProviders"`

	// RecentDecisions is the last N routing decisions (capped at 50 for
	// the show view). Full history is available via the explain endpoint
	// keyed by session id.
	RecentDecisions []RoutingDecision `json:"recentDecisions"`

	// CapturedAt is when this snapshot was taken.
	CapturedAt time.Time `json:"capturedAt"`
}

RoutingConfig is the current routing configuration returned by GET /api/daemon/routing/config. It surfaces Thompson-Sampling state across both dimensions (LLM × sandbox) per 004-sandbox-capability-matrix.md and the capability-matrix reframe.

type RoutingConfigResponse

type RoutingConfigResponse struct {
	Config RoutingConfig `json:"config"`
}

RoutingConfigResponse wraps RoutingConfig in the /api/daemon/routing/config response.

type RoutingDecision

type RoutingDecision struct {
	SessionID          string              `json:"sessionId"`
	ChosenSandbox      string              `json:"chosenSandbox"`
	ChosenLLM          string              `json:"chosenLLM"`
	RejectedCandidates []RejectedCandidate `json:"rejectedCandidates,omitempty"`
	Score              float64             `json:"score"`
	EstimatedCostCents *float64            `json:"estimatedCostCents,omitempty"`
	EstimatedLatencyMs *float64            `json:"estimatedLatencyMs,omitempty"`
	DecidedAt          time.Time           `json:"decidedAt"`
}

RoutingDecision is a single scheduler dispatch decision, emitted as a Layer 6 hook event (kind: "routing-decision") per 002-provider-base-contract.md.

type RoutingExplainResponse

type RoutingExplainResponse struct {
	SessionID string             `json:"sessionId"`
	Decision  RoutingDecision    `json:"decision"`
	Trace     []RoutingTraceStep `json:"trace"`
}

RoutingExplainResponse is the full decision trace for a specific session, returned by GET /api/daemon/routing/explain/<sessionId>.

type RoutingTraceStep

type RoutingTraceStep struct {
	Step int `json:"step"`
	// Phase is the scheduler phase:
	// "capability-filter", "tenant-policy", "capacity-filter", "score".
	Phase string `json:"phase"`
	// Dimension is the routing dimension: "sandbox" or "llm".
	Dimension  string               `json:"dimension"`
	Remaining  []string             `json:"remaining"`
	Eliminated []EliminatedProvider `json:"eliminated,omitempty"`
	Note       string               `json:"note,omitempty"`
}

RoutingTraceStep is a single step in the scheduler's decision trace.

type RoutingWeights

type RoutingWeights struct {
	Cost    float64 `json:"cost"`
	Latency float64 `json:"latency"`
}

RoutingWeights is the tenant-level scoring bias between cost and latency.

type RuntimeKind

type RuntimeKind = string

RuntimeKind is the §2 enum of eight runtime path types.

const (
	RuntimeKindNative            RuntimeKind = "native"
	RuntimeKindNPM               RuntimeKind = "npm"
	RuntimeKindPythonPip         RuntimeKind = "python-pip"
	RuntimeKindHTTP              RuntimeKind = "http"
	RuntimeKindMCPServer         RuntimeKind = "mcp-server"
	RuntimeKindA2AProtocol       RuntimeKind = "a2a-protocol"
	RuntimeKindVendorHosted      RuntimeKind = "vendor-hosted"
	RuntimeKindLangchainRunnable RuntimeKind = "langchain-runnable"
)

RuntimeKind enum values; the eight runtime path types.

type RuntimePath

type RuntimePath struct {
	// Kind is the runtime type (RuntimeKind* constants).
	Kind string `json:"kind"`
	// Config holds kind-specific parameters as a raw JSON object.
	// Discriminated by Kind:
	//   native:              { providerId, modelProfileId? }
	//   npm:                 { package, versionSpec?, entrypoint? }
	//   python-pip:          { package, versionSpec?, entrypoint? }
	//   http:                { method, url, bodyTemplate? }
	//   mcp-server:          { transport, command?, args?, url? }
	//   a2a-protocol:        { endpoint, skillsAdvertised }
	//   vendor-hosted:       { vendor, vendorAgentId, sdk }
	//   langchain-runnable:  { hubRef, sdk, commitSha? }
	Config map[string]any `json:"config"`
	// Preference is an optional tie-breaker; lower = preferred.
	// Zero value means unspecified; natural array order is used.
	Preference *int `json:"preference,omitempty"`
}

RuntimePath is a single ordered preference entry in AgentCard.Runtimes. The Config field is kind-discriminated — see 11-runtime-binding-strategy.md §1 for the per-kind shape.

type SandboxBillingModel

type SandboxBillingModel string

SandboxBillingModel is the billing model declared by a SandboxProvider. Values match the `billingModel` capability field in 004.

const (
	// BillingWallClock means the provider charges for every second the sandbox runs.
	BillingWallClock SandboxBillingModel = "wall-clock"
	// BillingActiveCPU means the provider charges only for active CPU time.
	BillingActiveCPU SandboxBillingModel = "active-cpu"
	// BillingInvocation means the provider charges per invocation (FaaS-style).
	BillingInvocation SandboxBillingModel = "invocation"
	// BillingFixed means the provider uses user-owned hardware (no per-session charge).
	BillingFixed SandboxBillingModel = "fixed"
)

type SandboxProviderID

type SandboxProviderID = string

SandboxProviderID is an opaque identifier for a registered SandboxProvider. Corresponds to the `providerId` field on SandboxHandle in the architecture.

type SandboxProviderState

type SandboxProviderState struct {
	ProviderID      string   `json:"providerId"`
	Alpha           float64  `json:"alpha"`
	Beta            float64  `json:"beta"`
	RecentScore     *float64 `json:"recentScore,omitempty"`
	RecentCostCents *float64 `json:"recentCostCents,omitempty"`
	RecentLatencyMs *float64 `json:"recentLatencyMs,omitempty"`
	SelectionCount  int      `json:"selectionCount"`
}

SandboxProviderState is the Thompson-Sampling state for one sandbox provider.

type SandboxProviderStats

type SandboxProviderStats struct {
	// ID is the unique identifier for this provider (e.g. "local", "e2b", "vercel").
	ID SandboxProviderID `json:"id"`
	// DisplayName is the human-readable provider label.
	DisplayName string `json:"displayName"`
	// TransportModel is the declared transport mode for this provider.
	TransportModel SandboxTransportModel `json:"transportModel"`
	// BillingModel is the declared billing model for this provider.
	BillingModel SandboxBillingModel `json:"billingModel"`
	// ProvisionedActive is the count of sandboxes currently running.
	ProvisionedActive int `json:"provisionedActive"`
	// ProvisionedPaused is the count of paused sandboxes (storage-cost only).
	ProvisionedPaused int `json:"provisionedPaused"`
	// MaxConcurrent is the declared ceiling, or -1 for unbounded.
	MaxConcurrent int `json:"maxConcurrent"`
	// Regions is the list of ISO region codes this provider serves; ["*"] means any.
	Regions []string `json:"regions"`
	// SupportsPauseResume indicates memory+FS preserve capability (e.g. E2B).
	SupportsPauseResume bool `json:"supportsPauseResume"`
	// SupportsFsSnapshot indicates FS-only snapshot capability (e.g. Vercel).
	SupportsFsSnapshot bool `json:"supportsFsSnapshot"`
	// IsA2ARemote indicates this provider represents a remote A2A agent peer.
	IsA2ARemote bool `json:"isA2ARemote"`
	// Healthy is false when the provider is in a degraded or unhealthy state.
	Healthy bool `json:"healthy"`
	// CapturedAt is the RFC3339 timestamp of this capacity snapshot.
	CapturedAt string `json:"capturedAt"`
}

SandboxProviderStats is the runtime snapshot for a registered SandboxProvider. Used by the dashboard "SandboxProvider awareness" panel and the scheduler's capacity-filter step (004 §Scheduling algorithm step 3).

type SandboxTransportModel

type SandboxTransportModel string

SandboxTransportModel is the transport model declared by a SandboxProvider. Values match the `transportModel` capability field in 004.

const (
	// TransportDialIn means the orchestrator initiates connections to the sandbox.
	TransportDialIn SandboxTransportModel = "dial-in"
	// TransportDialOut means the worker boots and dials the orchestrator.
	TransportDialOut SandboxTransportModel = "dial-out"
	// TransportEither means both models are supported; orchestrator picks.
	TransportEither SandboxTransportModel = "either"
)

type SessionDetail

type SessionDetail struct {
	ID           string          `json:"id"`
	Identifier   string          `json:"identifier"`
	Status       SessionStatus   `json:"status"`
	WorkType     string          `json:"workType"`
	StartedAt    string          `json:"startedAt"`
	Duration     int             `json:"duration"`
	Timeline     SessionTimeline `json:"timeline"`
	Provider     *string         `json:"provider,omitempty"`
	Branch       *string         `json:"branch,omitempty"`
	IssueTitle   *string         `json:"issueTitle,omitempty"`
	CostUsd      *float64        `json:"costUsd,omitempty"`
	InputTokens  *int            `json:"inputTokens,omitempty"`
	OutputTokens *int            `json:"outputTokens,omitempty"`
}

SessionDetail is the inner session object in the detail response.

type SessionDetailResponse

type SessionDetailResponse struct {
	Session   SessionDetail `json:"session"`
	Timestamp string        `json:"timestamp"`
}

SessionDetailResponse matches GET /api/public/sessions/:id.

type SessionResponse

type SessionResponse struct {
	ID         string        `json:"id"`
	Identifier string        `json:"identifier"`
	Status     SessionStatus `json:"status"`
	WorkType   string        `json:"workType"`
	StartedAt  string        `json:"startedAt"`
	Duration   int           `json:"duration"`
	CostUsd    *float64      `json:"costUsd,omitempty"`
	Provider   *string       `json:"provider,omitempty"`
}

SessionResponse matches a single session in GET /api/public/sessions.

type SessionStatus

type SessionStatus string

SessionStatus matches the public API status union type.

const (
	StatusQueued    SessionStatus = "queued"
	StatusParked    SessionStatus = "parked"
	StatusWorking   SessionStatus = "working"
	StatusCompleted SessionStatus = "completed"
	StatusFailed    SessionStatus = "failed"
	StatusStopped   SessionStatus = "stopped"
)

Session status values matching the public API status union type.

type SessionTimeline

type SessionTimeline struct {
	Created   string  `json:"created"`
	Queued    *string `json:"queued,omitempty"`
	Started   *string `json:"started,omitempty"`
	Completed *string `json:"completed,omitempty"`
}

SessionTimeline represents the timeline in a session detail response.

type SessionsListResponse

type SessionsListResponse struct {
	Sessions  []SessionResponse `json:"sessions"`
	Count     int               `json:"count"`
	Timestamp string            `json:"timestamp"`
}

SessionsListResponse matches GET /api/public/sessions.

type SetCapacityResponse

type SetCapacityResponse struct {
	// OK is true when the config key was accepted and written to daemon.yaml.
	OK bool `json:"ok"`
	// Key is the dotted config key that was set (e.g. "capacity.poolMaxDiskGb").
	Key string `json:"key"`
	// Value is the string representation of the new value.
	Value string `json:"value"`
	// Message is a human-readable description of the outcome.
	Message string `json:"message"`
}

SetCapacityResponse is the response from POST /api/daemon/capacity.

type StatsResponse

type StatsResponse struct {
	WorkersOnline     int     `json:"workersOnline"`
	AgentsWorking     int     `json:"agentsWorking"`
	QueueDepth        int     `json:"queueDepth"`
	CompletedToday    int     `json:"completedToday"`
	AvailableCapacity int     `json:"availableCapacity"`
	TotalCostToday    float64 `json:"totalCostToday"`
	TotalCostAllTime  float64 `json:"totalCostAllTime"`
	SessionCountToday int     `json:"sessionCountToday"`
	Timestamp         string  `json:"timestamp"`
}

StatsResponse matches GET /api/public/stats.

type StatsResponseV2

type StatsResponseV2 struct {
	StatsResponse
	// Machines is the per-machine capacity and status breakdown.
	// Empty when the platform has no multi-machine fleet registered.
	Machines []MachineStats `json:"machines,omitempty"`
	// Providers is the per-provider cost and capacity breakdown.
	// Empty when no provider cost data is available.
	Providers []ProviderCost `json:"providers,omitempty"`
}

StatsResponseV2 extends StatsResponse with per-machine and per-provider breakdowns required by the multi-machine fleet view (009 §issue #56) and the SandboxProvider awareness panel (009 §issue #59).

We add the new fields as a separate embedded struct to keep the original StatsResponse wire-compatible; callers that don't need the new fields can continue using StatsResponse directly.

type StopAgentRequest

type StopAgentRequest struct {
	TaskID string `json:"taskId"`
}

StopAgentRequest matches POST /api/mcp/stop-agent.

type StopAgentResponse

type StopAgentResponse struct {
	Stopped        bool   `json:"stopped"`
	TaskID         string `json:"taskId"`
	IssueID        string `json:"issueId"`
	PreviousStatus string `json:"previousStatus"`
	NewStatus      string `json:"newStatus"`
}

StopAgentResponse matches the stop-agent response.

type StopSessionResponse

type StopSessionResponse struct {
	Stopped        bool          `json:"stopped"`
	SessionID      string        `json:"sessionId"`
	PreviousStatus SessionStatus `json:"previousStatus"`
	NewStatus      SessionStatus `json:"newStatus"`
}

StopSessionResponse matches POST /api/public/sessions/:id/stop.

type SubmitTaskRequest

type SubmitTaskRequest struct {
	IssueID     string `json:"issueId"`
	Description string `json:"description,omitempty"`
	WorkType    string `json:"workType,omitempty"`
	Priority    int    `json:"priority,omitempty"`
}

SubmitTaskRequest matches POST /api/mcp/submit-task.

type SubmitTaskResponse

type SubmitTaskResponse struct {
	Submitted bool   `json:"submitted"`
	TaskID    string `json:"taskId"`
	IssueID   string `json:"issueId"`
	Status    string `json:"status"`
	Priority  int    `json:"priority"`
	WorkType  string `json:"workType"`
}

SubmitTaskResponse matches the submit-task response.

type SubstrateRequirement

type SubstrateRequirement struct {
	// Kind is one of: network-egress | host-binary | workarea | gpu | persistent-storage | long-running.
	Kind string `json:"kind"`
	// Config holds kind-specific parameters as a raw JSON object.
	// Discriminated by Kind:
	//   network-egress:      { hosts: string[] }
	//   host-binary:         { name, minVersion? }
	//   workarea:            { mode: 'fresh'|'persistent', sizeMB? }
	//   long-running:        { maxDurationSec, suspendable }
	Config map[string]any `json:"config"`
}

SubstrateRequirement declares a substrate need beyond the runtime path itself. Examples: network egress to specific hosts, host binaries, GPU, persistent storage.

type TrustClaims

type TrustClaims struct {
	// Tier is the trust classification: system | partner | community | untrusted.
	Tier string `json:"tier"`
	// Signature is an optional detached signature over the card body.
	Signature *string `json:"signature,omitempty"`
	// SigningKeyID is the mount-asserted key identifier used to verify Signature.
	SigningKeyID *string `json:"signingKeyId,omitempty"`
	// Provenance records the import chain for auditing.
	Provenance TrustProvenanceInfo `json:"provenance"`
	// EvaluatedQualityScore is a Tessl-style 0-1 composite quality metric.
	EvaluatedQualityScore *float64 `json:"evaluatedQualityScore,omitempty"`
}

TrustClaims carries the security posture of an AgentCard. Consumed at dispatch time by Cedar policy gates.

type TrustProvenanceInfo

type TrustProvenanceInfo struct {
	// SourceURL is the canonical upstream source (e.g. a GitHub tree URL).
	SourceURL *string `json:"sourceUrl,omitempty"`
	// SourceCommit is the git commit sha at import time.
	SourceCommit *string `json:"sourceCommit,omitempty"`
	// ImportedBy is the operator or system principal that mounted the ARP.
	ImportedBy string `json:"importedBy"`
	// ImportedAt is the RFC3339 timestamp of import.
	ImportedAt string `json:"importedAt"`
}

TrustProvenanceInfo records the import provenance for a card.

type WhoAmIOrg

type WhoAmIOrg struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	Slug string `json:"slug"`
	Plan string `json:"plan"`
}

WhoAmIOrg is the organization details from whoami.

type WhoAmIProject

type WhoAmIProject struct {
	ID              string `json:"id"`
	Name            string `json:"name"`
	Slug            string `json:"slug"`
	IsDefault       bool   `json:"isDefault"`
	SandboxProvider string `json:"sandboxProvider"`
	TeamSlug        string `json:"teamSlug"`
	TeamName        string `json:"teamName"`
}

WhoAmIProject is a project from whoami.

type WhoAmIResponse

type WhoAmIResponse struct {
	Org      WhoAmIOrg       `json:"org"`
	Projects []WhoAmIProject `json:"projects"`
	Scopes   []string        `json:"scopes"`
}

WhoAmIResponse matches GET /api/cli/whoami.

type Workarea

type Workarea struct {
	ID                 string             `json:"id"`
	Kind               WorkareaKind       `json:"kind"`
	ProviderID         string             `json:"providerId"`
	SessionID          string             `json:"sessionId,omitempty"`
	ProjectID          string             `json:"projectId,omitempty"`
	Status             WorkareaPoolStatus `json:"status"`
	Path               string             `json:"path,omitempty"`
	Ref                string             `json:"ref,omitempty"`
	Repository         string             `json:"repository,omitempty"`
	CleanStateChecksum string             `json:"cleanStateChecksum,omitempty"`
	Toolchain          map[string]string  `json:"toolchain,omitempty"`
	Mode               string             `json:"mode,omitempty"`        // "exclusive" | "shared"
	AcquirePath        string             `json:"acquirePath,omitempty"` // "pool-warm" | "pool-fresh" | "cold"
	AcquiredAt         *time.Time         `json:"acquiredAt,omitempty"`
	ReleasedAt         *time.Time         `json:"releasedAt,omitempty"`
	ArchiveLocation    string             `json:"archiveLocation,omitempty"`
	OwnerSession       string             `json:"ownerSession,omitempty"`

	// Manifest is the captured per-archive manifest for archived
	// workareas (kind = "archived"). Free-form JSON keyed by archive
	// version; consumers display rather than enforce shape.
	Manifest map[string]any `json:"manifest,omitempty"`
}

Workarea is the full workarea record returned by GET /api/daemon/workareas/<id> (inspect endpoint). Fields match the Workarea interface in 003-workarea-provider.md.

type WorkareaDiffEntry

type WorkareaDiffEntry struct {
	Path   string             `json:"path"`
	Status WorkareaDiffStatus `json:"status"`

	SizeA int64  `json:"sizeA,omitempty"`
	SizeB int64  `json:"sizeB,omitempty"`
	ModeA string `json:"modeA,omitempty"`
	ModeB string `json:"modeB,omitempty"`
	HashA string `json:"hashA,omitempty"`
	HashB string `json:"hashB,omitempty"`
}

WorkareaDiffEntry is a single per-path entry in a workarea diff. Hashes are SHA-256 over file contents; missing for directories. Symlinks compared by target string.

type WorkareaDiffEnvelope

type WorkareaDiffEnvelope struct {
	Diff WorkareaDiffResult `json:"diff"`
}

WorkareaDiffEnvelope is the single-JSON response shape from GET /api/daemon/workareas/<idA>/diff/<idB> when entries ≤ the daemon's configured streaming threshold (default 1000, see daemon.yaml key workarea.diffStreamingThreshold). Consumers MUST handle both this shape and the NDJSON streaming variant via Content-Type discrimination per ADR D4a.

type WorkareaDiffResult

type WorkareaDiffResult struct {
	Summary WorkareaDiffSummary `json:"summary"`
	Entries []WorkareaDiffEntry `json:"entries"`
}

WorkareaDiffResult is the diff payload itself.

type WorkareaDiffStatus

type WorkareaDiffStatus string

WorkareaDiffStatus is the per-entry change classification.

const (
	WorkareaDiffStatusAdded    WorkareaDiffStatus = "added"
	WorkareaDiffStatusRemoved  WorkareaDiffStatus = "removed"
	WorkareaDiffStatusModified WorkareaDiffStatus = "modified"
)

Per-entry diff change classifications.

type WorkareaDiffSummary

type WorkareaDiffSummary struct {
	WorkareaA string `json:"workareaA"`
	WorkareaB string `json:"workareaB"`
	Added     int    `json:"added"`
	Removed   int    `json:"removed"`
	Modified  int    `json:"modified"`
	Total     int    `json:"total"`
}

WorkareaDiffSummary is the aggregate-counts envelope. In a single-JSON response (entries below the streaming threshold) it sits alongside Entries; in NDJSON streaming it ships as the final line.

type WorkareaEnvelope

type WorkareaEnvelope struct {
	Workarea Workarea `json:"workarea"`
}

WorkareaEnvelope wraps a single Workarea returned by GET /api/daemon/workareas/<id>.

type WorkareaKind

type WorkareaKind string

WorkareaKind disambiguates active pool members from on-disk archives in the GET /api/daemon/workareas response.

const (
	WorkareaKindActive   WorkareaKind = "active"
	WorkareaKindArchived WorkareaKind = "archived"
)

Workarea kinds discriminate between live pool members and on-disk archives.

type WorkareaPoolMember

type WorkareaPoolMember struct {
	// ID is the provider-namespaced workarea identifier.
	ID string `json:"id"`
	// Repository is the git remote URL this pool member is cloned from.
	Repository string `json:"repository"`
	// Ref is the commit or branch actually checked out.
	Ref string `json:"ref"`
	// ToolchainKey is the canonical key for the toolchain set (e.g. "node-20+java-17").
	ToolchainKey string `json:"toolchainKey"`
	// Status is the current pool member lifecycle state.
	Status WorkareaPoolMemberStatus `json:"status"`
	// CleanStateChecksum is the sha256 of the canonical clean-state files.
	CleanStateChecksum string `json:"cleanStateChecksum"`
	// AcquiredBy is the session ID currently holding this member, or empty.
	AcquiredBy string `json:"acquiredBy,omitempty"`
	// CreatedAt is the RFC3339 timestamp of initial pool member creation.
	CreatedAt string `json:"createdAt"`
	// LastAcquiredAt is the RFC3339 timestamp of the most recent acquire (for LRU eviction).
	LastAcquiredAt string `json:"lastAcquiredAt,omitempty"`
	// DiskUsageMb is the approximate on-disk size of this pool member.
	DiskUsageMb int64 `json:"diskUsageMb,omitempty"`
}

WorkareaPoolMember describes a single entry in the local workarea pool. Keyed by (Repository, ToolchainKey) per the pool management design in 003.

type WorkareaPoolMemberStatus

type WorkareaPoolMemberStatus string

WorkareaPoolMemberStatus is the lifecycle state of a single warm-pool member. Values match the state machine in 003-workarea-provider.md §Pool member states.

const (
	// PoolMemberWarming means the clone + install is in progress.
	PoolMemberWarming WorkareaPoolMemberStatus = "warming"
	// PoolMemberReady means the member is clean and available for acquire.
	PoolMemberReady WorkareaPoolMemberStatus = "ready"
	// PoolMemberAcquired means the member is currently held by a session.
	PoolMemberAcquired WorkareaPoolMemberStatus = "acquired"
	// PoolMemberReleasing means a scoped clean is in progress before returning to ready.
	PoolMemberReleasing WorkareaPoolMemberStatus = "releasing"
	// PoolMemberInvalid means the lockfile changed or staleness exceeded; pending rebuild.
	PoolMemberInvalid WorkareaPoolMemberStatus = "invalid"
	// PoolMemberRetired means the member is slated for destruction.
	PoolMemberRetired WorkareaPoolMemberStatus = "retired"
)

type WorkareaPoolStats

type WorkareaPoolStats struct {
	// Members is the full list of pool members across all (repo, toolchain) keys.
	Members []WorkareaPoolMember `json:"members"`
	// TotalMembers is the count of all pool members regardless of status.
	TotalMembers int `json:"totalMembers"`
	// ReadyMembers is the count of members in the "ready" state.
	ReadyMembers int `json:"readyMembers"`
	// AcquiredMembers is the count of members currently held by sessions.
	AcquiredMembers int `json:"acquiredMembers"`
	// WarmingMembers is the count of members still being initialised.
	WarmingMembers int `json:"warmingMembers"`
	// InvalidMembers is the count of members pending rebuild.
	InvalidMembers int `json:"invalidMembers"`
	// TotalDiskUsageMb is the sum of DiskUsageMb across all pool members.
	TotalDiskUsageMb int64 `json:"totalDiskUsageMb"`
	// Timestamp is the RFC3339 capture time of this snapshot.
	Timestamp string `json:"timestamp"`
}

WorkareaPoolStats is the aggregate view of the local workarea pool returned by `donmai daemon stats --pool`. Matches the "WorkareaPoolPanel" TUI primitive in 014-tui-operator-surfaces.md.

type WorkareaPoolStatus

type WorkareaPoolStatus string

WorkareaPoolStatus is the state of a workarea pool member, from the pool-member state machine in 003-workarea-provider.md.

const (
	WorkareaStatusWarming   WorkareaPoolStatus = "warming"
	WorkareaStatusReady     WorkareaPoolStatus = "ready"
	WorkareaStatusAcquired  WorkareaPoolStatus = "acquired"
	WorkareaStatusReleasing WorkareaPoolStatus = "releasing"
	WorkareaStatusInvalid   WorkareaPoolStatus = "invalid"
	WorkareaStatusRetired   WorkareaPoolStatus = "retired"
	WorkareaStatusArchived  WorkareaPoolStatus = "archived"
)

Pool-member states from the workarea state machine in 003-workarea-provider.md.

type WorkareaRestoreRequest

type WorkareaRestoreRequest struct {
	// Reason is an optional human-readable justification recorded in the
	// daemon's audit log alongside the restore.
	Reason string `json:"reason,omitempty"`
	// IntoSessionId optionally pins the restored workarea to a specific
	// session id. If the id is already in use the daemon returns 409.
	IntoSessionID string `json:"intoSessionId,omitempty"`
}

WorkareaRestoreRequest is the body for POST /api/daemon/workareas/<archiveID>/restore. Per ADR D4a, restore materialises the named archive into a fresh active pool member.

type WorkareaRestoreResult

type WorkareaRestoreResult struct {
	Workarea Workarea `json:"workarea"`
}

WorkareaRestoreResult is the response from POST /api/daemon/workareas/<archiveID>/restore. The new id is distinct from the archive id (archives are immutable per ADR D4a).

type WorkareaSummary

type WorkareaSummary struct {
	ID         string             `json:"id"`
	Kind       WorkareaKind       `json:"kind"`
	ProviderID string             `json:"providerId"`
	SessionID  string             `json:"sessionId,omitempty"`
	ProjectID  string             `json:"projectId,omitempty"`
	Status     WorkareaPoolStatus `json:"status"`
	Ref        string             `json:"ref,omitempty"`
	Repository string             `json:"repository,omitempty"`

	// Archive-only fields. Populated when Kind == WorkareaKindArchived.
	CreatedAt      *time.Time `json:"createdAt,omitempty"`
	SizeBytes      int64      `json:"sizeBytes,omitempty"`
	SourceProvider string     `json:"sourceProvider,omitempty"`
	Disposition    string     `json:"disposition,omitempty"`

	// Active-only fields. Populated when Kind == WorkareaKindActive.
	AcquiredAt *time.Time `json:"acquiredAt,omitempty"`
	ReleasedAt *time.Time `json:"releasedAt,omitempty"`
	AgeSeconds int64      `json:"ageSeconds,omitempty"`
}

WorkareaSummary is a single workarea entry returned by GET /api/daemon/workareas (list endpoint). The same shape covers both active pool members and on-disk archives; consumers use Kind to disambiguate.

Directories

Path Synopsis
Package codeintel — native arch-intel diff/gate layer.
Package codeintel — native arch-intel diff/gate layer.
Package logsignatures implements the log-signature catalog and pattern-matching logic for the `donmai logs analyze` command.
Package logsignatures implements the log-signature catalog and pattern-matching logic for the `donmai logs analyze` command.
Package orchestrator implements the local orchestrator entrypoint for OSS users who do not run the daemon.
Package orchestrator implements the local orchestrator entrypoint for OSS users who do not run the daemon.
Package queue provides Redis-backed admin clients for the AgentFactory work queue and merge queue.
Package queue provides Redis-backed admin clients for the AgentFactory work queue and merge queue.
Package repoconfig loads and validates the .donmai/config.yaml file (RepositoryConfig kind).
Package repoconfig loads and validates the .donmai/config.yaml file (RepositoryConfig kind).

Jump to

Keyboard shortcuts

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