warden

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Mar 20, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package warden implements the code review agent that reviews Smith's changes.

The Warden spawns a separate Claude session with a review-focused prompt, providing the git diff of changes made by the Smith. It returns a structured verdict: approve, reject, or request-changes with feedback.

Index

Constants

View Source
const RulesFileName = ".forge/warden-rules.yaml"

RulesFileName is the per-anvil file storing learned review rules.

Variables

This section is empty.

Functions

func FetchRecentPRNumbers

func FetchRecentPRNumbers(ctx context.Context, repoDir string, limit int) ([]int, error)

FetchRecentPRNumbers returns the most recent merged PR numbers for a repo.

func GroupComments

func GroupComments(comments []PRComment) [][]PRComment

GroupComments groups semantically similar comments using keyword overlap. First, comments with identical normalized text are merged. Then, groups whose keyword sets exceed a Jaccard similarity threshold are merged together so that comments about the same pattern (e.g. "missing error check on Open()" vs "error from ReadFile not handled") land in one group.

func LearnFromCIFix added in v0.4.0

func LearnFromCIFix(ctx context.Context, anvilPath, repoDir string, failingLogs map[string]string, fixDiff string, prNumber int) error

LearnFromCIFix extracts lint rule patterns from CI failure logs and the subsequent fix diff, then stores them as warden rules so future Smith sessions avoid the anti-patterns before they reach CI.

It is intentionally non-fatal: callers should log any returned error but not let it block the successful CI fix result from being recorded.

func RulesPath

func RulesPath(anvilPath string) string

RulesPath returns the full path to the warden rules file for an anvil.

func SaveRules

func SaveRules(anvilPath string, rf *RulesFile) error

SaveRules writes the rules file to the anvil path, creating the .forge directory if it does not exist.

Types

type PRComment

type PRComment struct {
	Body     string `json:"body"`
	User     string `json:"user"`
	Path     string `json:"path"`
	PRNumber int    `json:"pr_number"`
}

PRComment represents a review comment fetched from GitHub.

func FetchCopilotComments

func FetchCopilotComments(ctx context.Context, repoDir string, prNumber int) ([]PRComment, error)

FetchCopilotComments retrieves review comments on a PR that were authored by copilot[bot], github-actions[bot], or copilot via the gh CLI.

type ReviewIssue

type ReviewIssue struct {
	// File is the affected file path.
	File string `json:"file"`
	// Line is the approximate line number (0 if unknown).
	Line int `json:"line"`
	// Severity is "error", "warning", or "suggestion".
	Severity string `json:"severity"`
	// Message describes the issue.
	Message string `json:"message"`
}

ReviewIssue represents a specific issue found during review.

type ReviewResult

type ReviewResult struct {
	// Verdict is the review decision.
	Verdict Verdict
	// UsedProvider records which provider actually completed the review.
	UsedProvider *provider.Provider
	// Summary is a brief summary of the review.
	Summary string
	// Issues is a list of specific issues found.
	Issues []ReviewIssue
	// RawOutput is the full Claude output.
	RawOutput string
	// Duration is how long the review took.
	Duration time.Duration
	// CostUSD is the cost of the review session.
	CostUSD float64
	// NoDiff is true when the rejection was because Smith produced no diff.
	NoDiff bool
}

ReviewResult captures the Warden's review outcome.

func Review

func Review(ctx context.Context, worktreePath, beadID, beadTitle, beadDescription, anvilPath string, db *state.DB, priorFeedback string, providers ...provider.Provider) (*ReviewResult, error)

Review runs a Warden review of the changes in the given worktree. It gets the git diff, spawns a Claude review session, and parses the verdict.

beadTitle and beadDescription are used to check whether the diff actually implements what the bead requested (scope drift detection). db is used to log lifecycle events; db may be nil to skip logging. providers is the ordered list of AI providers to try. When empty, provider.Defaults() is used. Provider fallback applies on rate limit.

type Rule

type Rule struct {
	ID       string `yaml:"id"       json:"id"`
	Category string `yaml:"category" json:"category"`
	Pattern  string `yaml:"pattern"  json:"pattern"`
	Check    string `yaml:"check"    json:"check"`
	Source   string `yaml:"source"   json:"source"`
	Added    string `yaml:"added"    json:"added"`
}

Rule represents a single learned review pattern.

func DistillRule

func DistillRule(ctx context.Context, comments []PRComment, repoDir string) (*Rule, error)

DistillRule uses a Claude session to convert a set of similar review comments into a single warden rule. Returns the rule or an error.

func (Rule) MarshalYAML added in v0.8.0

func (r Rule) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler for Rule, ensuring string values containing special YAML characters (like ": ") are double-quoted. It uses a type alias to get automatic field marshaling (so future fields on Rule are included without updating this method), then post-processes the resulting yaml.Node tree to apply quoting styles.

type RulesFile

type RulesFile struct {
	Rules []Rule `yaml:"rules"`
}

RulesFile is the top-level structure of warden-rules.yaml.

func LoadRules

func LoadRules(anvilPath string) (*RulesFile, error)

LoadRules reads the warden rules file from the anvil path. Returns an empty RulesFile (not an error) if the file does not exist.

func (*RulesFile) AddRule

func (rf *RulesFile) AddRule(r Rule) bool

AddRule appends a rule to the file, skipping duplicates by ID. Returns true if the rule was added (not a duplicate).

func (*RulesFile) FormatChecklist

func (rf *RulesFile) FormatChecklist() string

FormatChecklist returns the rules formatted as a numbered checklist suitable for inclusion in a review prompt.

func (*RulesFile) RemoveRule

func (rf *RulesFile) RemoveRule(id string) bool

RemoveRule removes a rule by ID. Returns true if a rule was removed.

type Verdict

type Verdict string

Verdict represents the Warden's review decision.

const (
	VerdictApprove        Verdict = "approve"
	VerdictReject         Verdict = "reject"
	VerdictRequestChanges Verdict = "request_changes"
)

Jump to

Keyboard shortcuts

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