Help us shape the future of Go! Take the 2026 Go Developer Survey

trace

package module
v0.18.0 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2026 License: MIT Imports: 17 Imported by: 0

README

goatherd-kernel

Go implementation of the Shepherd trace kernel: a content-addressed, append-only, causally-linked execution trace store over SQLite, the real-time effect bus, and the read-only trace UI. It implements shepherd.kernel.abi.v0 — the same frozen ABI as the Python reference (shepherd2) — and produces byte-identical digests from the same golden test vectors.

Module scope. This module is the kernel: the record model, canonical JSON, the SQLite store, the effect bus, and the execution/history projections. The trace package is the module root — import "github.com/buchenberg/goatherd-kernel" is package trace — with traceui (the read-only HTTP projection) and testkit (shared test support) as subpackages.

The runtime layer — the scope tree, merge gate, settlement and recovery, the sandbox backends, the substrate/materialize layer, the task runtime, and the supervision rules engine — lives in github.com/buchenberg/shepherd-runtime-go, which composes this module. See that README for branching, workspace capture/restore, supervision, and task execution.

What It Is

The kernel records agent actions as durable, inspectable traces. Every tool call, every file mutation, every agent decision becomes a record in a causal DAG with content-addressed identity.

Branching, workspace capture/restore, and supervision are built on top of the store by the runtime module, not here.

Install

go get github.com/buchenberg/goatherd-kernel

What You Can Do With It

Record agent execution traces

Every tool call, every model response, every file mutation becomes a durable, content-addressed record in a causal DAG:

store, _ := trace.NewSQLiteTraceStore("trace.sqlite")
ctx := context.Background()
defer store.Close(context.Background())

// Record a tool call intent
receipt, _ := store.Append(ctx, trace.TrustedAppendContext, trace.AppendBatch{
    AppendIntentID: "session:tool:1",
    Groups: []trace.AppendGroup{{
        TraceOwnerID: "agent:main",
        FactDrafts: []trace.RecordDraft{{
            Mode:      trace.Declaration,
            SchemaRef: "app.tool.bash.v1",
            Payload:   map[string]any{"cmd": "go test ./..."},
        }},
    }},
})

// Record the outcome
store.Append(ctx, trace.TrustedAppendContext, trace.AppendBatch{
    AppendIntentID: "session:result:1",
    Groups: []trace.AppendGroup{{
        TraceOwnerID:  "agent:main",
        CausalParents: receipt.FactIDs,
        FactDrafts: []trace.RecordDraft{{
            Mode:      trace.Capture,
            SchemaRef: "app.tool.bash.v1.applied",
            Payload:   map[string]any{"success": true, "duration": "2.3s"},
        }},
    }},
})
Observe agent actions in real time

Subscribe to the effect bus to receive events as they happen — no polling, no SQLite reads:

bus := trace.NewEffectBus(64)
store.WithBus(bus)

ch := bus.Subscribe("my-watcher")

// Events arrive as records are appended
event := <-ch
fmt.Println(event.KindLabel)  // "bash"
fmt.Println(event.Payload)    // map[cmd:go test ./...]
Inspect execution history

Read back traces by owner, causal closure, or frontier checkpoint:

// Everything an agent did
slice, _ := store.ReadOwnerPrefix(ctx, trace.TrustedReadContext, "agent:main", 999, trace.ModeBoth)

// Causal closure from a specific record
slice, _ = store.ReadCausalClosure(ctx, trace.TrustedReadContext, []string{"sha256:abc"}, trace.ModeBoth, "include_external_anchors")

// Point-in-time checkpoint
frontier, _ := store.PublishFrontier(ctx, trace.TrustedAppendContext, trace.FrontierSpec{...})
checkpoint, _ := store.ResolveFrontier(ctx, trace.TrustedReadContext, frontier.FrontierID, trace.ModeBoth)

Trace UI service

The traceui package serves a read-only HTTP projection of a trace store — the server half of the trace visualizer; the browser client lives in its own repository and consumes this contract:

store, _ := trace.NewSQLiteTraceStore("trace.sqlite")
bus := trace.NewEffectBus(64)
store.WithBus(bus)
svc, _ := traceui.New(traceui.Config{Store: store, Bus: bus})
http.Handle("/", svc.Handler()) // mount anywhere; embeds in the writer for live events
Endpoint Behavior
GET /api/health liveness, bus presence, fact count
GET /api/records?path=&through=&mode= records under an owner path subtree — the path and its :-delimited descendants (empty spans all owners) — with payloads and causal edges; a record retained on several paths appears once per path with that path's own owner and ordinal. through is an inclusive per-owner ordinal cutoff; mode filter optional. Arrays are never null
GET /api/events server-sent events, one effect per appended record — requires the bus (embedded mode); without one it answers 503 and the client polls /api/records

Records carry id, digest, schema, mode, kind, owner, per-owner ordinal, context and witness refs, causal parents, and — under the trusted read the service performs — the retained payload. Witness records appear on their own kernel:witness owner path. The bus is non-blocking: a stalled client drops events and repairs by re-reading /api/records; the content-addressed ids make the merge trivial.

cmd/traceui is a standalone read-only viewer for an existing trace file (traceui -db trace.sqlite -addr 127.0.0.1:8321) — no bus, so clients poll. It opens the database read-only (trace.OpenSQLiteTraceStoreReadOnly): no journal-mode pragma, no schema creation, and the existing schema is verified, so a wrong path fails loudly instead of serving an empty or modified trace.

Architecture

The kernel is small and acyclic:

trace  (module root)        the record model, canonical JSON, the SQLite store,
                            the effect bus, the projections
  ├── traceui               the read-only HTTP projection
  └── testkit               shared test support (vector schema + golden provenance)
Package Contents
trace (module root) the record model, canonical JSON, the SQLite trace store, the effect bus, execution/history/relation projections, the checkpoint-blob and materialization-ledger plumbing
traceui the read-only HTTP projection of a trace store
testkit test support shared with the runtime module — the execution-vector schema and the golden-provenance tests

The runtime packages — the root shepherd hub (scope tree, merge gate, settlement, recovery), sandbox/sandbox/git, substrate, materialize, task, and supervisor — live in github.com/buchenberg/shepherd-runtime-go.

Core Concepts

Records

Every trace entry is a record with content-addressed identity — record_id == SHA-256(canonical_input). Two records with identical content produce the same ID.

Records have a mode:

  • declaration — an intention (what the agent proposed)
  • capture — an observation (what actually happened)
Witnesses

Records cite a witness that describes the authority and environment under which they were accepted. Witnesses chain to a deterministic root witness (genesis record).

Causal Edges

Records declare their causal parents via caused_by. Parent order is part of record identity. This creates a DAG of provenance.

Frontiers

A frontier is an immutable bookmark pointing to a specific record on a specific owner path. Enables point-in-time reads and undo.

Slices

A slice is a graph-shaped read result — the selected records, their causal edges, witness support, and anchors for out-of-scope evidence.

Effect Bus

A transient pub/sub layer that fans out EffectEvent messages to subscribers. Non-blocking — slow subscribers get their oldest event dropped, never block the writer.

Workspace State

A WorkspaceState is a backend-neutral snapshot of a workspace — the replacement for the git-specific stash/HEAD pair:

type WorkspaceState struct {
    Backend  string         // "git", "containerd"
    Revision string         // git HEAD SHA, or a snapshot key
    Data     map[string]any // backend-specific, opaque to the kernel
}

Digest() returns the kernel canonical digest of the state (sha256:…), used in trace records and for drift detection. Two states with identical content digest identically regardless of map iteration order, because canonicalization sorts keys at every level.

Unlike a Checkpoint, a WorkspaceState has no lifecycle: it is reusable and stays valid, so one fork point can seed many speculative branches. (The Sandbox interface that produces and consumes workspace states — and the Checkpoint type — live in the runtime module.)

API

Store
store, err := trace.NewSQLiteTraceStore(path)  // ":memory:" for in-memory
defer store.Close(context.Background())
store.WithBus(bus)  // optional: attach effect bus

receipt, err := store.Append(ctx, trace.TrustedAppendContext, batch)  // Append records
slice, err := store.ReadOwnerPrefix(ctx, trace.TrustedReadContext, owner, through, modeFilter)
slice, err := store.ReadCausalClosure(ctx, trace.TrustedReadContext, roots, modeFilter, closurePolicy)
frontier, err := store.PublishFrontier(ctx, trace.TrustedAppendContext, spec)  // Immutable checkpoint
slice, err := store.ResolveFrontier(ctx, trace.TrustedReadContext, frontierId, modeFilter)
ids, err := store.PreviewRecordIDs(ctx, trace.TrustedAppendContext, batch)  // Dry-run append

// Read-only open (the viewer's opener): never writes, never creates schema.
ro, err := trace.OpenSQLiteTraceStoreReadOnly(path)

Every store call takes a Go context.Context first — cancellation and deadlines reach the SQL layer — with the trace-authority context (TrustedAppendContext / TrustedReadContext) second.

Effect Bus
bus := trace.NewEffectBus(bufferSize)  // 0 = default (64)
defer bus.Close()

ch := bus.Subscribe("watcher-id")     // <-chan EffectEvent
bus.Unsubscribe("watcher-id")
bus.Publish(event)                     // non-blocking
Constants
trace.Capture                    // "capture"
trace.Declaration                // "declaration"
trace.ModeBoth                   // "both"
trace.ModeCapturesOnly           // "captures_only"
trace.ModeDeclarationsOnly       // "declarations_only"
trace.TrustedAppendContext       // Default trusted append context
trace.TrustedReadContext         // Default trusted read context

trace.ABIVersion                 // "shepherd.kernel.abi.v0"
trace.CanonicalVersion           // "shepherd.kernel.canonical.v2"

trace.SchemaExecutionCreated     // "shepherd2.execution.created.v1"
trace.SchemaExecutionStarted     // "shepherd2.execution.started.v1"
trace.SchemaExecutionCompleted   // "shepherd2.execution.completed.v1"
trace.SchemaExecutionFailed      // "shepherd2.execution.failed.v1"
trace.SchemaExecutionRelation    // "shepherd2.execution_relation.created.v1"

The shepherd.* scope/checkpoint/workspace/supervisor schema constants and sandbox.ErrNoSandbox / sandbox.ErrUnsupported live in the runtime module.

Executions

Executions give runs identities: a create/start/complete/fail lifecycle folded from retained facts, with parent/child relations and an effective-history projection. Every id is derived exactly as the Python reference derives it — ExecutionIDFor and the full run sequence are pinned by Python-generated vectors — so a Go-written trace is readable by shepherd2 and vice versa.

history, err := trace.ProjectEffectiveHistoryFromStore(ctx, store, reader, cutoff)
// root execution + active children (spawned/adopted; abandoned drops) + published facts

Spawns and adopts are recorded as parent-owned relation facts; abandoning a child writes an abandoned relation under the same relation id, so the effective-history fold drops it. The whole tree projects from one terminal frontier, and re-opening the store file re-projects it identically.

The synchronous task facade over these projections — task.NewRegistry, StartTask/StartTaskSync, and TaskControl — lives in the runtime module.

Golden Vectors

The testdata/kernel_abi_v0.json file contains deterministic test vectors shared across implementations. If your digest of the root witness body matches sha256:28aa527e..., your implementation is compatible. testkit/golden_provenance_test.go pins the SHA-256 of every vector file in this module.

Tests

go test ./...          # the full suite
go test -race ./...    # the suite under the race detector
go vet ./...

The kernel suite covers the golden vectors (hash-pinned against the Python reference), the store ABI (append idempotency, conflicts, witness chains, frontier/cut resolution, authorization), and the execution/history projections. CI runs it on Linux, macOS, and Windows with the race detector on, plus a golden-drift check against the pinned Python reference.

The scopes, checkpoints, merge gate, settlement, supervision, sandbox, and restart-recovery suites live with those packages in the runtime module.

Dependencies

  • modernc.org/sqlite — pure Go SQLite driver (no CGo). The kernel has exactly one direct dependency.
  • Go 1.21+

License

MIT — see LICENSE, matching the upstream Python reference.

Documentation

Overview

Package trace is the kernel's record core: the append-only, content- addressed trace model, canonical JSON encoding, the SQLite trace store, the effect bus, and the execution/history/relation projections read from it. It is the leaf of the component graph - every other package builds on this vocabulary, and nothing here imports another shepherd package.

The record digests, canonical JSON flavour, and schema names are frozen ABI surface shared with the Python reference implementation; the fixture vectors in testdata pin them.

Index

Constants

View Source
const (
	CanonicalVersion     = "shepherd.kernel.canonical.v2"
	ABIVersion           = "shepherd.kernel.abi.v0"
	RootWitnessSchemaRef = "kernel.witness.root.v1"
	WitnessSchemaRef     = "kernel.witness.v1"
	RootWitnessRef       = ""
)
View Source
const (
	SchemaExecutionCreated   = "shepherd2.execution.created.v1"   // declaration
	SchemaExecutionStarted   = "shepherd2.execution.started.v1"   // capture
	SchemaExecutionCompleted = "shepherd2.execution.completed.v1" // capture
	SchemaExecutionFailed    = "shepherd2.execution.failed.v1"    // capture
)
View Source
const DefaultCheckpointBlobLimit = 1 << 20

DefaultCheckpointBlobLimit is the default per-checkpoint snapshot cap: 1 MiB, generous for serialized conversation history, small enough that a long session cannot balloon the trace database unnoticed.

View Source
const SchemaExecutionRelation = "shepherd2.execution_relation.created.v1"
View Source
const SchemaRuntimePublishedFact = "shepherd2.runtime.published_fact.v1"

Variables

View Source
var ErrProjectionMode = errors.New("goatherd: projection mode incompatible")

ErrProjectionMode reports a slice whose mode filter contradicts a projection's declared requirement. Python raises ProjectionModeError (a ValueError subclass); Go has no error hierarchy here, so the sentinel is matched with errors.Is.

View Source
var ErrUnknownFrontier = errors.New("unknown frontier")

ErrUnknownFrontier is the expected "no retained cutoff for this frontier id" condition, distinguished from real read faults so callers can retry it deliberately instead of spinning on every error.

View Source
var ExecutionProjection = ProjectionSpec{
	Name:            "shepherd2.execution.project",
	ModeRequirement: ProjectionRequiresBoth,
	RequiresPayload: true,
	AcceptsAnchors:  true,
}

ExecutionProjection is the projection spec every ProjectExecution entry point enforces. Python's is mode_requirement="both".

View Source
var ExecutionRelationProjection = ProjectionSpec{
	Name:            "shepherd2.execution_relation.project",
	ModeRequirement: ProjectionRequiresBoth,
	RequiresPayload: true,
	AcceptsAnchors:  true,
}

ExecutionRelationProjection is the spec ProjectExecutionRelations enforces.

View Source
var ExecutionRelationSchemaLibrary = &StaticSchemaLibrary{
	LibraryName: "shepherd2.execution_relation",
	Refs:        []string{SchemaExecutionRelation},
	Specs:       []ProjectionSpec{ExecutionRelationProjection},
}

ExecutionRelationSchemaLibrary describes the relation schema ring.

View Source
var ExecutionSchemaLibrary = &StaticSchemaLibrary{
	LibraryName: "shepherd2.execution",
	Refs: []string{
		SchemaExecutionCreated,
		SchemaExecutionStarted,
		SchemaExecutionCompleted,
		SchemaExecutionFailed,
	},
	Specs: []ProjectionSpec{ExecutionProjection},
}

ExecutionSchemaLibrary describes the execution schema ring.

View Source
var TrustedAppendContext = AppendContext{
	ActorRef:             "runtime:internal",
	PresentedWitnessRefs: []string{"trusted:internal"},
	SchemaVersionSet:     "shepherd2-slice-a",
	TrustMode:            "internal",
}

TrustedAppendContext is the default trusted append context for internal operations.

View Source
var TrustedReadContext = ReadContext{
	ActorRef:             "runtime:internal",
	PresentedWitnessRefs: []string{"trusted:internal"},
	VisibilityProfile:    VisibilityPayload,
}

TrustedReadContext is the default trusted read context for internal operations.

Functions

func CanonicalDigest

func CanonicalDigest(v any) (string, error)

CanonicalDigest returns the kernel digest for a canonical input payload.

It is byte-identical to Python's canonical_digest: sha256(CANONICAL_PREFIX + canonical_json_bytes(value)), rendered as "sha256:<hex>".

func CanonicalJSONASCIIBytes

func CanonicalJSONASCIIBytes(v any) ([]byte, error)

CanonicalJSONASCIIBytes encodes with CPython's json.dumps *default* (ensure_ascii=True), which is a different escaping flavour from the one the record digest uses.

The store needs both, and that is not an artefact of the Go port: shepherd2's trace_store.py runs two encoders in the same append path. Record and witness ids go through kernel.canonical.canonical_json_bytes (ensure_ascii=False), while its `_json_dumps` helper omits the argument, so the context id, the batch digest and the stored body/receipt JSON all use ensure_ascii=True. With an ASCII-only payload the two agree, which is why this is invisible in the existing tests.

func CanonicalJSONBytes

func CanonicalJSONBytes(v any) ([]byte, error)

CanonicalJSONBytes returns byte-stable canonical JSON for digest input: keys sorted at every level, compact separators, raw UTF-8, and CPython's number and string formatting.

It is byte-identical to Python's

json.dumps(value, sort_keys=True, separators=(",", ":"),
           ensure_ascii=False, allow_nan=False).encode("utf-8")

which is what `canonical_json_bytes` does in shepherd2. That identity is the point: digests over these bytes are compared across implementations.

Two things Go's encoding/json gets wrong here, both of which produce a different digest silently rather than failing:

  • it escapes <, > and & as \u003c, \u003e, \u0026, which CPython emits raw, so any payload with a shell `&&` or a `<placeholder>` diverges;
  • it has no float formatting that matches CPython's repr.

Hence the hand-written writer below. Do not simplify it back to json.Marshal.

One contract this imposes on callers: a payload decoded from JSON must be decoded with json.Decoder.UseNumber() (or into json.Number fields). Go's default interface{} decoding turns every number into float64, which erases Python's int/float distinction — JSON `1` and `1.0` are the same float64 but canonicalise to "1" and "1.0". The previous implementation papered over that by rendering integral float64s without a decimal point, which happened to fix integers and silently corrupted real float values.

func CanonicalRecordInput

func CanonicalRecordInput(schemaRef string, mode RecordMode, body map[string]any, causedBy []string, witness string) (map[string]any, error)

CanonicalRecordInput builds the canonical payload for one retained record.

func CanonicalWitnessInput

func CanonicalWitnessInput(schemaRef string, body map[string]any) (map[string]any, error)

CanonicalWitnessInput builds the canonical payload for one witness.

func CheckpointBlobLimitOrDefault

func CheckpointBlobLimitOrDefault(store *SQLiteTraceStore) int64

CheckpointBlobLimitOrDefault resolves the store's effective checkpoint blob limit, defaulting to DefaultCheckpointBlobLimit.

func CopyMap

func CopyMap(m map[string]any) map[string]any

func DeleteCheckpointBlob

func DeleteCheckpointBlob(gctx context.Context, store *SQLiteTraceStore, checkpointID string) error

DeleteCheckpointBlob removes a persisted checkpoint. Restore deletes its blob on success: a restored checkpoint is single-use and must not be offered as restorable again by a later recovery.

func DeleteMaterializationIntent

func DeleteMaterializationIntent(gctx context.Context, store *SQLiteTraceStore, intentID string) error

DeleteMaterializationIntent removes a completed-materialization ledger row. It exists so tests can simulate the crash window between the capture append and the ledger write; internal/ keeps it invisible outside the module.

func EnsureProjectionCompatible

func EnsureProjectionCompatible(slice Slice, spec ProjectionSpec) error

EnsureProjectionCompatible validates that a slice satisfies a projection's declared kernel requirements: a payload-requiring projection rejects a shape_only slice — which would otherwise fold an empty owner path into a plausible pending execution — and a mode disagreement wraps ErrProjectionMode. AcceptsAnchors is descriptive today (the folds' own payload-visible checks enforce it in practice); it is carried for parity with Python's ProjectionSpec.

func ExecutionIDFor

func ExecutionIDFor(appendIntentID, localRef string) string

ExecutionIDFor derives a stable execution id for an append-local execution reference: "exec:" + sha256("<appendIntentID>\0<localRef>")[:32].

The plan sketch showed an error return; the derivation has no failure mode (it hashes two strings), so the Go signature drops it deliberately.

func NonNilAnchors

func NonNilAnchors(anchors []map[string]any) []map[string]any

NonNilAnchors returns an empty (non-nil) slice for nil input, so a receipt without anchors serializes as [] rather than null, matching Python's tuple.

func NonNilMap

func NonNilMap(m map[string]any) map[string]any

NonNilMap normalizes a nil map to an empty one: the canonical writer renders a nil map as JSON null and an empty map as {}, and the reference always carries dicts — so a nil here would silently change the record digest, and therefore the record id, for the same logical run.

func NonNilStrings

func NonNilStrings(ss []string) []string

NonNilStrings returns an empty (non-nil) slice for nil input.

The canonical writer emits null for a nil slice and [] for an empty one, and Python serialises an empty tuple as []. Without this a Go zero value would canonicalise differently from the Python it is supposed to match.

func PersistCheckpointBlob

func PersistCheckpointBlob(gctx context.Context, store *SQLiteTraceStore, checkpointID, scopeID string, seq uint64, ws WorkspaceState, snapshot []byte, createdAt time.Time) error

PersistCheckpointBlob stores a checkpoint's restorable halves. It is the hard-fail half of durability: a checkpoint that cannot be persisted must not be handed out as restorable.

func RecordCompletedMaterialization

func RecordCompletedMaterialization(store *SQLiteTraceStore, intentID, digest string, receipt MaterializationReceipt) error

RecordCompletedMaterialization writes the ledger entry — the idempotency commit point. The insert races only with a concurrent completion of the same intent; INSERT OR IGNORE plus a digest comparison decides replays the same way Python's IntegrityError branch does, without matching driver error strings.

func RecordDigest

func RecordDigest(schemaRef string, mode RecordMode, body map[string]any, causedBy []string, witness string) (string, error)

RecordDigest returns the kernel record id for one retained record.

func RelationIDFor

func RelationIDFor(appendIntentID, localRef string) string

RelationIDFor derives a stable relation id: "rel:" + sha256("<appendIntentID>\0<localRef>")[:32]. Same shape as ExecutionIDFor — pinned by testdata/execution_vectors_v0.json.

func RootWitnessBody

func RootWitnessBody() map[string]any

RootWitnessBody returns the fixed root witness body.

func RootWitnessBodyDigest

func RootWitnessBodyDigest() (string, error)

RootWitnessBodyDigest returns the deterministic root witness-body digest.

func RootWitnessRecordID

func RootWitnessRecordID() (string, error)

RootWitnessRecordID returns the deterministic retained root witness record id.

func RootWitnessRecordIDMust

func RootWitnessRecordIDMust() string

RootWitnessRecordIDMust returns the root witness record id, panicking on error. Safe because the root witness is deterministic and always valid.

func ValidateMode

func ValidateMode(mode RecordMode) error

ValidateMode checks that a mode is valid.

func ValidateRootWitnessRecord

func ValidateRootWitnessRecord(schemaRef string, mode RecordMode, body map[string]any, causedBy []string, witness string) error

ValidateRootWitnessRecord validates the root witness record constraints.

func ValidateSchemaRef

func ValidateSchemaRef(schemaRef string) error

ValidateSchemaRef checks that a schema ref is non-empty.

func ValidateWitnessBody

func ValidateWitnessBody(schemaRef string, body map[string]any) error

ValidateWitnessBody validates the witness body shape.

func ValidateWitnessRef

func ValidateWitnessRef(witness string) error

ValidateWitnessRef checks that a witness ref is valid.

func WitnessBodyDigest

func WitnessBodyDigest(schemaRef string, body map[string]any) (string, error)

WitnessBodyDigest returns a digest for canonical witness-body input. Kernel records cite retained witness record ids, not this body digest.

Types

type AppendBatch

type AppendBatch struct {
	AppendIntentID string
	Groups         []AppendGroup
}

AppendBatch is an atomic semantic append attempt.

func CompleteExecutionBatch

func CompleteExecutionBatch(appendIntentID, executionID string, outputs map[string]any, causedBy []string) AppendBatch

CompleteExecutionBatch builds the canonical terminal-success append.

func CreateExecutionBatch

func CreateExecutionBatch(appendIntentID, executionID, taskRef string, inputs map[string]any, parentExecutionID string, causedBy []string) AppendBatch

CreateExecutionBatch builds the canonical creation/start append for one execution: a single group on the execution's own owner path, drafts in created-then-started order.

func CreateExecutionRelationBatch

func CreateExecutionRelationBatch(appendIntentID, relationID string, kind RelationKind, parentExecutionID, childExecutionID, childFrontierID string, causedBy []string) AppendBatch

CreateExecutionRelationBatch builds the canonical parent-owned relation append: the group's owner path is the PARENT's execution id.

func FailExecutionBatch

func FailExecutionBatch(appendIntentID, executionID, errMsg string, causedBy []string) AppendBatch

FailExecutionBatch builds the canonical terminal-failure append.

type AppendContext

type AppendContext struct {
	ActorRef             string
	PresentedWitnessRefs []string
	SchemaVersionSet     string
	TrustMode            string
}

AppendContext is a compatibility write context for append operations.

func (AppendContext) ToOperationContext

func (c AppendContext) ToOperationContext(op OperationKind) OperationContext

type AppendGroup

type AppendGroup struct {
	TraceOwnerID    string
	RetainedContext *RetainedContext
	CausalParents   []string
	FactDrafts      []RecordDraft
}

AppendGroup is an owner-local group inside one semantic append transition.

type AppendIntentConflictError

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

AppendIntentConflictError is raised when an append intent is retried with a different batch.

func NewAppendIntentConflictError

func NewAppendIntentConflictError(msg string) *AppendIntentConflictError

NewAppendIntentConflictError constructs an AppendIntentConflictError. Exported for the runtime layer.

func (*AppendIntentConflictError) Error

func (e *AppendIntentConflictError) Error() string

type AppendReceipt

type AppendReceipt struct {
	AppendIntentID  string
	FactIDs         []string
	CommitReceipts  []string
	OwnerRanges     map[string][2]int
	CausalEdges     [][2]string
	ContextReceipts []string
}

AppendReceipt is the storage and trace identity allocated by a successful append.

type Containment

type Containment string

Containment describes the sandbox containment level of a witness.

const (
	ContainFull        Containment = "full"
	ContainContained   Containment = "contained"
	ContainBuffered    Containment = "buffered"
	ContainUncontained Containment = "uncontained"
)

type ContextAnchor

type ContextAnchor struct {
	ContextID    string
	VisibleShape map[string]any
	HiddenReason string
}

ContextAnchor is a visible reference to a retained context hidden by visibility.

type EffectBus

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

EffectBus fans out EffectEvents to subscribers. It is a transient pub/sub layer — not a persistence mechanism. The trace store is the durable record; the bus is for real-time observation.

Publish is non-blocking: if a subscriber's buffer is full, the oldest event is dropped. This prevents a slow supervisor from blocking the sub-agent it's watching. A supervisor that can't keep up can always read the full trace from the store after the fact.

func NewEffectBus

func NewEffectBus(bufferSize int) *EffectBus

NewEffectBus creates a new effect bus with the given per-subscriber buffer size. If bufferSize <= 0, the default (64) is used.

func (*EffectBus) Close

func (b *EffectBus) Close()

Close shuts down the bus and closes all subscriber channels.

func (*EffectBus) Publish

func (b *EffectBus) Publish(event EffectEvent)

Publish sends an event to all subscribers. It never blocks — if a subscriber's buffer is full, the oldest event is dropped.

Ordering: Events from a single publisher arrive in order per subscriber. Events from concurrent publishers may interleave — there is no global ordering guarantee across goroutines. The trace store publishes events after each committed append, so events from a single store are ordered by append order.

func (*EffectBus) Subscribe

func (b *EffectBus) Subscribe(id string) <-chan EffectEvent

Subscribe creates a new subscription with the given ID and returns a receive-only channel. If a subscription with this ID already exists, the old one is closed and replaced.

func (*EffectBus) SubscriberCount

func (b *EffectBus) SubscriberCount() int

SubscriberCount returns the number of active subscribers.

func (*EffectBus) Unsubscribe

func (b *EffectBus) Unsubscribe(id string)

Unsubscribe removes a subscription and closes its channel.

type EffectEvent

type EffectEvent struct {
	// RecordID is the content-addressed ID of the retained record.
	RecordID string
	// IntentID is the append intent ID (idempotency key).
	IntentID string
	// TraceOwnerID identifies the sub-agent session (e.g., "sub:abc").
	TraceOwnerID string
	// Mode distinguishes intent (Declaration) from observation (Capture).
	Mode RecordMode
	// SchemaRef identifies the effect type (e.g., "yaah.tool.bash.v1").
	SchemaRef string
	// KindLabel is the human-readable label (e.g., "bash", "turn:started").
	KindLabel string
	// Payload carries the effect data. For declarations this is typically
	// tool args; for captures it's the result metadata.
	Payload map[string]any
	// CausalParents links to preceding records in the causal graph.
	CausalParents []string
	// Timestamp is when the event was emitted (wall clock, not trace time).
	Timestamp time.Time
}

EffectEvent is a real-time notification emitted when a trace record is appended. It is NOT a retained record — it's a transient bus message that carries just enough context for live supervision.

The trace store is the durable record; the event bus is ephemeral. Supervisors subscribe to the bus for real-time observation, and read from the store for historical analysis.

type EffectiveChild

type EffectiveChild struct {
	Relation  ExecutionRelation
	Execution Execution
}

EffectiveChild is one active child in a parent's effective history: the relation that links it plus its projected execution.

type EffectiveHistory

type EffectiveHistory struct {
	Root           Execution
	Relations      []ExecutionRelation
	Children       []EffectiveChild
	PublishedFacts []PublishedFact
}

EffectiveHistory is the projected effective history for one execution owner prefix. Relations carries every projected relation; Children only the active ones, matching Python.

func ProjectEffectiveHistory

func ProjectEffectiveHistory(rootSlice Slice, rootTraceOwnerID string, childSlices []Slice) (*EffectiveHistory, error)

ProjectEffectiveHistory projects the root execution, its active children and its parent-published facts from trace slices. Child slices are matched to relations by frontier id: a relation without a child frontier, or one whose frontier has no slice, is skipped.

func ProjectEffectiveHistoryFromStore

func ProjectEffectiveHistoryFromStore(ctx context.Context, store *SQLiteTraceStore, readContext ReadContext, cutoff Frontier) (*EffectiveHistory, error)

ProjectEffectiveHistoryFromStore resolves the root frontier and each active child's frontier, then projects.

type Execution

type Execution struct {
	ExecutionID       string
	TaskRef           string
	ParentExecutionID string
	Status            ExecutionStatus
	Inputs            map[string]any
	Outputs           map[string]any
	Error             string
	StartedFactID     string
	TerminalFactID    string
	Cutoff            Frontier
}

Execution is the projected execution value derived from retained trace facts. Python models parent_execution_id, error and the cutoff as Optionals; Go uses "" for the absent scalar fields, and Cutoff is always present — synthesized from the slice when no frontier backs it, exactly as Python's _cutoff_from_slice does.

func ProjectExecution

func ProjectExecution(traceSlice Slice, targetTraceOwnerID string, cutoff *Frontier) (*Execution, error)

ProjectExecution projects an execution from a payload-visible trace slice, folding the owner path in order: created → started → terminal. Facts whose payload execution_id is absent or the target are folded; anything else on the path is skipped. The last terminal fact wins, matching Python.

func ProjectExecutionFromStore

func ProjectExecutionFromStore(ctx context.Context, store *SQLiteTraceStore, readContext ReadContext, cutoff Frontier) (*Execution, error)

ProjectExecutionFromStore resolves a frontier and projects an execution.

type ExecutionRelation

type ExecutionRelation struct {
	RelationID        string
	RelationKind      RelationKind
	ParentExecutionID string
	ChildExecutionID  string
	ChildFrontierID   string
	CreatedFactID     string
}

ExecutionRelation is the projected parent-owned relation between two executions. ChildFrontierID is "" when the relation carries no child frontier (Python's None).

func ExecutionRelationFromFact

func ExecutionRelationFromFact(fact Record) (ExecutionRelation, error)

ExecutionRelationFromFact projects one relation-created fact.

func ProjectExecutionRelations

func ProjectExecutionRelations(traceSlice Slice, parentTraceOwnerID string) ([]ExecutionRelation, error)

ProjectExecutionRelations projects parent-owned relations from a payload-visible slice, in owner-path order. Facts carrying another parent's relation are skipped — relations are addressed by the owner path they live on.

func ProjectExecutionRelationsFromStore

func ProjectExecutionRelationsFromStore(ctx context.Context, store *SQLiteTraceStore, readContext ReadContext, cutoff Frontier) ([]ExecutionRelation, error)

ProjectExecutionRelationsFromStore resolves a frontier and projects the parent-owned relations it covers.

type ExecutionStatus

type ExecutionStatus string

ExecutionStatus is the projected lifecycle state of an execution.

const (
	ExecutionPending   ExecutionStatus = "pending"
	ExecutionRunning   ExecutionStatus = "running"
	ExecutionSucceeded ExecutionStatus = "succeeded"
	ExecutionFailed    ExecutionStatus = "failed"
)

type ExternalAnchor

type ExternalAnchor struct {
	Ref          string
	AnchorKind   string
	VisibleShape map[string]any
	HiddenReason string
}

ExternalAnchor is a visible reference to a fact outside a slice or hidden by visibility.

type Frontier

type Frontier struct {
	FrontierID          string
	TargetTraceOwnerID  string
	ThroughFactID       string
	ThroughOwnerOrdinal int
	PublisherOwnerID    string
	CreatedByFactID     string
}

Frontier is an immutable read address over retained path entries.

func PublishExecutionFrontier

func PublishExecutionFrontier(ctx context.Context, store *SQLiteTraceStore, auth AppendContext, frontierID, targetExecutionID, throughFactID, publisherExecutionID, appendIntentID string, causedBy []string) (Frontier, error)

PublishExecutionFrontier publishes an execution-schema terminal frontier over the Ring 0 frontier ABI. The terminal-frontier law is enforced here: the through-fact must be payload-visible and must carry a completed or failed schema; anything else fails before the frontier exists.

type FrontierSpec

type FrontierSpec struct {
	FrontierID         string
	TargetTraceOwnerID string
	ThroughFactID      string
	PublisherOwnerID   string
	AppendIntentID     string
	CausedBy           []string
}

FrontierSpec is the append input for publishing a frontier.

type MaterializationOutcome

type MaterializationOutcome string

MaterializationOutcome is the result vocabulary a substrate reports.

const (
	// MaterializationSuccess means every declaration was applied and every
	// intended capture is present in the result.
	MaterializationSuccess MaterializationOutcome = "success"
	// MaterializationCleanFailure means nothing was applied and the failure
	// reason explains why. No captures are emitted — a substrate claiming
	// clean_failure while emitting capture drafts is rejected by dispatch,
	// because the two claims contradict each other. A substrate may only
	// claim clean_failure when it did not attempt a world-side mutation:
	// a failure after a mutation was attempted is split_state, because the
	// world may have changed without a capture.
	MaterializationCleanFailure MaterializationOutcome = "clean_failure"
	// MaterializationSplitState means the batch did not apply cleanly: the
	// captures and anchors describe only the records that verifiably
	// landed, and the world-side state of the failed record(s) is uncertain
	// — the failure reason names them.
	MaterializationSplitState MaterializationOutcome = "split_state"
)

type MaterializationReceipt

type MaterializationReceipt struct {
	Outcome           MaterializationOutcome
	SubstrateRef      string
	TargetRecordIDs   []string
	ProducedRecordIDs []string
	FailureReason     string
	WorldSideAnchors  []map[string]any
}

MaterializationReceipt is the kernel materialize transition receipt handed back to the caller and stored in the completed-intent ledger. Its field set mirrors Python's MaterializationReceipt exactly, because the ledger's receipt_json is serialized from it and must stay cross-readable.

func ReadCompletedMaterialization

func ReadCompletedMaterialization(store *SQLiteTraceStore, intentID string) (string, MaterializationReceipt, bool, error)

ReadCompletedMaterialization looks up the ledger for a materialize intent. The store lock is held only around the query, mirroring Python's _read_completed_intent; no lock is held across the substrate call or the capture append in the orchestrator.

type MaterializationResult

type MaterializationResult struct {
	Outcome          MaterializationOutcome
	CaptureDrafts    []RecordDraft
	FailureReason    string
	WorldSideAnchors []map[string]any
}

MaterializationResult is the substrate-produced result before the kernel appends captures. Substrates never append themselves: dispatch owns the append (the materialize orchestrator), which keeps substrates testable without a store.

type ModeFilter

type ModeFilter string

ModeFilter controls which record modes appear in a slice.

const (
	ModeBoth             ModeFilter = "both"
	ModeDeclarationsOnly ModeFilter = "declarations_only"
	ModeCapturesOnly     ModeFilter = "captures_only"
)

type OperationContext

type OperationContext struct {
	ActorRef               string
	Operation              OperationKind
	PresentedAuthorityRefs []string
	SchemaEnvironmentRef   string
	VisibilityProfile      VisibilityProfile
	TrustMode              string
}

OperationContext is the trace-facing operation context for kernel operations.

Operation records which operation the context was built for. Since plan 03, the materialization dispatch consults it: ensureMaterializeAuthorized requires OpMaterialize and rejects anything else. The append/read helpers still set it themselves and their authorization checks still do not consult it, so outside Materialize it remains descriptive.

type OperationKind

type OperationKind string

OperationKind identifies the type of kernel operation for authorization.

const (
	OpAppend     OperationKind = "append"
	OpRead       OperationKind = "read"
	OpPublishCut OperationKind = "publish_cut"

	// OpMaterialize is the operation kind the substrate materialization
	// dispatch requires (plan 03): Materialize accepts an OperationContext
	// and rejects any context whose Operation is not this kind. The
	// append/read entry points still derive their own operation kinds, so
	// the only way to present this one is through Materialize itself.
	OpMaterialize OperationKind = "materialize"

	// OpObserve is reserved for a future operation and remains unreachable:
	// no exported entry point presents it.
	OpObserve OperationKind = "observe"
)

type ProjectionModeRequirement

type ProjectionModeRequirement string

ProjectionModeRequirement is what a projection needs a slice's mode filter to be. "any" accepts everything.

const (
	ProjectionRequiresDeclarations ProjectionModeRequirement = "declarations_only"
	ProjectionRequiresCaptures     ProjectionModeRequirement = "captures_only"
	ProjectionRequiresBoth         ProjectionModeRequirement = "both"
	ProjectionAcceptsAny           ProjectionModeRequirement = "any"
)

type ProjectionSpec

type ProjectionSpec struct {
	Name            string
	ModeRequirement ProjectionModeRequirement
	RequiresPayload bool
	AcceptsAnchors  bool
}

ProjectionSpec declares one pure projection's kernel requirements.

type PublishedFact

type PublishedFact struct {
	FactID string
	Kind   string
	Data   map[string]any
}

PublishedFact is a parent-published fact visible in effective history.

type ReadContext

type ReadContext struct {
	ActorRef             string
	PresentedWitnessRefs []string
	VisibilityProfile    VisibilityProfile
}

ReadContext is a compatibility read context for read operations.

func (ReadContext) ToOperationContext

func (c ReadContext) ToOperationContext() OperationContext

type Record

type Record struct {
	Envelope RecordEnvelope
	Body     RecordBody
	View     *RecordView
}

Record is one retained record: envelope plus body plus optional view.

func (Record) GetEnvelope

func (r Record) GetEnvelope() RecordEnvelope

func (Record) GetView

func (r Record) GetView() *RecordView

type RecordBody

type RecordBody struct {
	Payload map[string]any
}

RecordBody holds the retained schema-specific payload.

type RecordDraft

type RecordDraft struct {
	Mode              RecordMode
	SchemaRef         string
	Payload           map[string]any
	KindLabel         string
	AppendLocalID     string
	CausedByFactIDs   []string
	CausedByLocalRefs []string
}

RecordDraft is an append input. Drafts are not retained records.

func ExecutionCompletedDraft

func ExecutionCompletedDraft(executionID string, outputs map[string]any) RecordDraft

ExecutionCompletedDraft builds the terminal-success lifecycle fact.

func ExecutionCreatedDraft

func ExecutionCreatedDraft(executionID, taskRef string, inputs map[string]any, parentExecutionID string) RecordDraft

ExecutionCreatedDraft builds the execution entity fact (declaration). The created fact is the ID anchor: created carries task_ref, inputs and the parent link. An absent parent is JSON null, never "".

func ExecutionFailedDraft

func ExecutionFailedDraft(executionID, errMsg string) RecordDraft

ExecutionFailedDraft builds the terminal-failure lifecycle fact.

func ExecutionStartedDraft

func ExecutionStartedDraft(executionID string) RecordDraft

ExecutionStartedDraft builds the execution-started lifecycle fact (capture).

type RecordEnvelope

type RecordEnvelope struct {
	RecordID    string
	Digest      string
	SchemaRef   string
	Mode        RecordMode
	WitnessRef  string
	CausedByIDs []string
}

RecordEnvelope holds stable semantic identity and causality for one record.

type RecordMode

type RecordMode string

RecordMode distinguishes observed facts from stated intentions.

const (
	Capture     RecordMode = "capture"
	Declaration RecordMode = "declaration"
)

type RecordShape

type RecordShape struct {
	Envelope     RecordEnvelope
	View         *RecordView
	HiddenReason string
}

RecordShape is a visibility-filtered record without retained payload.

func (RecordShape) GetEnvelope

func (r RecordShape) GetEnvelope() RecordEnvelope

func (RecordShape) GetView

func (r RecordShape) GetView() *RecordView

type RecordView

type RecordView struct {
	TraceOwnerID string
	OwnerOrdinal int
	ContextRef   string
	KindLabel    string
}

RecordView holds path/read-view metadata outside semantic record identity.

type RecoveredCheckpointBlob

type RecoveredCheckpointBlob struct {
	CheckpointID string
	ScopeID      string
	Seq          uint64
	State        WorkspaceState
	Snapshot     []byte
	CreatedAt    time.Time
}

RecoveredCheckpointBlob is one persisted checkpoint row as recovery receives it.

func LoadCheckpointBlobs

func LoadCheckpointBlobs(gctx context.Context, store *SQLiteTraceStore) ([]RecoveredCheckpointBlob, []string, error)

LoadCheckpointBlobs returns every persisted checkpoint, oldest first by creation time. Rows whose state JSON cannot be decoded are skipped with their IDs collected — a corrupt row must not fail recovery of the rest.

type RelationKind

type RelationKind string

RelationKind describes what a parent did with a child execution.

const (
	RelationSpawned   RelationKind = "spawned"
	RelationAdopted   RelationKind = "adopted"
	RelationAbandoned RelationKind = "abandoned"
)

type RetainedContext

type RetainedContext struct {
	ContextID               string
	ActiveBindingRefs       []string
	CapabilityWitnessRefs   []string
	SemanticEnvironmentRefs []string
	VisibilityPolicyRefs    []string
	SubstrateRef            string
	Containment             Containment
}

RetainedContext is a durable semantic context stamped into retained fact envelopes.

type SQLiteTraceStore

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

SQLiteTraceStore is the canonical TraceStore implementation backed by SQLite.

func NewSQLiteTraceStore

func NewSQLiteTraceStore(path string) (*SQLiteTraceStore, error)

NewSQLiteTraceStore creates a new trace store at the given path. Use ":memory:" for an in-memory store.

func OpenSQLiteTraceStoreReadOnly

func OpenSQLiteTraceStoreReadOnly(path string) (*SQLiteTraceStore, error)

OpenSQLiteTraceStoreReadOnly opens an existing trace database for reading only. It is the viewer's opener: unlike NewSQLiteTraceStore it never writes — no journal-mode pragma runs and no schema is created — so a missing, empty, or non-trace file fails loudly instead of materializing a valid-looking empty trace. The database must already hold the full trace schema, which is validated without DDL.

The path names a file, never ":memory:". Paths containing SQLite URI metacharacters ('?', '#') are percent-encoded, as the URI filename form requires.

func (*SQLiteTraceStore) Append

Append appends a semantic batch or returns the prior receipt for its intent.

func (*SQLiteTraceStore) Close

func (s *SQLiteTraceStore) Close(ctx context.Context) error

Close closes the underlying database connection.

func (*SQLiteTraceStore) ContextCount

func (s *SQLiteTraceStore) ContextCount(ctx context.Context) (int, error)

ContextCount returns the retained context count for diagnostics.

func (*SQLiteTraceStore) FactCount

func (s *SQLiteTraceStore) FactCount(ctx context.Context) (int, error)

FactCount returns the retained fact count for diagnostics.

func (*SQLiteTraceStore) PreviewRecordIDs

func (s *SQLiteTraceStore) PreviewRecordIDs(ctx context.Context, auth AppendContext, batch AppendBatch) ([]string, error)

PreviewRecordIDs returns the durable record IDs this batch would allocate if committed.

func (*SQLiteTraceStore) PublishCut

func (s *SQLiteTraceStore) PublishCut(ctx context.Context, auth AppendContext, spec FrontierSpec) (Frontier, error)

PublishCut is an alias for PublishFrontier.

func (*SQLiteTraceStore) PublishFrontier

func (s *SQLiteTraceStore) PublishFrontier(ctx context.Context, auth AppendContext, spec FrontierSpec) (Frontier, error)

PublishFrontier publishes a retained owner-prefix frontier through the append path.

func (*SQLiteTraceStore) ReadCausalClosure

func (s *SQLiteTraceStore) ReadCausalClosure(ctx context.Context, auth ReadContext, roots []string, modeFilter ModeFilter, closurePolicy string) (Slice, error)

ReadCausalClosure reads the causal closure for one or more root facts.

func (*SQLiteTraceStore) ReadFact

func (s *SQLiteTraceStore) ReadFact(ctx context.Context, auth ReadContext, factID string) (VisibleRecord, error)

ReadFact reads one retained fact.

func (*SQLiteTraceStore) ReadOwnerCutoff

func (s *SQLiteTraceStore) ReadOwnerCutoff(ctx context.Context, frontierID string) (Frontier, error)

ReadOwnerCutoff reads a published frontier by ID.

func (*SQLiteTraceStore) ReadOwnerPrefix

func (s *SQLiteTraceStore) ReadOwnerPrefix(ctx context.Context, auth ReadContext, ownerID string, through int, modeFilter ModeFilter) (Slice, error)

ReadOwnerPrefix reads all facts on an owner path up to and including the given ordinal.

func (*SQLiteTraceStore) ReadPathPrefix

func (s *SQLiteTraceStore) ReadPathPrefix(ctx context.Context, auth ReadContext, pathRef string, through int, modeFilter ModeFilter) (Slice, error)

ReadPathPrefix is the TraceStore protocol's path-addressed prefix read.

In shepherd2 this is a pure alias for read_owner_prefix — the protocol declares it (facts.py:443) but the reference implementation's body is `return self.read_owner_prefix(read_context, trace_owner_id, through, mode_filter)`. It takes a trace owner id, not a free-form path, and applies no different addressing, so this delegates rather than reimplementing the query.

It exists for protocol completeness: a caller written against the Python protocol can call either name and get the same slice.

func (*SQLiteTraceStore) ResolveCut

func (s *SQLiteTraceStore) ResolveCut(ctx context.Context, auth ReadContext, cutID string, modeFilter ModeFilter) (Slice, error)

ResolveCut is an alias for ResolveFrontier.

func (*SQLiteTraceStore) ResolveFrontier

func (s *SQLiteTraceStore) ResolveFrontier(ctx context.Context, auth ReadContext, frontierID string, modeFilter ModeFilter) (Slice, error)

ResolveFrontier resolves a frontier into a graph-shaped trace slice.

func (*SQLiteTraceStore) WithBus

func (s *SQLiteTraceStore) WithBus(bus *EffectBus) *SQLiteTraceStore

WithBus attaches an effect bus to the store. When set, every successful Append publishes an EffectEvent for each retained record. This enables real-time supervision without modifying the store's persistence behavior.

The bus is optional — existing code that doesn't set a bus sees no change.

func (*SQLiteTraceStore) WithCheckpointBlobLimit

func (s *SQLiteTraceStore) WithCheckpointBlobLimit(limit int64) *SQLiteTraceStore

WithCheckpointBlobLimit bounds the opaque snapshot bytes persisted per checkpoint. A checkpoint whose snapshot exceeds the limit fails loudly at creation — the host externalizes large state instead of silently growing the trace database. Zero restores the default.

type ScannedRecord

type ScannedRecord struct {
	RecordID  string
	OwnerID   string
	SchemaRef string
	Payload   map[string]any
}

ScannedRecord is one record selected by schema ref, with the owner path it was read from and its decoded payload. Recovery is the caller: the lifecycle, checkpoint, and settlement schemas are open-map payloads, so records are the durable registry a restart rebuilds from.

func ScanRecordsBySchema

func ScanRecordsBySchema(gctx context.Context, store *SQLiteTraceStore, schemaRefs ...string) ([]ScannedRecord, error)

ScanRecordsBySchema returns every retained record whose schema_ref is one of the given refs, each with its owner path (path_ref) and payload. A record retained on multiple paths appears once per path; lifecycle records are single-path by construction.

It is a package function, deliberately not a method on SQLiteTraceStore: the root package re-exports the store type, and a method would surface this no-ReadContext scan in the public API. As an internal/ package function it stays invisible to importers outside the module.

type SchemaLibrary

type SchemaLibrary interface {
	Name() string
	SchemaRefs() []string
	ProjectionSpecs() []ProjectionSpec
}

SchemaLibrary is the minimal contract for schema-defined records and projections.

type Slice

type Slice struct {
	Frontier          *Frontier
	VisibilityProfile VisibilityProfile
	ModeFilter        ModeFilter
	FactsByID         map[string]VisibleRecord
	ContextsByID      map[string]RetainedContext
	OwnerPaths        map[string][]string
	// OwnerPathOrder lists the owner paths in the order they were first
	// encountered while reading. FactIDs uses it so the flattened order is
	// deterministic and matches Python, where owner_paths is a dict and
	// TraceSlice.fact_ids() therefore flattens in insertion order. Without it,
	// FactIDs would iterate Go's map and return a different order every call.
	OwnerPathOrder  []string
	CausalEdges     [][2]string
	ExternalAnchors []ExternalAnchor
	ContextAnchors  []ContextAnchor
	WitnessesByID   map[string]VisibleRecord
	WitnessAnchors  []WitnessAnchor
}

Slice is a graph-shaped read result over retained trace facts.

func (Slice) FactIDs

func (s Slice) FactIDs() []string

FactIDs returns all fact IDs across all owner paths in the slice.

Paths are visited in the order they were first encountered while reading, matching Python's TraceSlice.fact_ids(), which flattens the insertion-ordered owner_paths dict. The fallback sorts rather than ranging over the map: a hand-built Slice should still produce a stable order, and ranging over a Go map does not.

type StaticSchemaLibrary

type StaticSchemaLibrary struct {
	LibraryName string
	Refs        []string
	Specs       []ProjectionSpec
}

StaticSchemaLibrary is a simple immutable schema-library descriptor.

func ShepherdSchemas

func ShepherdSchemas() *StaticSchemaLibrary

ShepherdSchemas is the default schema library. It registers the execution and relation rings WITH their projection specs, plus the runtime-published-fact ref as a known schema — the reference defines no ProjectionSpec for published facts (they are folded by the history projection, which carries the specs), so none is claimed here either. Plan 04's settlement projections will extend this library, not replace it.

func (*StaticSchemaLibrary) Name

func (l *StaticSchemaLibrary) Name() string

func (*StaticSchemaLibrary) ProjectionSpecs

func (l *StaticSchemaLibrary) ProjectionSpecs() []ProjectionSpec

func (*StaticSchemaLibrary) SchemaRefs

func (l *StaticSchemaLibrary) SchemaRefs() []string

type TraceStoreError

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

TraceStoreError is the base error for trace store law violations.

func NewTraceStoreError

func NewTraceStoreError(msg string) *TraceStoreError

NewTraceStoreError constructs a TraceStoreError with the given message. Exported for the runtime layer, which raises store-shaped errors from outside this package.

func (*TraceStoreError) Error

func (e *TraceStoreError) Error() string

type UnknownFactError

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

UnknownFactError is raised when a retained fact references a missing fact.

func (*UnknownFactError) Error

func (e *UnknownFactError) Error() string

type VisibilityProfile

type VisibilityProfile string

VisibilityProfile controls what record content is exposed in a slice.

const (
	VisibilityShapeOnly    VisibilityProfile = "shape_only"
	VisibilityPayload      VisibilityProfile = "payload"
	VisibilityFullInternal VisibilityProfile = "full_internal"
)

type VisibleRecord

type VisibleRecord interface {
	GetEnvelope() RecordEnvelope
	GetView() *RecordView
	// contains filtered or unexported methods
}

VisibleRecord is either a full Record or a RecordShape.

type WitnessAnchor

type WitnessAnchor struct {
	WitnessRef   string
	VisibleShape map[string]any
	HiddenReason string
}

WitnessAnchor is a visible reference to a witness record hidden by visibility.

type WitnessBody

type WitnessBody struct {
	ActorRef                string
	AuthorityRefs           []string
	ActiveBindingRefs       []string
	SemanticEnvironmentRefs []string
	VisibilityPolicyRefs    []string
	ProvenancePolicyRefs    []string
	SubstrateRef            string
	Containment             Containment
}

WitnessBody describes the authority and environment under which records were accepted.

type WorkspaceState

type WorkspaceState struct {
	// Backend identifies the backend that produced the state ("git",
	// "containerd", ...). Apply rejects a state from a different backend.
	Backend string
	// Revision is an optional backend timeline position: the git HEAD SHA for
	// the git backend, a snapshot key for a snapshot-backed backend.
	Revision string
	// Data carries the backend-specific payload.
	Data map[string]any
}

WorkspaceState is the backend-neutral description of a sandbox workspace: the state Capture produces and Apply consumes. It lives in the trace component because it is trace-recordable data — its Digest exists for trace records and drift detection — and both the sandbox and the runtime layer consume it through the public aliases.

func (WorkspaceState) Digest

func (ws WorkspaceState) Digest() (string, error)

Digest returns the kernel canonical digest of the state, for trace records and drift detection. It is deterministic: CanonicalDigest sorts keys at every nesting level, so two states with the same content digest identically regardless of map iteration order.

It returns an error only if Data contains a value that cannot be canonically marshaled. Callers recording a trace treat a digest failure as advisory.

Directories

Path Synopsis
cmd
traceui command
Command traceui is a standalone read-only viewer for a shepherd trace database: it serves the traceui package's HTTP API over an existing trace file, for pointing a browser client at a session after (or during) a run.
Command traceui is a standalone read-only viewer for a shepherd trace database: it serves the traceui package's HTTP API over an existing trace file, for pointing a browser client at a session after (or during) a run.
Package testkit holds the shared schema of the Python-generated execution vector fixtures.
Package testkit holds the shared schema of the Python-generated execution vector fixtures.
Package traceui serves a read-only HTTP projection of a trace store: the appended records as JSON, and - when an effect bus is attached - a live server-sent-events stream of the same events the Supervisor observes.
Package traceui serves a read-only HTTP projection of a trace store: the appended records as JSON, and - when an effect bus is attached - a live server-sent-events stream of the same events the Supervisor observes.

Jump to

Keyboard shortcuts

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