generate

package
v0.2.0-rc.3 Latest Latest
Warning

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

Go to latest
Published: Nov 13, 2026 License: MIT Imports: 35 Imported by: 0

Documentation

Overview

Package generate is the pipeline behind "the generation pipeline": it assembles the generation bundle for a pull request, unpacks the checkout into a private run directory, runs the shared generate-and-repair loop (agent.Generator) with a model backend, and finishes the document the way the hosted worker does: output redaction, secret rejection, derived fields, the generator block and a strict check of the stored form.

Its sources and the backend are interfaces, so a test runs the whole pipeline against a fake clone, a fake GitHub and a stub backend. Run never writes the document anywhere: it returns it, and nothing is returned for a run that was rejected, so a caller cannot publish a partial result.

Every failure is an *Error naming a Category, which the command line maps to an exit code.

Index

Constants

View Source
const MaxGroupMembers = 8

MaxGroupMembers bounds a group; internal/reviewgroups enforces it on definitions.

Variables

AutoOrder is the order in which auto tries the backends. The model a run names applies to the first only. cursor-agent is left out on purpose: it must be chosen explicitly (see SECURITY.md, "The cursor-agent backend").

DesktopAutoOrder is the order in which auto tries the backends in the desktop app and its daemon: Claude Code, then Codex. auto never spends money through the Anthropic API there.

View Source
var ErrBackendNotOffered = errors.New("the baum desktop app does not run jobs with this backend")

ErrBackendNotOffered is a backend the desktop app does not run jobs with.

View Source
var ErrCannotComplete = errors.New("the backend cannot make a single structured call")

ErrCannotComplete is a backend without single-call completions (agent.Completer): cursor-agent.

View Source
var ErrHeadChanged = errors.New("pull request head changed")

ErrHeadChanged: a pull request's head moved after the run was prepared, so its evidence would not be what was confirmed.

Functions

func BoundPasses

func BoundPasses(backend agent.Backend, timeout time.Duration) agent.Backend

passBounded applies the per-call timeout to a backend. BoundPasses bounds each call of backend by timeout as a review's pass_timeout does: a call that runs out fails with the budget "pass_timeout", which the loop does not retry. Zero leaves it unbounded.

func CheckExplicitPath

func CheckExplicitPath(name config.Backend, path string) error

CheckExplicitPath returns an ExplicitPathError when path is not an executable file, and nil for an empty path.

func ConcurrentCalls

func ConcurrentCalls(backend agent.Backend) bool

ConcurrentCalls reports whether backend may run several calls over one run directory at once (agent.ConcurrentCaller). A host's wrapper of a backend forwards it, or a staged review runs its stages in turn.

func DesktopBackend

func DesktopBackend(b config.Backend) bool

DesktopBackend reports whether the desktop app and its daemon run jobs with b: auto, claude and codex. The cursor-agent and anthropic backends stay available to the baum command line only.

func Gaps

func Gaps(document []byte) ([]string, bool)

Gaps names the sections of a completed staged document published without their details, and reports whether it has no context. A stale section, carried from an earlier version, is not one: nothing writes its details again.

func NotOfferedError

func NotOfferedError(b config.Backend) error

NotOfferedError reports a job whose backend, such as one set in config.toml, the desktop app does not run. It never switches to another backend.

func RemoveTree

func RemoveTree(dir string)

RemoveTree removes a directory whose subdirectories may be read-only, as an unpacked checkout's are.

func RunTask

func RunTask(ctx context.Context, o TaskOptions) (agent.Outcome, []byte, error)

RunTask runs a task through the review harness's loop, as Run runs a review: the wall clock and pass bounds apply, what the loop returned is masked (agent.RedactTaskOutput) on every path before it is returned, and a failure is an *Error of its category. A reply the schema or the task's check still rejected after the repairs is a CategoryValidation error, and no document is returned with an error. The Outcome is returned on every path, for the ledger.

func WriteDiagnostics

func WriteDiagnostics(path string, runErr error, outcome agent.Outcome) error

WriteDiagnostics writes the run's end state to path: ok or failed, the category and the (already redacted) error text of a failure, and the outcome, whose size the loop bounds (at most agent.MaxDiagnostics events and a retained document of at most agent.MaxRetainedDocumentBytes).

func WriteFileAtomic

func WriteFileAtomic(path string, data []byte) (err error)

WriteFileAtomic writes data to path through a temporary file beside it, so a failed run leaves no partial file. The file is readable by its owner only: it can hold session text.

Types

type Assembler

type Assembler interface {
	Assemble(ctx context.Context, req assemble.Request) (assemble.Result, error)
}

Assembler builds the bundle and the archives of one pull request; *assemble.Assembler implements it.

type Backends

type Backends struct {
	Claude      func(model string) CheckedBackend
	Codex       func(model string) CheckedBackend
	CursorAgent func(model string) CheckedBackend
	Anthropic   func(model string) CheckedBackend
}

Backends builds the local backends. DefaultBackends and DefaultBackendsFor are the only production implementations: the user's installed CLIs under their own login, in the profiles meant for a person's machine, and the Anthropic API under their own key. Tests substitute fakes.

func DefaultBackends

func DefaultBackends() Backends

DefaultBackends builds Claude Code with the User profile, Codex with the Local profile and the Cursor Agent CLI, which run in the user's environment, finding each on PATH, and the Anthropic API with the key from ANTHROPIC_API_KEY. The Isolated and Container profiles belong to hosted runs and are never built here.

func DefaultBackendsFor

func DefaultBackendsFor(cfg config.Config) Backends

DefaultBackendsFor is DefaultBackends with the executables cfg names in BackendPaths and the variables of its AgentEnv. A named path replaces the PATH lookup: when it cannot be run, the backend fails naming backend_paths.<name> and PATH is not searched.

type Category

type Category string

Category classifies why a run failed.

const (
	// CategoryInput is a failure of what the run needs: the pull request, its
	// commits in the clone, GitHub, or a bundle or checkout over its caps.
	CategoryInput Category = "input"
	// CategoryBackend is a backend that is missing, too old, cannot sandbox,
	// failed or whose provider was unavailable.
	CategoryBackend Category = "backend"
	// CategoryBudget is a spent call, token or wall-clock budget.
	CategoryBudget Category = "budget"
	// CategoryValidation is a document the validator rejected after the
	// repairs, or one that held a secret. Nothing is written for it.
	CategoryValidation Category = "validation"
	// CategoryInterrupted is a run stopped by SIGINT or SIGTERM.
	CategoryInterrupted Category = "interrupted"
	// CategoryInternal is a failure of baum's own steps, such as masking the
	// output. The hosted worker treats it as a plain failure, not a rejected
	// document, so it exits with the generic code.
	CategoryInternal Category = "internal"
)

func CategoryOf

func CategoryOf(err error) Category

CategoryOf returns the category of err, or "" when it is not an *Error.

type CheckedBackend

type CheckedBackend interface {
	agent.Backend
	// Check returns the installed version.
	Check(ctx context.Context) (version string, err error)
}

CheckedBackend is a backend that can verify, before any work is done, that it is installed, recent enough and able to run.

type Error

type Error struct {
	Category Category
	Err      error
	// contains filtered or unexported fields
}

Error is a failure of one category. Its text never holds a secret the model or the backend wrote: it is redacted before it is built.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Is

func (e *Error) Is(target error) bool

func (*Error) Unwrap

func (e *Error) Unwrap() error

type ExplicitPathError

type ExplicitPathError struct {
	Backend config.Backend
	Path    string
	Err     error
}

ExplicitPathError reports a backend_paths entry that names a file which cannot be run. Err is why.

func (*ExplicitPathError) Error

func (e *ExplicitPathError) Error() string

func (*ExplicitPathError) Unwrap

func (e *ExplicitPathError) Unwrap() error

type Group

type Group struct {
	// Name is the group's name, the document's stack title unless
	// GeneratedName.
	Name string
	// GeneratedName gives the document's stack title the name the model
	// writes for the group, when it wrote a usable one: a stack group's,
	// whose name is baum's. A group the person named keeps Name.
	GeneratedName bool
	// Members are the group's pull requests in group order.
	Members []GroupMember
	// MemberReviews is written to the run directory as members.json, the
	// members' own reviews in brief for the model to read.
	MemberReviews []byte
}

Group asks Run for a review group's combined review instead of one pull request's: Request names the repository and the limits, and its Number is ignored. See internal/reviewgroups.

type GroupMember

type GroupMember struct {
	Number int
	// Head, when not empty, is the head the run was confirmed for: a member
	// whose head moved fails the run before any model call.
	Head string
	// ReviewVersion is the member's saved review version the run reads,
	// recorded in the document's stack; at least 1.
	ReviewVersion int
}

GroupMember is one pull request of a group.

type Options

type Options struct {
	PriceList *pricing.List
	Assembler Assembler
	// Request names the pull request and the limits. Run sets its Checkout and
	// Attachments writers.
	Request assemble.Request
	Backend agent.Backend
	// BackendVersion is the installed backend's version, for the progress line.
	BackendVersion string
	Model          string
	Budgets        agent.Budgets
	// PassTimeout bounds each backend call; zero leaves it to the wall clock.
	PassTimeout time.Duration
	// TileKinds is the tile allow-list; empty offers no tiles.
	TileKinds []string
	// PromptSource is recorded in the stored metadata as store.Metadata's
	// PromptSource; the host that chose the prompts sets it.
	PromptSource string
	// Prompts defaults to this module's public prompt.
	Prompts agent.Prompts
	// Staged writes a single pull request's review in stages
	// (agent.Generator.StagedReview) instead of in one pass: the outline,
	// then the sections' details and the context. A section whose details
	// fail is published without them and a context that fails is left out;
	// only a failed outline (or no section with details) fails the run. A
	// review group is always written in one pass.
	Staged bool
	// StagedPrompts defaults to this module's public staged prompt.
	StagedPrompts agent.StagedPrompts
	// OnDraft, for a staged run, receives the review so far each time a
	// stage result lands, masked and completed as the published document is
	// (CompleteStaged) but with the sections still being written pending.
	// It is never a version. Calls come one at a time, from a goroutine of
	// the run, and the last one returns before Run does.
	OnDraft func(document []byte)
	// Continue, for a staged run, is the saved version to complete instead
	// of writing a new one: the latest version, some of whose sections
	// failed. Only the details of those sections are written again
	// (agent.StagedRun.Outline), against the version's head, base and merge
	// base, and the result is the same version with its metadata, model,
	// prompt version and generation time. Request.Previous must be the
	// version before it, which it was reconciled with. Nothing is kept for
	// a chat.
	Continue  *store.Version
	Validator *review.DocumentValidator
	Redactor  *bundle.Redactor
	// Progress receives one line per step; nil discards them. The document is
	// never written to it.
	Progress io.Writer
	// OnRepairs receives the validation repairs made so far after each
	// validation, over every stage of a staged run, without model text.
	OnRepairs func(repairs int)
	// KeepRunDir keeps the run directory and reports its path on Progress.
	KeepRunDir bool
	// KeepSession persists the backend's session and keeps the run directory,
	// under SessionRoot, when the run succeeds with a session id, and records
	// both in the version's Metadata.Session so a later chat can continue the
	// session in the same directory. A failed run, a missing session id and a
	// group review remove the directory as usual. Only a local Claude Code or
	// Codex backend supports it.
	KeepSession bool
	// SessionRoot is the directory kept runs are made in; empty is
	// reviewruns.DefaultRoot.
	SessionRoot string
	// Stored, for Publish, runs once the version is stored, with its metadata.
	// The version is already published: an error is a warning on Progress.
	Stored func(ctx context.Context, key store.Key, m store.Metadata) error
	// BundleOut, when not empty, receives the exact bundle the model was given.
	BundleOut string
	// DiagnosticsOut, when not empty, receives the run's redacted outcome as
	// JSON: usage, repairs, findings and at most agent.MaxDiagnostics events.
	// It is written for failed runs too.
	DiagnosticsOut string
	// Now defaults to time.Now.
	Now func() time.Time
	// Group, when set, generates a review group's combined review of the
	// pull requests it names instead of the one Request names; Prompts then
	// defaults to the public group prompt.
	Group *Group
}

Options are the inputs of one run.

type Result

type Result struct {
	Attachments []store.Attachment
	// Document is the finished, strictly valid document. Nil on any failure.
	Document []byte
	Metadata store.Metadata
	Outcome  agent.Outcome
	// RunDir is the run directory when KeepRunDir or KeepSession kept it.
	RunDir string
	// Elapsed is the wall time of the run.
	Elapsed time.Duration
	// FailedSections, for a staged run, are the sections the document holds
	// without their details, and ContextFailed says it has no context.
	FailedSections []string
	ContextFailed  bool
}

Result is a finished run.

func Publish

func Publish(ctx context.Context, versions Versions, key store.Key, o Options, cost func(Result) *float64) (result Result, err error)

Publish runs the same validation/repair pipeline for CLI and queued jobs and atomically appends only a completed document to the version store. Once the version is stored the call succeeds: the version is already visible, so a failure to record the run's outcome, or of o.Stored, afterwards is a warning on o.Progress.

func Run

func Run(ctx context.Context, o Options) (result Result, err error)

Run executes the pipeline. The run directory is removed on every path unless Options.KeepRunDir is set.

type Selected

type Selected struct {
	Backend CheckedBackend
	Version string
	// Model is the model the backend was built with; empty is its default.
	Model string
}

Selected is the backend a run uses.

func Select

func Select(ctx context.Context, requested config.Backend, model string, backends Backends, skipped io.Writer) (Selected, error)

Select resolves the requested backend, checking that it can run.

auto tries, in order, claude, codex and anthropic, each when it passes its checks (anthropic's is that ANTHROPIC_API_KEY is set), and fails naming every reason when none does. It never picks cursor-agent, which cannot be held to read-only as reliably as the others: that backend runs only when named. A backend named explicitly fails with its own check's reason.

A model names a model of one backend, so with auto it applies to the first choice, claude, only: a backend auto falls back to runs with its own default model, and skipped says so. skipped also receives why each earlier choice was skipped; nil discards both. anthropic's default model is resolved here (anthropic.DefaultModel), so Selected.Model names it and the run's cost at API prices can be worked out from it.

func SelectDesktop

func SelectDesktop(ctx context.Context, requested config.Backend, model string, backends Backends, skipped io.Writer) (Selected, error)

SelectDesktop is Select for the desktop app and its daemon. It refuses a known backend other than auto, claude and codex (ErrBackendNotOffered), and auto tries DesktopAutoOrder only, so no job reaches cursor-agent or the Anthropic API.

type TaskOptions

type TaskOptions struct {
	Backend agent.Backend
	// Task is the task; its Budgets' WallClock bounds the whole run.
	Task agent.Task
	// PassTimeout bounds each backend call; zero leaves it to the wall clock.
	PassTimeout time.Duration
	Redactor    *bundle.Redactor
	Logger      *slog.Logger
}

TaskOptions are the inputs of one agent task (agent.Task) besides a review, such as feature discovery.

type Versions

type Versions interface {
	Latest(context.Context, store.Key) (store.Version, error)
	BeginRun(context.Context, store.Key, time.Time) (int64, error)
	HeartbeatRun(context.Context, int64, time.Time) error
	FinishRun(context.Context, int64, string) error
	Put(context.Context, store.Key, store.Version, store.Version) error
}

Versions is the part of *store.Store that Publish uses.

Directories

Path Synopsis
Package generatetest is a stub model backend for tests of "the generation pipeline": it returns canned documents without calling a model, and records the run directories it was given.
Package generatetest is a stub model backend for tests of "the generation pipeline": it returns canned documents without calling a model, and records the run directories it was given.

Jump to

Keyboard shortcuts

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