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
- Variables
- func ParseReference(ref string) (kind, digest string, err error)
- func RebuildProjection(events []storage.Event) (RunSnapshot, []TaskSnapshot, []LifecycleEvent, error)
- func Reference(kind string, data []byte) string
- func ValidRunTransitions(oldStatus, newStatus RunStatus) bool
- func ValidTaskTransition(oldStatus, newStatus string) bool
- type AttemptID
- type AttemptSnapshot
- type DisplayNameGenerator
- type LeaseRepository
- type LedgerRepository
- type LifecycleEvent
- type MemoryLedgerRepository
- func (m *MemoryLedgerRepository) AdmitSingleTask(_ context.Context, a SingleTaskAdmission) error
- func (m *MemoryLedgerRepository) AppendEvent(_ context.Context, event LifecycleEvent) error
- func (m *MemoryLedgerRepository) ClaimRun(_ context.Context, runID, holder string) error
- func (m *MemoryLedgerRepository) ClearRunClaim(_ context.Context, runID string) error
- func (m *MemoryLedgerRepository) CloseRun(_ context.Context, runID string) error
- func (m *MemoryLedgerRepository) CompareAndSetTaskStatus(_ context.Context, runID, taskID string, expectedVersion uint64, ...) error
- func (m *MemoryLedgerRepository) CreateRun(_ context.Context, key string, snapshot RunSnapshot) error
- func (m *MemoryLedgerRepository) CreateTask(_ context.Context, snap TaskSnapshot) error
- func (m *MemoryLedgerRepository) DeleteRun(_ context.Context, runID string) error
- func (m *MemoryLedgerRepository) GetRun(_ context.Context, runID string) (RunSnapshot, error)
- func (m *MemoryLedgerRepository) GetRunByIdempotencyKey(_ context.Context, key string) (RunSnapshot, error)
- func (m *MemoryLedgerRepository) GetTask(_ context.Context, runID, taskID string) (TaskSnapshot, error)
- func (m *MemoryLedgerRepository) ListEvents(_ context.Context, runID string) ([]LifecycleEvent, error)
- func (m *MemoryLedgerRepository) ListRuns(_ context.Context, status ...RunStatus) ([]RunSnapshot, error)
- func (m *MemoryLedgerRepository) ListTasks(_ context.Context, runID string) ([]TaskSnapshot, error)
- func (m *MemoryLedgerRepository) LoadContent(_ context.Context, ref string) ([]byte, error)
- func (m *MemoryLedgerRepository) ReleaseRun(_ context.Context, runID, holder string) error
- func (m *MemoryLedgerRepository) SetTaskAttempt(_ context.Context, runID, taskID, attemptID, status string, ...) error
- func (m *MemoryLedgerRepository) SetTaskOutput(_ context.Context, runID, taskID string, ...) error
- func (m *MemoryLedgerRepository) SetTimeSource(now func() time.Time)
- func (m *MemoryLedgerRepository) StoreContent(_ context.Context, ref string, data []byte) error
- type RecoveredRun
- type RunID
- type RunPolicy
- type RunSnapshot
- type RunStatus
- type SingleTaskAdmission
- type StorageLedgerRepository
- func (s *StorageLedgerRepository) AdmitSingleTask(ctx context.Context, a SingleTaskAdmission) error
- func (s *StorageLedgerRepository) AppendEvent(ctx context.Context, event LifecycleEvent) error
- func (s *StorageLedgerRepository) CheckSpoolGrant(ctx context.Context, ref, principal string) (bool, error)
- func (s *StorageLedgerRepository) ClaimRun(ctx context.Context, runID string, holder string) error
- func (s *StorageLedgerRepository) ClearRunClaim(ctx context.Context, runID string) error
- func (s *StorageLedgerRepository) Close() error
- func (s *StorageLedgerRepository) CloseRun(ctx context.Context, runID string) error
- func (s *StorageLedgerRepository) CompareAndSetTaskStatus(ctx context.Context, runID, taskID string, expectedVersion uint64, ...) error
- func (s *StorageLedgerRepository) CreateRun(ctx context.Context, key string, snapshot RunSnapshot) error
- func (s *StorageLedgerRepository) CreateTask(ctx context.Context, snap TaskSnapshot) error
- func (s *StorageLedgerRepository) DeleteRun(ctx context.Context, runID string) error
- func (s *StorageLedgerRepository) GetRun(ctx context.Context, runID string) (RunSnapshot, error)
- func (s *StorageLedgerRepository) GetRunByIdempotencyKey(ctx context.Context, key string) (RunSnapshot, error)
- func (s *StorageLedgerRepository) GetTask(ctx context.Context, runID, taskID string) (TaskSnapshot, error)
- func (s *StorageLedgerRepository) GrantSpool(ctx context.Context, ref, principal string) error
- func (s *StorageLedgerRepository) IsRunHeld(ctx context.Context, runID string) (bool, error)
- func (s *StorageLedgerRepository) IsRunTokenFenced(ctx context.Context, runID, token string) (bool, error)
- func (s *StorageLedgerRepository) ListEvents(ctx context.Context, runID string) ([]LifecycleEvent, error)
- func (s *StorageLedgerRepository) ListRuns(ctx context.Context, status ...RunStatus) ([]RunSnapshot, error)
- func (s *StorageLedgerRepository) ListTasks(ctx context.Context, runID string) ([]TaskSnapshot, error)
- func (s *StorageLedgerRepository) LoadContent(ctx context.Context, ref string) ([]byte, error)
- func (s *StorageLedgerRepository) Recover(ctx context.Context) ([]RecoveredRun, error)
- func (s *StorageLedgerRepository) ReleaseRun(ctx context.Context, runID string, holder string) error
- func (s *StorageLedgerRepository) SetTaskAttempt(ctx context.Context, runID, taskID, attemptID, status string, ...) error
- func (s *StorageLedgerRepository) SetTaskOutput(ctx context.Context, runID, taskID string, ...) error
- func (s *StorageLedgerRepository) SetTimeSource(now func() time.Time)
- func (s *StorageLedgerRepository) StoreContent(ctx context.Context, ref string, data []byte) error
- func (s *StorageLedgerRepository) TakeoverExpiredRunClaim(ctx context.Context, runID, holder string, maxAge time.Duration) error
- func (s *StorageLedgerRepository) UnderlyingStore() storage.Store
- type TaskID
- type TaskSnapshot
- type TaskStatus
Constants ¶
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 ¶
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.
var ErrMalformedReference = sdkadapter.ErrMalformedReference
ErrMalformedReference reports a reference that is not in canonical form.
Functions ¶
func ParseReference ¶
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 ¶
Reference returns the canonical reference for data: "ref:<kind>:<64 hex>". It returns "" for empty data or an unrecognised kind.
func ValidRunTransitions ¶
ValidRunTransitions returns true if the transition from oldStatus to newStatus is valid for a run.
func ValidTaskTransition ¶
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 (m *MemoryLedgerRepository) AdmitSingleTask(_ context.Context, a SingleTaskAdmission) error
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 (*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 (m *MemoryLedgerRepository) GetRun(_ context.Context, runID string) (RunSnapshot, error)
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 (*MemoryLedgerRepository) ReleaseRun ¶
func (m *MemoryLedgerRepository) ReleaseRun(_ context.Context, runID, holder string) error
func (*MemoryLedgerRepository) SetTaskAttempt ¶
func (*MemoryLedgerRepository) SetTaskOutput ¶
func (*MemoryLedgerRepository) SetTimeSource ¶
func (m *MemoryLedgerRepository) SetTimeSource(now func() time.Time)
SetTimeSource replaces the clock for deterministic tests.
func (*MemoryLedgerRepository) StoreContent ¶
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 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 (s *StorageLedgerRepository) AdmitSingleTask(ctx context.Context, a SingleTaskAdmission) error
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) 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 (*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 (s *StorageLedgerRepository) GetRun(ctx context.Context, runID string) (RunSnapshot, error)
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 ¶
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 (*StorageLedgerRepository) Recover ¶
func (s *StorageLedgerRepository) Recover(ctx context.Context) ([]RecoveredRun, error)
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 (*StorageLedgerRepository) SetTaskAttempt ¶
func (*StorageLedgerRepository) SetTaskOutput ¶
func (*StorageLedgerRepository) SetTimeSource ¶
func (s *StorageLedgerRepository) SetTimeSource(now func() time.Time)
SetTimeSource replaces the clock for deterministic tests.
func (*StorageLedgerRepository) StoreContent ¶
func (*StorageLedgerRepository) TakeoverExpiredRunClaim ¶
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),
// operator-facing only. 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" )
Source Files
¶
- displayname.go
- memory.go
- memory_admission.go
- memory_claims.go
- reference.go
- repository.go
- single_admission.go
- storage.go
- storage_admission.go
- storage_claims.go
- storage_event_id.go
- storage_grants.go
- storage_owner.go
- storage_projection.go
- storage_queries.go
- storage_recovery.go
- storage_schema.go
- storage_sequences.go
- transition.go
- types.go