ledger

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: AGPL-3.0 Imports: 17 Imported by: 0

Documentation

Overview

Package ledger defines immutable identity types, snapshots, and the repository boundary for subagent orchestration. It provides the storage abstraction that the coordinator depends on, with an in-memory default implementation.

Index

Constants

View Source
const (
	RefKindOutput    = sdkadapter.KindOutput
	RefKindError     = sdkadapter.KindError
	RefKindMessage   = sdkadapter.KindMessage
	RefKindToolCalls = sdkadapter.KindToolCalls
	RefKindNote      = sdkadapter.KindNote
)

Reference kinds for content-addressed task results and agent messages.

Variables

View Source
var (
	ErrDuplicate         = ledgercore.ErrDuplicate
	ErrNotFound          = ledgercore.ErrNotFound
	ErrInvalidTransition = ledgercore.ErrInvalidTransition
	ErrConflict          = ledgercore.ErrConflict
	ErrClosed            = ledgercore.ErrClosed
	ErrInvalidReference  = errors.New("invalid ledger reference")
	ErrClaimHeld         = ledgercore.ErrClaimHeld
	ErrClaimNotHeld      = ledgercore.ErrClaimNotHeld
	ErrContentNotFound   = ledgercore.ErrContentNotFound
)

Sentinel errors returned by LedgerRepository methods.

View Source
var ErrMalformedReference = sdkadapter.ErrMalformedReference

ErrMalformedReference reports a reference that is not in canonical form.

Functions

func ParseReference

func ParseReference(ref string) (kind, digest string, err error)

ParseReference splits a canonical reference into its kind and hex digest, returning ErrMalformedReference for any other shape.

func RebuildProjection

func RebuildProjection(events []storage.Event) (RunSnapshot, []TaskSnapshot, []LifecycleEvent, error)

RebuildProjection replays storage events in sequence order to reconstruct the current RunSnapshot, task list, and lifecycle events. It is a pure deterministic function: the same event slice always produces the same state. Returns zero values if events is empty.

func Reference

func Reference(kind string, data []byte) string

Reference returns the canonical reference for data: "ref:<kind>:<64 hex>". It returns "" for empty data or an unrecognised kind.

func ValidRunTransitions

func ValidRunTransitions(oldStatus, newStatus RunStatus) bool

ValidRunTransitions returns true if the transition from oldStatus to newStatus is valid for a run.

func ValidTaskTransition

func ValidTaskTransition(oldStatus, newStatus string) bool

ValidTaskTransitions returns true if the transition from oldStatus to newStatus is valid per the state model:

queued -> running
queued/running -> cancel_requested -> canceled
running -> {completed, failed, timed_out, blocked, retry_pending, awaiting_input}
awaiting_input -> {running, cancel_requested, canceled, timed_out, failed}
failed/timed_out -> retry_pending -> {queued, canceled}
failed/timed_out -> blocked
completed, canceled, blocked are terminal

awaiting_input is the first status that may return to running (plan 53.02).

Types

type AttemptID

type AttemptID string

AttemptID is a system-generated immutable identifier for one execution attempt.

type AttemptSnapshot

type AttemptSnapshot struct {
	AttemptID  string
	TaskID     string
	RunID      string
	AttemptNum int
	StartedAt  time.Time
	FinishedAt *time.Time
	Status     string
}

AttemptSnapshot captures one execution attempt for a task.

func (AttemptSnapshot) Clone

func (s AttemptSnapshot) Clone() AttemptSnapshot

Clone returns a deep copy of the snapshot.

type DisplayNameGenerator

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

DisplayNameGenerator allocates unique human-readable display names scoped to a run. Names use a base format like "agent-1", "agent-2", etc. and handle collisions with numeric suffixes.

func NewDisplayNameGenerator

func NewDisplayNameGenerator() *DisplayNameGenerator

NewDisplayNameGenerator creates a new generator with an empty used set.

func (*DisplayNameGenerator) Generate

func (g *DisplayNameGenerator) Generate(base string) string

Generate returns a unique display name for the given base name. If the base name is empty, it defaults to "agent". The generated name is guaranteed to be unique among all names generated by this instance.

func (*DisplayNameGenerator) Reserve

func (g *DisplayNameGenerator) Reserve(name string)

Reserve marks a display name as already used. Useful for deterministic test injection or restoring names from a persistent store.

func (*DisplayNameGenerator) Reset

func (g *DisplayNameGenerator) Reset()

Reset clears all reserved names and resets the counter. Used in tests.

type LeaseRepository

type LeaseRepository interface {
	TakeoverExpiredRunClaim(context.Context, string, string, time.Duration) error
}

LeaseRepository can take a claim only after its heartbeat expires.

type LedgerRepository

type LedgerRepository interface {
	AdmitSingleTask(context.Context, SingleTaskAdmission) error
	// CreateRun creates a new run record. Returns ErrDuplicate if an
	// idempotency-key matched run already exists.
	CreateRun(ctx context.Context, key string, snapshot RunSnapshot) error

	// GetRun returns a defensive copy of the current run snapshot.
	// Returns ErrNotFound if the run does not exist.
	GetRun(ctx context.Context, runID string) (RunSnapshot, error)

	// GetRunByIdempotencyKey returns the run previously created with key.
	// Returns ErrNotFound for an empty or unknown key.
	GetRunByIdempotencyKey(ctx context.Context, key string) (RunSnapshot, error)

	// ListRuns returns bounded snapshots, optionally filtered by status.
	ListRuns(ctx context.Context, status ...RunStatus) ([]RunSnapshot, error)

	// CreateTask creates a new task record within a run.
	// Returns ErrDuplicate if the task ID already exists.
	// Returns ErrNotFound if the run does not exist.
	// Returns ErrClosed if the run has been closed/deleted.
	CreateTask(ctx context.Context, snap TaskSnapshot) error

	// GetTask returns a defensive copy of a task snapshot.
	// Returns ErrNotFound if the task does not exist.
	GetTask(ctx context.Context, runID, taskID string) (TaskSnapshot, error)

	// ListTasks returns all task snapshots for a run, ordered by creation.
	ListTasks(ctx context.Context, runID string) ([]TaskSnapshot, error)

	// AppendEvent records a lifecycle event with idempotency-key dedup.
	// Returns ErrDuplicate if the event ID already exists.
	AppendEvent(ctx context.Context, event LifecycleEvent) error

	// ListEvents returns all events for a run, ordered by sequence.
	ListEvents(ctx context.Context, runID string) ([]LifecycleEvent, error)

	// CompareAndSetTaskStatus atomically transitions a task's status and
	// increments its version. Returns ErrConflict if the current version
	// does not match expectedVersion. Returns ErrInvalidTransition if
	// the status change is not valid.
	CompareAndSetTaskStatus(ctx context.Context, runID, taskID string,
		expectedVersion uint64, newStatus string) error

	// SetTaskOutput stores a bounded redacted output/error/tool-calls
	// reference for a task. toolCallsRef is "" when the task made no tool
	// calls or none were recorded.
	SetTaskOutput(ctx context.Context, runID, taskID string,
		outputRef, errorRef, toolCallsRef string) error

	// SetTaskAttempt records the terminal state of one persisted attempt.
	// An attempt ID that is not yet present starts a new attempt rather than
	// erroring, so a re-execution (a retry, or a resumed run) records its own
	// outcome instead of overwriting the record of the execution before it.
	SetTaskAttempt(ctx context.Context, runID, taskID, attemptID, status string,
		finishedAt *time.Time) error

	// CloseRun marks a run as closed. No further state transitions are allowed.
	// Returns ErrNotFound if the run does not exist.
	// Returns ErrInvalidTransition if already closed.
	CloseRun(ctx context.Context, runID string) error

	// DeleteRun removes all data for a run. Returns ErrNotFound if not found.
	DeleteRun(ctx context.Context, runID string) error

	// ClaimRun acquires an exclusive execution claim on a run. The holder is
	// a random per-process ID - never a principal, session ID or role. Returns
	// ErrClaimHeld if another holder already holds the claim. The same holder
	// calling ClaimRun again refreshes the claim successfully.
	ClaimRun(ctx context.Context, runID, holder string) error

	// ReleaseRun releases the execution claim on a run. Only the current
	// holder may release. Returns ErrClaimNotHeld if the caller does not hold
	// the claim.
	ReleaseRun(ctx context.Context, runID, holder string) error

	// ClearRunClaim force-releases any execution claim on a run, regardless
	// of holder. Used during crash recovery to clear stale claims on runs
	// that have reached a terminal state.
	ClearRunClaim(ctx context.Context, runID string) error

	// StoreContent persists raw bytes keyed by a content-addressed reference
	// (e.g. "ref:output:xxxx"). The same ref may be stored multiple times;
	// subsequent stores are idempotent. Recorded content is never reclaimed,
	// including when the run that stored it is deleted.
	StoreContent(ctx context.Context, ref string, data []byte) error

	// LoadContent retrieves bytes previously stored by StoreContent.
	// Returns ErrContentNotFound if the ref is unknown.
	LoadContent(ctx context.Context, ref string) ([]byte, error)
}

LedgerRepository is the narrow storage boundary for the coordinator. Implementations must be concurrency-safe and return defensive copies.

type LifecycleEvent

type LifecycleEvent struct {
	ID        string // unique event identifier (idempotency key)
	RunID     string
	Sequence  uint64 // monotonic per-run
	Kind      string // e.g. "task_created", "task_completed", "run_canceled"
	TaskID    string // empty for run-level events
	AttemptID string // empty for task-level or run-level events
	// SessionID is carried when the task's session is known; it is empty for
	// run-level events and for cancel/recovery events where the task session is
	// not retained. It lets a workflow run be correlated across surfaces
	// (workflow run -> coordinator run -> bus).
	SessionID string `json:"session_id,omitempty"`
	Payload   []byte // bounded, redacted; nil for most events
	CreatedAt time.Time
}

LifecycleEvent is an append-only event for a run.

func (LifecycleEvent) Clone

func (e LifecycleEvent) Clone() LifecycleEvent

Clone returns a deep copy of the event.

type MemoryLedgerRepository

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

MemoryLedgerRepository is an in-memory implementation of LedgerRepository. It uses sync.RWMutex for concurrency safety and returns defensive copies on all read paths. It is the default backend for Phase 1 and suitable for unit and race tests.

func NewMemoryLedgerRepository

func NewMemoryLedgerRepository() *MemoryLedgerRepository

NewMemoryLedgerRepository creates a new empty in-memory ledger repository.

func (*MemoryLedgerRepository) AdmitSingleTask

func (*MemoryLedgerRepository) AppendEvent

func (m *MemoryLedgerRepository) AppendEvent(_ context.Context, event LifecycleEvent) error

func (*MemoryLedgerRepository) ClaimRun

func (m *MemoryLedgerRepository) ClaimRun(_ context.Context, runID, holder string) error

func (*MemoryLedgerRepository) ClearRunClaim

func (m *MemoryLedgerRepository) ClearRunClaim(_ context.Context, runID string) error

func (*MemoryLedgerRepository) CloseRun

func (m *MemoryLedgerRepository) CloseRun(_ context.Context, runID string) error

func (*MemoryLedgerRepository) CompareAndSetTaskStatus

func (m *MemoryLedgerRepository) CompareAndSetTaskStatus(_ context.Context, runID, taskID string, expectedVersion uint64, newStatus string) error

func (*MemoryLedgerRepository) CreateRun

func (m *MemoryLedgerRepository) CreateRun(_ context.Context, key string, snapshot RunSnapshot) error

func (*MemoryLedgerRepository) CreateTask

func (m *MemoryLedgerRepository) CreateTask(_ context.Context, snap TaskSnapshot) error

func (*MemoryLedgerRepository) DeleteRun

func (m *MemoryLedgerRepository) DeleteRun(_ context.Context, runID string) error

func (*MemoryLedgerRepository) GetRun

func (*MemoryLedgerRepository) GetRunByIdempotencyKey

func (m *MemoryLedgerRepository) GetRunByIdempotencyKey(_ context.Context, key string) (RunSnapshot, error)

func (*MemoryLedgerRepository) GetTask

func (m *MemoryLedgerRepository) GetTask(_ context.Context, runID, taskID string) (TaskSnapshot, error)

func (*MemoryLedgerRepository) ListEvents

func (m *MemoryLedgerRepository) ListEvents(_ context.Context, runID string) ([]LifecycleEvent, error)

func (*MemoryLedgerRepository) ListRuns

func (m *MemoryLedgerRepository) ListRuns(_ context.Context, status ...RunStatus) ([]RunSnapshot, error)

func (*MemoryLedgerRepository) ListTasks

func (m *MemoryLedgerRepository) ListTasks(_ context.Context, runID string) ([]TaskSnapshot, error)

func (*MemoryLedgerRepository) LoadContent

func (m *MemoryLedgerRepository) LoadContent(_ context.Context, ref string) ([]byte, error)

func (*MemoryLedgerRepository) ReleaseRun

func (m *MemoryLedgerRepository) ReleaseRun(_ context.Context, runID, holder string) error

func (*MemoryLedgerRepository) SetTaskAttempt

func (m *MemoryLedgerRepository) SetTaskAttempt(_ context.Context, runID, taskID, attemptID, status string, finishedAt *time.Time) error

func (*MemoryLedgerRepository) SetTaskOutput

func (m *MemoryLedgerRepository) SetTaskOutput(_ context.Context, runID, taskID string, outputRef, errorRef, toolCallsRef string) error

func (*MemoryLedgerRepository) SetTimeSource

func (m *MemoryLedgerRepository) SetTimeSource(now func() time.Time)

SetTimeSource replaces the clock for deterministic tests.

func (*MemoryLedgerRepository) StoreContent

func (m *MemoryLedgerRepository) StoreContent(_ context.Context, ref string, data []byte) error

type RecoveredRun

type RecoveredRun struct {
	RunID          string
	DisplayName    string
	Status         RunStatus
	WasInterrupted bool
	// CreatedAt is when the run was created, carried through so callers can tell
	// a run interrupted moments ago from one abandoned days back. Both classify
	// identically, and only the first is worth telling the user about.
	CreatedAt time.Time
}

RecoveredRun describes a run that was recovered from durable storage.

type RunID

type RunID string

RunID is a system-generated immutable identifier for one orchestration run.

type RunPolicy

type RunPolicy = ledgercore.RunPolicy

RunPolicy describes fixed recovery behaviour for one admitted run.

type RunSnapshot

type RunSnapshot struct {
	RunID              string
	DisplayName        string
	Status             RunStatus // created, queued, running, completed, failed, canceled
	RequestFingerprint string    // canonical coordinator request identity, when provided
	Tasks              []TaskSnapshot
	CreatedAt          time.Time
	CompletedAt        *time.Time
	Labels             map[string]string // caller-provided optional aliases only
	// IdempotencyKey is the caller-supplied deduplication key the run was
	// created under. It is persisted with the run_created payload so a fresh
	// repository replaying the store re-registers the key and refuses a
	// second CreateRun with it, instead of executing the same work twice.
	IdempotencyKey string    `json:"idempotency_key,omitempty"`
	Policy         RunPolicy `json:"policy"`
}

RunSnapshot is a defensive-copy snapshot of a single orchestration run.

func (RunSnapshot) Clone

func (s RunSnapshot) Clone() RunSnapshot

Clone returns a deep copy of the snapshot.

type RunStatus

type RunStatus string

RunStatus represents the lifecycle state of a run.

const (
	RunStatusCreated   RunStatus = "created"
	RunStatusQueued    RunStatus = "queued"
	RunStatusRunning   RunStatus = "running"
	RunStatusCompleted RunStatus = "completed"
	RunStatusFailed    RunStatus = "failed"
	RunStatusCanceled  RunStatus = "canceled"
)

type SingleTaskAdmission

type SingleTaskAdmission struct {
	IdempotencyKey string
	Run            RunSnapshot
	Task           TaskSnapshot
}

SingleTaskAdmission is the complete durable tuple for one child run.

type StorageLedgerRepository

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

StorageLedgerRepository wraps a storage.Store as a durable LedgerRepository. Every mutation writes an event to the append-only store AND updates an in-memory projection for fast reads.

The projection is not a one-shot build. Each operation first catches up on events appended by *other* repository instances over the same store, so two processes sharing one workspace observe each other's writes. Catch-up is incremental: a per-run applied-sequence watermark bounds the tail read to the events that arrived since this instance last looked.

func NewBorrowedStorageLedgerRepository

func NewBorrowedStorageLedgerRepository(store storage.Store) *StorageLedgerRepository

NewBorrowedStorageLedgerRepository creates a ledger projection over a caller-owned store. Closing the repository releases its claims but leaves the shared store open for the owning lifecycle coordinator.

func NewStorageLedgerRepository

func NewStorageLedgerRepository(store storage.Store) *StorageLedgerRepository

NewStorageLedgerRepository creates a StorageLedgerRepository backed by the given store. The in-memory projection is built lazily on first access and refreshed incrementally afterwards.

func (*StorageLedgerRepository) AdmitSingleTask

func (*StorageLedgerRepository) AppendEvent

func (s *StorageLedgerRepository) AppendEvent(ctx context.Context, event LifecycleEvent) error

func (*StorageLedgerRepository) CheckSpoolGrant

func (s *StorageLedgerRepository) CheckSpoolGrant(ctx context.Context, ref, principal string) (bool, error)

CheckSpoolGrant forwards a durable remainder grant lookup to the underlying store when it supports one, reporting no durable grant otherwise.

func (*StorageLedgerRepository) ClaimRun

func (s *StorageLedgerRepository) ClaimRun(ctx context.Context, runID string, holder string) error

func (*StorageLedgerRepository) ClearRunClaim

func (s *StorageLedgerRepository) ClearRunClaim(ctx context.Context, runID string) error

func (*StorageLedgerRepository) Close

func (s *StorageLedgerRepository) Close() error

Close closes the underlying store and marks the repository as closed. All claims held by this instance are released before closing the store. Subsequent method calls will return ErrClosed.

func (*StorageLedgerRepository) CloseRun

func (s *StorageLedgerRepository) CloseRun(ctx context.Context, runID string) error

CloseRun marks a run as closed. The terminal transition (status canceled, completed_at) is marshalled INTO the single run_closed event payload, so the closure and the terminal status land in ONE fenced append: a store failure cannot leave a durable closure row beside a projection that still reports the run open, and no retry or concurrent writer can commit task transitions after the durable closure (DC-4). On append failure the projection is rebuilt from the store, so reads report only what is durable. Legacy run_closed rows without the optional fields decode empty and close through closeRebuiltRun, exactly as they always did.

func (*StorageLedgerRepository) CompareAndSetTaskStatus

func (s *StorageLedgerRepository) CompareAndSetTaskStatus(ctx context.Context, runID, taskID string, expectedVersion uint64, newStatus string) error

func (*StorageLedgerRepository) CreateRun

func (s *StorageLedgerRepository) CreateRun(ctx context.Context, key string, snapshot RunSnapshot) error

func (*StorageLedgerRepository) CreateTask

func (s *StorageLedgerRepository) CreateTask(ctx context.Context, snap TaskSnapshot) error

func (*StorageLedgerRepository) DeleteRun

func (s *StorageLedgerRepository) DeleteRun(ctx context.Context, runID string) error

func (*StorageLedgerRepository) GetRun

func (*StorageLedgerRepository) GetRunByIdempotencyKey

func (s *StorageLedgerRepository) GetRunByIdempotencyKey(ctx context.Context, key string) (RunSnapshot, error)

func (*StorageLedgerRepository) GetTask

func (s *StorageLedgerRepository) GetTask(ctx context.Context, runID, taskID string) (TaskSnapshot, error)

func (*StorageLedgerRepository) GrantSpool

func (s *StorageLedgerRepository) GrantSpool(ctx context.Context, ref, principal string) error

GrantSpool forwards a durable remainder grant to the underlying store when it supports one. Stores without the surface ignore the grant, which keeps in-process-only visibility for memory-backed repositories.

func (*StorageLedgerRepository) IsRunHeld

func (s *StorageLedgerRepository) IsRunHeld(ctx context.Context, runID string) (bool, error)

IsRunHeld reports whether runID currently has an active claim. The probe is read-only: it never acquires, refreshes, or releases a claim, so observing a run can never disturb its holder. Backends that cannot expose claim state report (false, nil) instead of failing.

func (*StorageLedgerRepository) IsRunTokenFenced

func (s *StorageLedgerRepository) IsRunTokenFenced(ctx context.Context, runID, token string) (bool, error)

IsRunTokenFenced reports whether token has been fenced out of runID by a subsequent takeover. The history is durable: a fenced token stays fenced across releases, so a re-issued claim by the same token reads true until cleanup. A token that is the current holder of runID always reads false. Backends that cannot expose fence history report (false, nil).

func (*StorageLedgerRepository) ListEvents

func (s *StorageLedgerRepository) ListEvents(ctx context.Context, runID string) ([]LifecycleEvent, error)

func (*StorageLedgerRepository) ListRuns

func (s *StorageLedgerRepository) ListRuns(ctx context.Context, status ...RunStatus) ([]RunSnapshot, error)

func (*StorageLedgerRepository) ListTasks

func (s *StorageLedgerRepository) ListTasks(ctx context.Context, runID string) ([]TaskSnapshot, error)

func (*StorageLedgerRepository) LoadContent

func (s *StorageLedgerRepository) LoadContent(ctx context.Context, ref string) ([]byte, error)

func (*StorageLedgerRepository) Recover

Recover brings the projection up to date and classifies every run, reporting which ones were left non-terminal by a previous process. It deliberately mutates no run status: there is no non-terminal "interrupted" status to write, and all three terminal statuses make ResumeInterruptedRun refuse the run, so marking anything here would destroy the recoverability this report exists to advertise. Classification is therefore recomputed on every call, and a run stays reported as interrupted until it is resumed, canceled or deleted.

It also clears stale execution claims on terminal runs (the holder crashed before releasing the claim). Non-terminal runs with stale claims are NOT cleared because a live concurrent process may be executing without re-acquiring its claim on every write. Stale non-terminal claims require explicit user intervention (CLI force-release).

func (*StorageLedgerRepository) ReleaseRun

func (s *StorageLedgerRepository) ReleaseRun(ctx context.Context, runID string, holder string) error

func (*StorageLedgerRepository) SetTaskAttempt

func (s *StorageLedgerRepository) SetTaskAttempt(ctx context.Context, runID, taskID, attemptID, status string, finishedAt *time.Time) error

func (*StorageLedgerRepository) SetTaskOutput

func (s *StorageLedgerRepository) SetTaskOutput(ctx context.Context, runID, taskID string, outputRef, errorRef, toolCallsRef string) error

func (*StorageLedgerRepository) SetTimeSource

func (s *StorageLedgerRepository) SetTimeSource(now func() time.Time)

SetTimeSource replaces the clock for deterministic tests.

func (*StorageLedgerRepository) StoreContent

func (s *StorageLedgerRepository) StoreContent(ctx context.Context, ref string, data []byte) error

func (*StorageLedgerRepository) TakeoverExpiredRunClaim

func (s *StorageLedgerRepository) TakeoverExpiredRunClaim(ctx context.Context, runID, holder string, maxAge time.Duration) error

func (*StorageLedgerRepository) UnderlyingStore

func (s *StorageLedgerRepository) UnderlyingStore() storage.Store

UnderlyingStore returns the dependency injected at construction. It is a read-only identity seam for lifecycle wiring and ownership tests.

type TaskID

type TaskID string

TaskID is a system-generated immutable identifier for one DAG node within a run.

type TaskSnapshot

type TaskSnapshot struct {
	RunID        string
	TaskID       string
	ParentTaskID string // empty for root tasks
	// RawID is the model-supplied task id verbatim, before dispatch_tasks
	// namespaces it into TaskID for harness-level uniqueness (see
	// subagents.Task.RawID). Empty for any task not built through
	// dispatch_tasks.
	RawID       string `json:"raw_id,omitempty"`
	DisplayName string
	Status      string // queued, running, completed, failed, timed_out, canceled, blocked, cancel_requested
	Attempts    []AttemptSnapshot
	DependsOn   []string // TaskIDs this task depends on
	CreatedAt   time.Time
	CompletedAt *time.Time
	OutputRef   string // bounded redacted reference; empty until completion
	ErrorRef    string // bounded redacted reference; empty unless failed
	// ToolCallsRef is a bounded, redacted reference to this task's recorded
	// tool-call step trace (subagent tool name/input/output pairs). Result
	// envelopes hand it to the model as tool_calls_ref, pageable via
	// ledger_read. Empty when the task made no tool calls, or for any task
	// recorded before this field existed. Set once at task completion, on
	// the same SetTaskOutput call as OutputRef/ErrorRef.
	ToolCallsRef string `json:"tool_calls_ref,omitempty"`
	Version      uint64 // per-task monotonic version for compare-and-set
	// HandlerName is the registered handler name for the sub-agent task.
	// Stored so ResumeInterruptedRun can rebuild the task config.
	HandlerName string `json:"handler_name,omitempty"`
	// Agent routing metadata describes work, never a durable authority grant.
	// Resume must resolve this name against its current authorized registry.
	AgentName    string `json:"agent_name,omitempty"`
	AgentDigest  string `json:"agent_digest,omitempty"`
	Skill        string `json:"skill,omitempty"`
	ProviderName string `json:"provider_name,omitempty"`
	Model        string `json:"model,omitempty"`
	// Scope is a non-authority execution serialization key. It must survive resume.
	Scope string `json:"scope,omitempty"`
	// OutputSchema is part of the work request and must survive coordinator recovery.
	OutputSchema map[string]any `json:"output_schema,omitempty"`
	// InputSchema is part of the work request and must survive coordinator recovery.
	InputSchema map[string]any `json:"input_schema,omitempty"`
	// Input is the task payload, stored so a resumed task re-executes the work
	// it was given rather than an empty request.
	//
	// Only fields describing the WORK live here. Permission, scope, role,
	// session and turn are deliberately absent: the ledger is a file in the
	// workspace and the agent has file tools, so a persisted permission would be
	// a privilege grant the agent could write for itself.
	//
	// ParentTaskID above is the one identity-shaped field that IS persisted - it
	// is derived from Task.Owner (coordinator/spawn.go, via parentTaskID) and
	// records DAG parentage, which resume needs. It is deliberately NOT restored
	// into Task.Owner: doing so would make a resumed run'"'"'s dispatcher ParentID and
	// provenance attributable to a workspace-writable file.
	// TestResumeDoesNotRestoreAuthorityFields is the tripwire. See plan 12 §3.
	Input json.RawMessage `json:"input,omitempty"`
	// Timeout, Budget and Depth are resource limits: restored on resume, but
	// clamped to the live configuration so the ledger cannot raise a ceiling.
	Timeout               time.Duration      `json:"timeout,omitempty"`
	Budget                int                `json:"budget,omitempty"`
	Depth                 int                `json:"depth,omitempty"`
	WorkLimits            runtime.WorkLimits `json:"work_limits,omitempty"`
	DisableProviderReplay bool               `json:"disable_provider_replay,omitempty"`
}

TaskSnapshot is a defensive-copy snapshot of a single DAG node within a run.

func (TaskSnapshot) Clone

func (s TaskSnapshot) Clone() TaskSnapshot

Clone returns a deep copy of the snapshot.

type TaskStatus

type TaskStatus string

TaskStatus represents the lifecycle state of a task.

const (
	TaskStatusQueued          TaskStatus = "queued"
	TaskStatusRunning         TaskStatus = "running"
	TaskStatusCompleted       TaskStatus = "completed"
	TaskStatusFailed          TaskStatus = "failed"
	TaskStatusTimedOut        TaskStatus = "timed_out"
	TaskStatusCanceled        TaskStatus = "canceled"
	TaskStatusBlocked         TaskStatus = "blocked"
	TaskStatusCancelRequested TaskStatus = "cancel_requested"
	TaskStatusRetryPending    TaskStatus = "retry_pending"
	// TaskStatusAwaitingInput is non-terminal: the task is parked on a
	// question (plan 53.02). Distinct from terminal TaskStatusBlocked
	// (dependency failure; INV-AG-21). May return to running.
	TaskStatusAwaitingInput TaskStatus = "awaiting_input"
)

Jump to

Keyboard shortcuts

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