probes

package
v1.4.11 Latest Latest
Warning

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

Go to latest
Published: May 22, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package probes provides instrumented dependency wrappers and operation contracts for SDK integration tests.

The package addresses a class of bug that PromptKit's existing test suite could not detect: stages whose element flow is correct (1 in → 1 out) but whose external side effects (Load, Save, render, emit) multiply with input cardinality. Without explicit operation counters, "did X happen" tests pass while "did X happen exactly N times" remains unenforced.

Contracts declare per-Send operation budgets ("renderer.RenderDetailed must execute exactly once per Send, regardless of history depth"). Probes capture the actual count. Tests run a fixture matrix that varies the dimensions which drive multiplication and assert contracts hold across all of them.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AutoSummarizeOpts

type AutoSummarizeOpts struct {
	Threshold int
	BatchSize int
}

AutoSummarizeOpts configures probed auto-summarization.

type Bound

type Bound struct {
	Min int
	Max int
}

Bound describes the acceptable count range for an operation per Send. A Max of -1 means unbounded.

func AtLeast

func AtLeast(n int) Bound

AtLeast returns a Bound that requires at least n occurrences (no upper bound).

func AtMost

func AtMost(n int) Bound

AtMost returns a Bound that requires at most n occurrences.

func Exactly

func Exactly(n int) Bound

Exactly returns a Bound that requires exactly n occurrences.

func Range

func Range(lo, hi int) Bound

Range returns a Bound that requires lo <= count <= hi.

func (Bound) Contains

func (b Bound) Contains(n int) bool

Contains reports whether n satisfies the bound.

func (Bound) String

func (b Bound) String() string

String returns a human-readable description of the Bound.

type Op

type Op string

Op is the name of a counted operation, e.g. "store.Load" or "events.template.rendered".

type Ops

type Ops map[Op]Bound

Ops maps an operation name to its expected per-Send bound.

type PipelineInvariants

type PipelineInvariants struct {
	// Label is a free-form name used in failure messages.
	Label string
	// PerSend lists pipeline-wide operations whose count is Send-scoped.
	PerSend Ops
}

PipelineInvariants declares per-Send budgets that hold across the entire pipeline (cross-stage), not for any single stage.

func (PipelineInvariants) AssertHolds

func (p PipelineInvariants) AssertHolds(t *testing.T, snap Snapshot)

AssertHolds checks that the snapshot satisfies every clause.

type Probes

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

Probes captures observed operation counts for a single Send window.

Probes is wired into the SDK via Run: store calls are counted via a wrapping statestore.Store; events are counted via a SubscribeAll listener on the bus. Renderer / tool / provider counts are derived from existing event types rather than wrapping each interface — the lifecycle events on the bus are already authoritative for "this operation happened once."

For tests that need to inspect event payloads (e.g. assert tokens entering the provider stay within budget), the full event records are retained and exposed via Events(eventType).

A separately-counted Provider wrapper is exposed via SummarizerProvider for auto-summarize tests, since the LLMSummarizer calls Predict on its provider directly without going through the pipeline's ProviderStage (so no provider.call.* events fire for summarization).

Counters are reset by ResetCounters; Run calls it after sdk.Open completes so that init-time Loads/Saves do not appear in Send-scoped snapshots.

func Run

func Run(tb testing.TB, ro RunOptions) (*Probes, *sdk.Conversation)

Run wires probes around a fresh sdk.Conversation and returns both. Counters are reset before Run returns, so the caller observes only post-Open traffic.

Cleanup (closing the conv and the bus) is registered with tb.Cleanup.

Accepts testing.TB so both *testing.T (unit / integration tests) and *testing.B (benchmarks) can use the helper.

RunOptions is intentionally passed by value: tests benefit from the inline struct-literal call site (Run(t, RunOptions{SeedHistory: 5})), and the per-call cost of an 80-byte copy is negligible against the work Run does.

func (*Probes) Bus

func (p *Probes) Bus() *events.EventBus

Bus returns the event bus the probes are listening on. Tests can use it for additional subscriptions, but should not close it — Run wires cleanup.

func (*Probes) Events

func (p *Probes) Events(et events.EventType) []*events.Event

Events returns a snapshot of all collected events of the given type, in the order they were observed. Useful for inspecting payload data — for example, asserting that tokens entering the provider stay within budget.

func (*Probes) ResetCounters

func (p *Probes) ResetCounters()

ResetCounters zeroes every counter. Run calls this after sdk.Open so that initialisation traffic does not leak into per-Send observations.

func (*Probes) Snapshot

func (p *Probes) Snapshot() Snapshot

Snapshot captures the current counter state.

func (*Probes) SummarizerProvider

func (p *Probes) SummarizerProvider() providers.Provider

SummarizerProvider returns a counted Provider wrapper suitable to pass as the auto-summarize provider via sdk.WithAutoSummarize. Predict calls on this provider are counted under op "summarizer.Predict".

func (*Probes) WaitForCount

func (p *Probes) WaitForCount(op Op, atLeast int, timeout time.Duration) bool

WaitForCount blocks until the count for op reaches at least atLeast or the timeout expires. Returns true if the threshold was met, false on timeout.

Counts grow monotonically inside a single observation window (we do not emit anti-events), so a successful WaitForCount guarantees the snapshot holds at least the requested count. Callers asserting an *exact* count should pair WaitForCount with a brief settle period and an Equal check to catch overshoot.

type RunOptions

type RunOptions struct {
	// PackJSON is the pack definition. If empty, a minimal default is used.
	PackJSON string
	// PromptName selects the prompt within the pack. Defaults to "chat".
	PromptName string
	// ConversationID is passed to sdk.WithConversationID. Defaults to
	// "probes-conv".
	ConversationID string
	// SeedHistory pre-populates the conversation with N prior messages
	// (alternating user/assistant). Used to exercise stages whose work
	// scales with conversation length.
	SeedHistory int
	// SDKOptions are appended after the probe-default options. Caller-supplied
	// options can override defaults (for example, providing a non-mock
	// provider or a different state store), but doing so will defeat the
	// corresponding probe.
	SDKOptions []sdk.Option
	// AutoSummarize, when non-nil, wires sdk.WithAutoSummarize using the
	// probes' counted summarizer provider, so summarizer.Predict shows up
	// in Snapshot.Count.
	AutoSummarize *AutoSummarizeOpts
}

RunOptions configures a probed conversation.

Zero values give a sensible default: a fresh in-memory store, the minimal pack, the "chat" prompt, a deterministic conversation ID, and a mock provider. Tests override only what they need.

type Snapshot

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

Snapshot is an immutable point-in-time view of probe counters.

Operation names follow the convention "<dependency>.<method>" for direct wraps (e.g. "store.Load") and "events.<event_type>" for events (e.g. "events.prompt.template.rendered").

func (Snapshot) All

func (s Snapshot) All() map[Op]int

All returns a copy of the underlying counts map. Mostly useful for debugging — assertions should use Count.

func (Snapshot) Count

func (s Snapshot) Count(op Op) int

Count returns the count for op, or 0 if op was never seen.

type StageContract

type StageContract struct {
	// Stage is a free-form label used in failure messages.
	Stage string
	// PerSend lists operations whose count is expected to be Send-scoped.
	PerSend Ops
}

StageContract declares the per-Send operation budget for a single stage. Used by tests as a first-class fixture: assert that a stage performs each declared operation within bounds across a matrix of inputs.

func (StageContract) AssertHolds

func (c StageContract) AssertHolds(t *testing.T, snap Snapshot)

AssertHolds checks that the snapshot satisfies every clause of the contract. Each violation produces a separate t.Errorf so all failures surface at once.

Jump to

Keyboard shortcuts

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