shadow

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package shadow is shadow mode's record and arithmetic (FR-26, ADR-011): what a shadow run pinned, what each attempt produced beside the human's patch, how a person graded the two blind, and the yield those grades give, with its confidence interval. Running the lane is the engine's; this package only keeps and reads the evidence, in ynf's own store under shadow/<run id>/, so it works on every store provider and never touches an item, a ticket or memory.

Index

Constants

View Source
const (
	Equivalent   = "equivalent"
	DifferentOK  = "different-valid"
	Superficial  = "superficial"
	Wrong        = "wrong"
	DoesNotBuild = "does-not-build"
)

Grades are ynh's five (its shadow-mode tutorial), the rubric a patch is graded against.

Variables

AllGrades lists the grades in the order a grader is offered them.

View Source
var ErrGraded = errors.New("shadow: already graded; --regrade replaces the grade")

ErrGraded means the attempt already has a grade and the caller did not ask to replace it.

Functions

func Graded

func Graded(ctx context.Context, s store.Store, run string) (int, error)

Graded counts a run's attempts that have a grade.

func NewOrder

func NewOrder() bool

NewOrder draws a blind order.

func SaveAttempt

func SaveAttempt(ctx context.Context, s store.Store, a Attempt) error

SaveAttempt writes an attempt.

func SaveGrade

func SaveGrade(ctx context.Context, s store.Store, run string, g Grade, regrade bool) error

SaveGrade writes an attempt's grade. An existing grade is kept unless regrade is set.

func SaveRun

func SaveRun(ctx context.Context, s store.Store, r Run) error

SaveRun writes a run, replacing any earlier version of it.

func Success

func Success(g string) bool

Success reports whether a grade counts toward yield: the patch fixes the defect, by the same means or by others.

func ValidGrade

func ValidGrade(g string) bool

ValidGrade reports whether g is one of the five.

func Wilson

func Wilson(k, n int) (low, high float64)

Wilson is the 95% Wilson score interval for k successes in n trials. It is the interval to use at the sample sizes shadow mode works with: unlike the plain normal approximation it stays inside [0, 1] and is honest at 0 or n successes. With no trials it is the whole of [0, 1].

Types

type Attempt

type Attempt struct {
	ID       string `json:"id"` // ULID
	Run      string `json:"run"`
	Repo     string `json:"repo"`
	Ticket   string `json:"ticket"` // owner/name#number
	FixPR    int    `json:"fix_pr"`
	MergeSHA string `json:"merge_sha"`
	Base     string `json:"base"` // the commit before the human fix
	// Title and Body are the ticket as the agent was given it, for the grader to read.
	Title string `json:"title,omitempty"`
	Body  string `json:"body,omitempty"`

	Outcome  string   `json:"outcome"`
	Detail   string   `json:"detail,omitempty"`
	Exit     int      `json:"exit"`
	Duration string   `json:"duration,omitempty"`
	Model    string   `json:"model,omitempty"`
	Changed  []string `json:"changed,omitempty"`
	runner.Usage
	// GateAccepted is whether the lane's diff gate would have let the change through to a pull
	// request; GateDetail says why not.
	GateAccepted bool   `json:"gate_accepted"`
	GateDetail   string `json:"gate_detail,omitempty"`

	AgentPatch string `json:"agent_patch"`
	HumanPatch string `json:"human_patch"`
	RunDir     string `json:"run_dir,omitempty"` // the run's folder: task, stdout, stderr, trajectory
	// AgentIsA is the blind order, drawn when the attempt is recorded: which of the two patches a
	// grader sees as A. It is copied into the grade, and never shown before both are graded.
	AgentIsA bool      `json:"agent_is_a"`
	Started  time.Time `json:"started"`
}

Attempt is one candidate run against its fix's base: everything needed to grade it and to report on it, kept whole so a later reader needs nothing but the store.

func Attempts

func Attempts(ctx context.Context, s store.Store, run string) ([]Attempt, error)

Attempts lists a run's attempts, in the order they ran.

func (Attempt) Blind

func (a Attempt) Blind() (patchA, patchB string)

Blind is the two patches as a grader sees them: A and B in the attempt's recorded order.

func (Attempt) Converged

func (a Attempt) Converged() bool

Converged reports whether the run ended converged.

type Grade

type Grade struct {
	Attempt  string    `json:"attempt"`
	AgentIsA bool      `json:"agent_is_a"` // the order the grader saw
	Agent    string    `json:"agent"`
	Human    string    `json:"human,omitempty"` // empty when the human patch was not graded
	Auto     bool      `json:"auto,omitempty"`  // graded without a person: an empty agent patch
	Note     string    `json:"note,omitempty"`
	By       string    `json:"by,omitempty"`
	At       time.Time `json:"at"`
}

Grade is a person's blind grading of one attempt: a grade for the agent's patch and one for the human's. Grading both is deliberate: the human patch is a check on the grader, and each grade is a labelled example.

func AutoGrade

func AutoGrade(attempt string, agentIsA bool, now time.Time) Grade

AutoGrade is the grade of an attempt that left no patch: wrong, without asking anyone.

func LoadGrade

func LoadGrade(ctx context.Context, s store.Store, run, attempt string) (g Grade, ok bool, err error)

LoadGrade reads an attempt's grade; ok is false when it has none.

func NewGrade

func NewGrade(attempt string, agentIsA bool, a, b string, now time.Time) (Grade, error)

NewGrade is the grade for what a grader gave patches A and B, recorded against the order the grader saw.

type GraderCheck

type GraderCheck struct {
	Graded int            `json:"graded"`
	Grades map[string]int `json:"grades,omitempty"`
	Passed *Rate          `json:"passed,omitempty"` // equivalent or different-valid
}

GraderCheck is how the grader did on the human patches, which are known to have been merged: a grader who calls many of them wrong is a grader to doubt.

type Group

type Group struct {
	Repo      string         `json:"repo"` // empty for the pooled group
	Attempted int            `json:"attempted"`
	Graded    int            `json:"graded"`
	Grades    map[string]int `json:"grades,omitempty"` // grades of the agent's patches
	// Yield is (equivalent + different-valid) ÷ graded agent attempts; nil until one is graded.
	Yield *Rate `json:"yield,omitempty"`
	// UpperBound is converged-and-gate-accepted ÷ attempted: what yield could be at most, with
	// nothing graded. It is not a measured yield.
	UpperBound  *Rate `json:"upper_bound"`
	Superficial int   `json:"superficial"`
}

Group is the numbers for one repository, or all of them pooled.

type Observed

type Observed struct {
	Harness    string `json:"harness,omitempty"` // name@version
	HarnessSHA string `json:"harness_sha,omitempty"`
	Ynh        string `json:"ynh_version,omitempty"`
	Model      string `json:"model,omitempty"`
	Effort     string `json:"effort,omitempty"`
}

Observed is what the runs reported having run on.

type PinRecord

type PinRecord struct {
	Run  string `json:"run"`
	Repo string `json:"repo"`
	Pins
}

PinRecord is one repository's pins in one shadow run.

type Pins

type Pins struct {
	Lane       string `json:"lane"`
	PolicyHash string `json:"policy_hash"`
	PolicySHA  string `json:"policy_sha,omitempty"` // the repository's commit its lanes were read at
	ConfigSHA  string `json:"config_sha,omitempty"`
	Runner     string `json:"runner"`
	Executor   string `json:"executor"`
	// Image is the agent image every run used: the lane's own, or the one built once from the
	// default branch's harness. Empty for a run on the host or inline, which has no image.
	Image string `json:"image,omitempty"`
	// Harness is the harness folder every run used, as a path in the default branch's checkout,
	// when the lane runs one from the repository on the host.
	Harness string `json:"harness,omitempty"`
	// HostAutoApprove is the --auto-approve the person gave at the terminal, when the attempts ran
	// on the host and passed it to ynh; empty when none was given or the lane runs in containment.
	HostAutoApprove string `json:"host_auto_approve,omitempty"`
	Model           string `json:"model,omitempty"`  // as the lane configures it; empty is the vendor's default
	Effort          string `json:"effort,omitempty"` // as the lane configures it

	Observed Observed `json:"observed"`
	Varied   []string `json:"varied,omitempty"`
}

Pins are what a shadow run held fixed for every candidate, so the sample is one experiment (the method's "pin the harness, do not inherit it"). The first group is resolved once before the first run; the observed group is what the runs themselves reported, and Varied names any that changed between attempts, which would make the sample two experiments.

func (*Pins) Observe

func (p *Pins) Observe(attempts []Attempt)

Observe fills in what the attempts reported, and names each thing that was not the same in all of them.

type Rate

type Rate struct {
	Successes int     `json:"successes"`
	N         int     `json:"n"`
	Value     float64 `json:"value"`
	Low       float64 `json:"low"`
	High      float64 `json:"high"`
}

Rate is a proportion with its 95% interval.

func NewRate

func NewRate(k, n int) *Rate

NewRate is k out of n with its Wilson interval; nil when there is nothing to divide by.

func (*Rate) String

func (r *Rate) String() string

type Report

type Report struct {
	Lane      string   `json:"lane"`
	Runs      []string `json:"runs"`
	Attempted int      `json:"attempted"`
	Graded    int      `json:"graded"`
	Pooled    Group    `json:"pooled"`
	Repos     []Group  `json:"repos,omitempty"`
	// Outcomes counts every attempt's run outcome.
	Outcomes map[string]int `json:"outcomes"`
	// CostUSD is the total the runner reported; CostReported how many attempts reported one.
	CostUSD      float64     `json:"cost_usd"`
	CostReported int         `json:"cost_reported"`
	CostPerRun   float64     `json:"cost_per_attempt,omitempty"`
	Pins         []PinRecord `json:"pins"`
	Grader       GraderCheck `json:"grader_check"`
	// BreakEven is y* = r ÷ h, when the lane declares the human time h and the review time r;
	// lanes declare neither yet, so it is never set and yield is not compared with it.
	BreakEven *float64 `json:"break_even,omitempty"`
	Note      string   `json:"note,omitempty"`
}

Report is what `ynf shadow report` says.

func BuildReport

func BuildReport(lane string, runs []Run, attempts []Attempt, grades map[string]Grade) Report

BuildReport computes the report for attempts (all of one lane), their grades by attempt id, and the runs they came from.

func (Report) Text

func (r Report) Text() string

Text renders the report for a terminal.

type Run

type Run struct {
	ID      string    `json:"id"` // ULID
	Lane    string    `json:"lane"`
	Repos   []string  `json:"repos"`
	Created time.Time `json:"created"`
	Since   string    `json:"since,omitempty"`
	Limit   int       `json:"limit,omitempty"`
	// Pins are what each repository's runs held fixed, by repository.
	Pins map[string]Pins `json:"pins"`
	// Candidates is how many closed tickets the lane would have taken; Attempted how many of
	// them ran (the limit, or a fix that could not be built from, leave some out).
	Candidates int    `json:"candidates"`
	Attempted  int    `json:"attempted"`
	Skipped    []Skip `json:"skipped,omitempty"`
	// Stopped says why the run ended before its candidates ran out, when it did: a run that
	// cannot start (a missing executor, an image that will not build) would fail every candidate
	// the same way, so it stops after the first.
	Stopped string `json:"stopped,omitempty"`
}

Run is one `ynf shadow run`.

func LoadRun

func LoadRun(ctx context.Context, s store.Store, id string) (Run, error)

LoadRun reads a run; an id that names none is an error naming it.

func Runs

func Runs(ctx context.Context, s store.Store) ([]Run, error)

Runs lists every shadow run, oldest first.

type Skip

type Skip struct {
	Ticket string `json:"ticket"`
	Reason string `json:"reason"`
}

Skip is a candidate that was not attempted, and why.

Jump to

Keyboard shortcuts

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