smoke

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package smoke runs end-to-end smoke tests against a reef-core instance.

This file implements the full pod lifecycle smoke test: spawn a lobster pod, observe live WebSocket events (stream, tool_call, cost), reconcile the cost against the REST budget delta, kill the pod, and confirm a terminal status.

Package smoke runs a non-TUI end-to-end smoke test against a reef-core instance. It exercises the full Phase 3 custody chain: structured_bundle → openbrain_snapshot → capture_commitment → custody.

Preconditions:

  • reef-core running on the target URL (default http://localhost:4000)
  • A valid session token (get one via: cd reef-core && mix reef_core.dev_session -q)
  • opencode on reef-core's PATH
  • ANTHROPIC_API_KEY set on reef-core's side (not konareef's)

Flow:

  1. POST /api/agents with structured memory bundle + capture-thought task
  2. Server validates session, stores bundle, emits structured_bundle proof, takes Open Brain snapshot, spawns opencode, runs LLM call, captures thought, emits capture_commitment + custody proofs
  3. Client polls GET /api/proofs?agent_id=... until a custody proof appears or the timeout hits
  4. Print chain summary + result

Index

Constants

This section is empty.

Variables

View Source
var CannedBundle = map[string]string{
	"projects/goals.md": `# Goals

Prove that konareef can spawn a pod on reef-core and receive a valid
custody proof chain back.
`,
	"projects/decisions.md": `# Decisions

- 2026-04-15: First end-to-end konareef → reef-core smoke test
- 2026-04-15: TUI spawn flow deferred; smoke is a separate subcommand
`,
	"preferences/coding-style.md": `# Coding style

- Go: tab indent, gofmt, no comments on obvious code
- Elixir: match CLAUDE.md conventions
`,
}

CannedBundle is a canned structured memory bundle for the smoke test. Three small files mimicking what an orchestrator would upload before spawning a pod.

Functions

func Run

func Run(cfg Config) error

Run executes the smoke test. Returns nil on success (custody proof observed, chain of length 3 or 4 verified), or an error on any failure.

func RunLifecycle

func RunLifecycle(cfg Config) error

RunLifecycle executes the full pod lifecycle smoke test against reef-core.

The test proceeds through ten steps:

  1. Preflight: confirm reef-core is reachable via ListAgents.
  2. Snapshot the pre-spawn budget via GetBudget.
  3. Spawn a lobster pod with cfg.Task (defaulting to a canned capture-thought task).
  4. Open a WebSocket collector, join pod:events and agent:<id>.
  5. Expect a "stream" wire event on the per-agent channel within cfg.Timeout.
  6. Expect a "tool_call" wire event within cfg.Timeout (optional; warns if absent).
  7. Expect an "agent_cost" event on pod:events within cfg.Timeout.
  8. Reconcile WS-reported cost against the REST budget delta (5% tolerance).
  9. Kill the agent via KillAgent and expect agent_exited on pod:events.
  10. Confirm the agent status is terminal via ListAgents.

cfg must have a non-empty SessionToken. cfg.Task may be empty, in which case the default capture-thought task from Default() is used.

Returns nil on success, or a descriptive wrapped error on any failure.

func TokenFromEnv

func TokenFromEnv() string

TokenFromEnv reads the session token from KONAREEF_TOKEN, allowing shells to `export KONAREEF_TOKEN=$(cd ../reef-core && mix reef_core.dev_session -q)`.

Types

type Config

type Config struct {
	BaseURL         string
	SessionToken    string
	Task            string
	Timeout         time.Duration
	PollInterval    time.Duration
	MemoryRoundtrip bool

	// PodAttestation, when non-nil, attaches publisher signing
	// metadata to the spawn request so the resulting structured_bundle
	// commitment's pod_hash / publisher_signature columns are populated.
	// The caller supplies this from `install.LoadCachedAttestation`
	// when spawning a previously installed signed pod (P0.3R).
	PodAttestation *api.PodAttestation
}

Config configures a smoke test run.

MemoryRoundtrip is opt-in (default false) because it requires a reef-core build that includes the Phase 1.5 memory subsystem (the MemoryHook teardown wiring + GET /api/memory/entries). When false, the lifecycle smoke skips the memory verification step entirely so it can still pass against older reef-core deployments.

func Default

func Default() Config

Default returns sensible defaults for an interactive smoke test.

type Event

type Event struct {
	// Topic is the Phoenix channel topic, e.g. "pod:events" or "agent:<id>".
	Topic string
	// EventType is the Phoenix event name, e.g. "agent_started", "stream", "cost".
	EventType string
	// AgentID is extracted from the topic when the topic is "agent:<id>",
	// or from payload["agent_id"] for lifecycle events on "pod:events".
	AgentID string
	// Payload is the raw parsed payload map from the Phoenix message.
	Payload map[string]any
	// ReceivedAt is the wall-clock time at which the event was buffered.
	ReceivedAt time.Time
}

Event is a single WebSocket event captured from reef-core.

type EventCollector

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

EventCollector subscribes to reef-core's Phoenix Channel WebSocket and buffers every inbound event for test assertions.

func NewEventCollector

func NewEventCollector(serverURL, token string) *EventCollector

NewEventCollector creates a collector pointed at the reef-core HTTP base URL (e.g. "http://localhost:4000"). The token is a base64-encoded reef-core session token. Does not connect; call Start to open the connection.

func (*EventCollector) All

func (collector *EventCollector) All() []Event

All returns a snapshot copy of every event received so far. Safe to call from any goroutine; the returned slice is independent of the internal buffer.

func (*EventCollector) Close

func (collector *EventCollector) Close() error

Close shuts the WebSocket connection down gracefully and cancels the read-loop and heartbeat goroutines. Idempotent — safe to call multiple times.

func (*EventCollector) Expect

func (collector *EventCollector) Expect(topic, eventType, agentID string, timeout time.Duration) (Event, error)

Expect blocks until an event matching topic, eventType, and agentID arrives, or the timeout expires. Events that arrived before Expect was called are also eligible — the collector buffers everything since Start. Pass an empty string for topic, eventType, or agentID to match any value in that field. Returns the matched Event and nil on success, or a zero Event and an error on timeout.

func (*EventCollector) JoinAgent

func (collector *EventCollector) JoinAgent(agentID string) error

JoinAgent also joins the per-agent channel "agent:<agentID>". Safe to call after Start. Returns once the join is confirmed or the context stored at Start time is cancelled.

func (*EventCollector) Start

func (collector *EventCollector) Start(ctx context.Context) error

Start opens the WebSocket connection and joins "pod:events". It blocks until the join is confirmed or the context is cancelled. Once confirmed, it spawns a background read-loop goroutine that exits when ctx is cancelled or the connection drops. Returns an error if the dial or join fails.

func (*EventCollector) SumCost

func (collector *EventCollector) SumCost() int64

SumCost returns the sum of "sats" values across every "agent_cost" event seen on the "pod:events" topic — the canonical pod-wide feed BudgetModel consumes. Use this to reconcile against REST budget deltas in lifecycle tests.

reef-core broadcasts each :agent_cost PubSub event to BOTH "pod:events" (this feed) and the per-agent "agent:<id>" topic (where it surfaces as a "cost" wire event consumed by the Inspector). Counting both feeds would double-count every spend; a single source is the right reconciliation target. The smoke test asserts both feeds independently to keep coverage of the per-agent path.

Jump to

Keyboard shortcuts

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