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

runview

package
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package runview is a read-only, local web viewer for one run's journal: a plan flow's declared topology with the run's path drawn over it, or an agent run's timeline of model turns, tool calls, attempts, approvals and halts, with the audit verdict when a signed head or evidence package is given. It never writes to the store it reads, and it serves on a loopback address only (see Listen). The bide-view command (cmd/bide-view, its own module) is its front end.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Handler

func Handler(o Options) http.Handler

Handler serves the run list at / and a run at /run?id=<run> (its View as JSON at /run.json?id=<run>). It answers only GET and HEAD, and only requests addressed to a loopback host, so a page on another site cannot read it through a rebound DNS name.

func Listen

func Listen(addr string) (net.Listener, error)

Listen listens on addr, which must name a loopback IP (127.0.0.1 or ::1) or "localhost" (listened on as 127.0.0.1). Any other host, an empty one included, is refused: the viewer shows a journal's contents and must not be reachable from another machine.

func Main

func Main(args []string, stdout, stderr io.Writer, stores Stores) int

Main is the bide-view command: it parses args, opens the input, and serves until interrupted. It returns the exit status: 0 after a clean shutdown, 2 for a usage error, 1 otherwise.

Types

type ApprovalCheck

type ApprovalCheck struct {
	OK   bool   `json:"ok"`
	Text string `json:"text"`
}

ApprovalCheck is audit.VerifyApprovals' verdict on one gate, in words.

type Approvals

type Approvals struct {
	Keys     agent.ApproverVerifierFor
	Expected *agent.ApprovalPolicy
}

Approvals configures the approval-signature check a Prover runs: Keys resolves each approver's public key (nil: no check), and Expected, when set, is the policy the auditor expects, which the check runs against instead of the policy the gate's tally records.

type Conformance

type Conformance struct {
	OK     bool     `json:"ok"`
	Method string   `json:"method"` // "plan.Conform", or "structural" (see structural)
	Diffs  []string `json:"diffs,omitempty"`
	Digest string   `json:"digest"` // "match", "mismatch", or "not compared"
}

Conformance is the verdict on whether the run followed the declared topology.

type Decision

type Decision struct {
	Approver string `json:"approver,omitempty"` // empty for a one-decision gate's Approve
	Approved bool   `json:"approved"`
	Signed   bool   `json:"signed"`
}

Decision is one recorded approval decision.

type Event

type Event struct {
	Seq    int      `json:"seq"`   // 1-based position in the journal
	Name   string   `json:"name"`  // the record's journal name
	Kind   string   `json:"kind"`  // agent.StepKind
	Class  string   `json:"class"` // the row's style: model, tool, attempt, approval, halt, end, value
	Title  string   `json:"title"`
	Detail string   `json:"detail,omitempty"`
	Badges []string `json:"badges,omitempty"`
}

Event is one journal record, as a timeline row.

type Exports

type Exports map[string][]agent.Record

Exports is a Source over exported journals (audit.JournalExport), by run ID.

func (Exports) History

func (x Exports) History(_ context.Context, runID string) ([]agent.Record, error)

History returns the exported run's records.

func (Exports) Runs

func (x Exports) Runs(context.Context) ([]string, error)

Runs lists the exported runs.

type Flow

type Flow struct {
	Topology plan.Topology
	// Digest is flow.Digest(), compared with the digest the run journaled. Empty: not compared.
	Digest string
	// Conform is flow.Conform. Nil: the viewer runs only its structural check (see Conformance).
	Conform func(ctx context.Context, j *agent.Journal, runID string) (bool, []string, error)
}

Flow is a declared flow the viewer draws a run against. The journal records a flow run's name and topology digest, not its topology, so the topology comes from the caller: a program that holds the *plan.Flow passes its Topology, Digest and Conform; the bide-view command reads a Topology exported as JSON (json.Marshal(flow.Topology())) and, optionally, the digest.

type Gate

type Gate struct {
	ToolUseID  string     `json:"tool_use_id"`
	ToolName   string     `json:"tool_name,omitempty"`
	Single     bool       `json:"single,omitempty"` // a one-decision gate (agent.Approve)
	Need       int        `json:"need,omitempty"`
	Approvers  []string   `json:"approvers,omitempty"`
	ApprovedBy []string   `json:"approved_by,omitempty"`
	DeniedBy   []string   `json:"denied_by,omitempty"`
	Pending    []string   `json:"pending,omitempty"`
	Decisions  []Decision `json:"decisions,omitempty"`
	Tallied    bool       `json:"tallied"` // the gate journaled its terminal tally
	// Waiting: the run paused at this gate (its approval-pending record, agent.ApprovalWait) and
	// the call has no result, no terminal tally, and (for a one-decision gate) no decision yet.
	Waiting bool `json:"waiting"`
	// Signatures is whether the gate's approver signatures were verified (audit.VerifyApprovals,
	// with -approver-keys), or why they were not checked; SignaturesOK reports a verified gate.
	Signatures   string `json:"signatures"`
	SignaturesOK bool   `json:"signatures_ok"`
	Status       string `json:"status"`
}

Gate is a tool call's approval gate, from the decisions and tally the journal holds.

type Graph

type Graph struct {
	Nodes   []GraphNode `json:"nodes"`
	Edges   []GraphEdge `json:"edges"`
	SVG     string      `json:"-"`
	Mermaid string      `json:"mermaid"`
	Width   int         `json:"-"`
	Height  int         `json:"-"`
}

Graph is the declared topology with the run's path overlaid.

type GraphEdge

type GraphEdge struct {
	From  string `json:"from"`
	To    string `json:"to"`
	Label string `json:"label,omitempty"`
	Taken bool   `json:"taken"`
	Back  bool   `json:"back,omitempty"`
}

GraphEdge is one declared edge or Switch arm, and whether the run took it.

type GraphNode

type GraphNode struct {
	Name   string `json:"name"`
	Kind   string `json:"kind"`
	Status string `json:"status"` // done, halted, attempted, not-reached
	Iters  int    `json:"iters,omitempty"`
	Last   bool   `json:"last,omitempty"`
	// contains filtered or unexported fields
}

GraphNode is one declared node and what the run did with it.

type Halt

type Halt struct {
	Op          string    `json:"op"` // "tool" or "step"
	ID          string    `json:"id"` // the tool-use ID, or the step name ("node:<name>" for a plan node)
	ToolName    string    `json:"tool_name,omitempty"`
	Marker      string    `json:"marker"`
	AttemptedAt time.Time `json:"attempted_at,omitzero"`
	Ref         string    `json:"ref"` // the agent.HaltRef to resolve it with, as Go
}

Halt is an operation whose attempt marker is live with no result: a resume of the run returns *agent.OutcomeUnknown for it until agent.ResolveHalt records its outcome.

type JournalSource

type JournalSource struct{ J *agent.Journal }

JournalSource reads a store through a Journal. Runs lists through the store's agent.Lister, when it has one.

func (JournalSource) History

func (s JournalSource) History(ctx context.Context, runID string) ([]agent.Record, error)

History reads the run's records.

func (JournalSource) Runs

func (s JournalSource) Runs(ctx context.Context) ([]string, error)

Runs lists the store's runs, or none when the store cannot list them.

type Options

type Options struct {
	Source Source
	// Flows are the declared flows runs are drawn against, by flow name.
	Flows map[string]*Flow
	// Provers check runs against audit artifacts; the first to return a verdict for a run wins.
	Provers []Prover
}

Options configure Handler.

type Proof

type Proof struct {
	Source   string   `json:"source"` // "signed tree head" or "evidence package"
	OK       bool     `json:"ok"`
	Summary  string   `json:"summary"`
	Covers   int      `json:"covers"` // journal records the signed head commits to
	Problems []string `json:"problems,omitempty"`
	Items    []string `json:"items,omitempty"`
	// Approvals is the signature verdict on each m-of-n gate that journaled its tally, by
	// tool-use ID: audit.VerifyApprovals over the gate's evidence, with the approver keys given.
	// Nil without approver keys.
	Approvals map[string]ApprovalCheck `json:"approvals,omitempty"`
}

Proof is the audit verdict on the run's journal, from the audit package's own verifiers (the code bide-audit verify and verify-evidence run), never a reimplementation.

type Prover

type Prover func(ctx context.Context, runID string, recs []agent.Record) *Proof

Prover checks a run's records against an audit artifact. It returns nil for a run the artifact is not about.

func EvidenceProver

func EvidenceProver(pkg audit.EvidencePackage, v audit.Verifier, ap Approvals, opts ...audit.EvidenceVerifyOption) Prover

EvidenceProver checks an evidence package (audit.EvidencePackage.Verify, as bide-audit verify-evidence does) and that its signed head commits to the journal shown.

With approver keys (ap.Keys non-nil), it also checks each m-of-n gate's signatures with audit.VerifyApprovals over the package's actions, as bide-audit verify-approvals does.

func HeadProver

func HeadProver(sth audit.SignedTreeHead, v audit.Verifier, ap Approvals) Prover

HeadProver checks a signed tree head: its signature under v and the timestamp rule (audit.CheckTimestamp), and that its root commits to the first sth.Size records of the journal shown, by building and verifying an inclusion proof of the last of them (audit.ProveRecord, ProofBundle.Verify), as bide-audit prove and verify do.

With approver keys (ap.Keys non-nil), it also checks each m-of-n gate's signatures: it builds the gate's evidence from the journal under sth (audit.ApprovalEvidence) and verifies it with audit.VerifyApprovals, as bide-audit verify-approvals does.

type Source

type Source interface {
	Runs(ctx context.Context) ([]string, error)
	History(ctx context.Context, runID string) ([]agent.Record, error)
}

Source is what the viewer reads: the runs it lists and each run's records. Both are reads.

type Stores

type Stores struct {
	SQLite   func(path string) (agent.Store, io.Closer, error)
	Postgres func(dsn string) (agent.Store, io.Closer, error)
}

Stores opens the stores bide-view reads, read-only. It is how the command plugs in store backends (store/sqlite's and store/postgres's OpenReadOnly) without the core module importing one. A nil opener means this build cannot read that kind of store.

type View

type View struct {
	RunID  string `json:"run_id"`
	Kind   string `json:"kind"` // agent.RunKind, or "" when the run has no run:start
	Input  string `json:"input,omitempty"`
	Flow   string `json:"flow,omitempty"`   // the flow name run:start records
	Digest string `json:"digest,omitempty"` // the topology digest flow:digest records
	// State is the agent.RunState, except "halted" for a started run with a live attempt marker
	// and no result (see Halts): a resume returns *agent.OutcomeUnknown, so it is not in progress.
	State     string `json:"state"`
	StateText string `json:"state_text"` // State as the page shows it ("halted: outcome unknown")
	Terminal  string `json:"terminal,omitempty"`
	Records   int    `json:"records"`

	Events    []Event      `json:"events"`
	Halts     []Halt       `json:"halts,omitempty"`
	Gates     []Gate       `json:"gates,omitempty"`
	Graph     *Graph       `json:"graph,omitempty"`
	Conform   *Conformance `json:"conformance,omitempty"`
	Proof     *Proof       `json:"proof,omitempty"`
	Notes     []string     `json:"notes,omitempty"` // what the page cannot show for this run, and why
	LastNode  string       `json:"last_node,omitempty"`
	FinalText string       `json:"final_text,omitempty"`
}

View is everything the run page shows, built from the run's records alone (see Build).

func Build

func Build(ctx context.Context, runID string, recs []agent.Record, flow *Flow) *View

Build reads the run's records into a View. recs is the run's journal in order (header included); flow, when non-nil, is the declared flow the run is drawn against.

Jump to

Keyboard shortcuts

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