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
- func FetchRecentPRNumbers(ctx context.Context, repoDir string, limit int) ([]int, error)
- func GroupComments(comments []PRComment) [][]PRComment
- func InsertRulesAsPending(rules []Rule, anvilName string, insert PendingInserter) error
- func LearnFromCIFix(ctx context.Context, anvilPath, repoDir string, failingLogs map[string]string, ...) error
- func RulesPath(anvilPath string) string
- func SaveRules(anvilPath string, rf *RulesFile) error
- type LearnConfig
- type PRComment
- type PendingInserter
- type ReviewIssue
- type ReviewResult
- type Rule
- type RulesFile
- type SourceList
- type Verdict
Constants ¶
const RulesFileName = ".forge/warden-rules.yaml"
RulesFileName is the per-anvil file storing learned review rules.
Variables ¶
This section is empty.
Functions ¶
func FetchRecentPRNumbers ¶
FetchRecentPRNumbers returns the most recent merged PR numbers for a repo.
func GroupComments ¶
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 InsertRulesAsPending ¶ added in v0.10.0
func InsertRulesAsPending(rules []Rule, anvilName string, insert PendingInserter) error
InsertRulesAsPending serializes each rule to YAML and inserts it into the pending_warden_rules table via the provided inserter function.
func LearnFromCIFix ¶ added in v0.4.0
func LearnFromCIFix(ctx context.Context, anvilPath, repoDir string, failingLogs map[string]string, fixDiff string, prNumber int, cfg ...*LearnConfig) 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.
When cfg is non-nil and cfg.SmelterEnabled is true, new rules are inserted into the pending_warden_rules table instead of being written directly to the rules file. When cfg is nil or SmelterEnabled is false, the existing direct-save behavior is preserved.
It is intentionally non-fatal: callers should log any returned error but not let it block the successful CI fix result from being recorded.
Types ¶
type LearnConfig ¶ added in v0.10.0
type LearnConfig struct {
SmelterEnabled bool
AnvilName string // anvil name for pending rule insertion
InsertPending PendingInserter // typically state.DB.InsertPendingRule
}
LearnConfig provides optional smelter-aware routing for learned rules. When SmelterEnabled is true and InsertPending is non-nil, new rules are inserted into the pending_warden_rules table instead of being written directly to the rules file.
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.
type PendingInserter ¶ added in v0.10.0
PendingInserter is a function that inserts a rule into the pending_warden_rules table. It matches the signature of state.DB.InsertPendingRule.
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 SourceList `yaml:"source" json:"source"`
Added string `yaml:"added" json:"added"`
}
Rule represents a single learned review pattern.
func DistillRule ¶
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
MarshalYAML implements yaml.Marshaler for Rule, applying appropriate YAML styles to string fields:
- Scalars longer than 80 characters use a folded block scalar (>-) for readability and easier editing.
- Shorter scalars that contain YAML-special sequences (": ", '"') or a comment-introducing '#' 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.
type RulesFile ¶
type RulesFile struct {
Rules []Rule `yaml:"rules"`
}
RulesFile is the top-level structure of warden-rules.yaml.
func LoadRules ¶
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 ¶
AddRule appends a rule to the file, skipping duplicates by ID. Returns true if the rule was added (not a duplicate).
func (*RulesFile) FormatChecklist ¶
FormatChecklist returns the rules formatted as a numbered checklist suitable for inclusion in a review prompt.
func (*RulesFile) RemoveRule ¶
RemoveRule removes a rule by ID. Returns true if a rule was removed.
type SourceList ¶ added in v0.10.0
type SourceList []string
SourceList is a slice of source references. It YAML-marshals as a plain scalar when there is exactly one element and as a flow sequence when there are multiple, making multi-PR attribution programmatically accessible. It unmarshals from either format for backward compatibility.
func (SourceList) MarshalYAML ¶ added in v0.10.0
func (sl SourceList) MarshalYAML() (any, error)
MarshalYAML emits a plain scalar for a single source and a YAML flow sequence for multiple sources.
func (SourceList) String ¶ added in v0.10.0
func (sl SourceList) String() string
String returns the sources joined by ", " for display purposes.
func (*SourceList) UnmarshalYAML ¶ added in v0.10.0
func (sl *SourceList) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML reads either a scalar string or a YAML sequence into a SourceList.