Documentation
¶
Index ¶
- Constants
- Variables
- func HasSubstantiveCodeChange(diff *types.Diff) bool
- func RenderRuleCatalog(ids []string) string
- func ReviewChangeScope(diff *types.Diff) string
- func ValidateRuleCatalog(ids []string, est TokenEstimator) error
- type BuildOptions
- type ContextSegment
- type Document
- type HeuristicEstimator
- type LanguageRules
- type ParseError
- type ParseErrorKind
- type PriorityTier
- type PromptBuilder
- func (b *PromptBuilder) BuildDocumentationPrompt(diff *types.Diff, language string) string
- func (b *PromptBuilder) BuildPrompt(diff *types.Diff, metrics *analyzer.DiffMetrics, opts BuildOptions) (PromptParts, error)
- func (b *PromptBuilder) BuildReviewPrompt(diff *types.Diff, metrics *analyzer.DiffMetrics) string
- func (b *PromptBuilder) BuildSummaryPrompt(diff *types.Diff, metrics *analyzer.DiffMetrics) string
- func (b *PromptBuilder) BuildTestPrompt(diff *types.Diff, language string) string
- func (b *PromptBuilder) RuleCatalog() []string
- func (b *PromptBuilder) SetRuleCatalog(ids []string) error
- func (b *PromptBuilder) TruncatePrompt(prompt string, maxTokens int) string
- type PromptParts
- type ResponseParser
- func (p *ResponseParser) ExtractCodeBlocks(response string) []string
- func (p *ResponseParser) ParseDocumentationResponse(response string) (string, error)
- func (p *ResponseParser) ParseReviewResponse(response string) (*types.ReviewResult, error)
- func (p *ResponseParser) ParseSummaryResponse(response string) (string, error)
- func (p *ResponseParser) ParseTestResponse(response string, language string) (string, error)
- func (p *ResponseParser) SanitizeResponse(response string) string
- type TokenBudget
- func (b *TokenBudget) Available() int
- func (b *TokenBudget) BuildContextSegments(diff *types.Diff, detector *analyzer.LanguageDetector) []ContextSegment
- func (b *TokenBudget) EstimateTotal(segments []ContextSegment) int
- func (b *TokenBudget) TrimToFit(segments []ContextSegment, baseTokens int) []ContextSegment
- type TokenEstimator
Constants ¶
const MaxRuleCatalogTokens = 512
MaxRuleCatalogTokens is the ceiling AC-002 puts on the rendered catalog section. The current 21-rule catalog renders at roughly a quarter of it, so there is room to grow; growing PAST it is a loud build/assembly failure and never a silent truncation. That distinction is the whole point: a truncated list would make the model cite a rule that exists but was cut, and the gate would discard it -- this card's defect back by another road.
Variables ¶
var DefaultRuleCatalog = []string{
"performance/excessive-allocation",
"performance/inefficient-algorithm",
"performance/inefficient-loop",
"performance/memory-leak",
"performance/n-plus-one",
"quality/dead-code",
"quality/duplicate-code",
"quality/high-complexity",
"quality/long-function",
"quality/magic-numbers",
"quality/missing-error-handling",
"quality/poor-naming",
"quality/unused-variable",
"security/command-injection",
"security/hardcoded-secret",
"security/insecure-random",
"security/missing-auth",
"security/path-traversal",
"security/sql-injection",
"security/weak-crypto",
"security/xss",
}
DefaultRuleCatalog is the mirror of the embedded review catalog: every id of internal/review/rules/{security,quality,performance}.yml, sorted, exactly as RulesLoader.Get indexes them. Keep it sorted and keep it complete -- tests/unit/AUR-461.go proves both.
Functions ¶
func HasSubstantiveCodeChange ¶ added in v1.0.12
HasSubstantiveCodeChange distinguishes a code-bearing change from a repository-operation change. Config, workflow, documentation and comment-only edits may still be reviewed for their direct effect, but they must not receive fabricated praise about code quality in the published review. Unknown extensions remain code by default so a new source language is never silently excluded.
func RenderRuleCatalog ¶ added in v1.0.2
RenderRuleCatalog renders the closed list injected into the review prompt. It deliberately carries ids only -- no titles: the ids are self-descriptive (security/command-injection is what the model called "shell-injection"), and mirroring titles too would double the surface that can drift from the YAML.
The rendered block must not open a ```json fence: AUR-459's TemplateTeachesOneSchema requires the template to show exactly one JSON example, and a second one here would teach a second schema.
func ReviewChangeScope ¶ added in v1.0.12
ReviewChangeScope is safe to place in the model prompt because it is derived from the diff, not authored by repository content.
func ValidateRuleCatalog ¶ added in v1.0.2
func ValidateRuleCatalog(ids []string, est TokenEstimator) error
ValidateRuleCatalog reports whether the rendered form of ids fits MaxRuleCatalogTokens under est, and rejects an empty or unsorted catalog. An empty catalog would render a section telling the model to choose from nothing.
Types ¶
type BuildOptions ¶
type BuildOptions struct {
MaxTokens int // Maximum tokens for the entire prompt
SchemaKind string // Type of schema: "review", "test", "docs", "summary"
Role string // Role context: "reviewer", "tester", "documenter"
ReserveReply int // Tokens to reserve for the reply
CIContext string // Existing CI/check context, when the caller has it
Language string // Human-facing review language, e.g. "pt-BR"
ChangeScope string // Deterministic scope classification for the review
}
BuildOptions configures prompt building
type ContextSegment ¶
type ContextSegment struct {
Content string // The actual content
Priority PriorityTier // Priority level for trimming
SortKey string // Stable sort key for deterministic ordering
Tokens int // Estimated token count
FilePath string // Path of the diff file this segment came from (AUR-467)
IsProse bool // True when FilePath classified as documentation, not code (AUR-467)
}
ContextSegment represents a piece of context with priority
type Document ¶
type Document struct {
Path string // Document path
Content string // Document content
Type string // Document type: "style-guide", "standards", "examples"
}
Document represents additional context documents
type HeuristicEstimator ¶
type HeuristicEstimator struct{}
HeuristicEstimator is the production TokenEstimator. builder.go in the restored c12d7ab engine constructed its default estimator as &StubEstimator{}, but StubEstimator only ever existed in types_test.go -- it never compiled into a production binary (see AUR-430's restoration audit). This type is that estimator, promoted to production: the same ~4-characters-per-token heuristic already used, unrelated to any vendor, by internal/llm/estimator.go's heuristicTokens fallback. Keeping the same ratio here means a budget computed by this package roughly agrees with the one internal/llm falls back to when a provider cannot report its own token count.
func NewHeuristicEstimator ¶
func NewHeuristicEstimator() *HeuristicEstimator
NewHeuristicEstimator creates the default production TokenEstimator.
func (*HeuristicEstimator) Estimate ¶
func (e *HeuristicEstimator) Estimate(text string) int
Estimate approximates token count at ~4 characters per token, never returning zero for non-empty input so a non-empty segment can never be budgeted as free.
type LanguageRules ¶
type LanguageRules struct {
Language string // Programming language
Rules []string // List of rules to apply
}
LanguageRules contains language-specific review rules
type ParseError ¶
type ParseError struct {
Kind ParseErrorKind
// Raw is the response that failed to parse, bounded to a safe preview
// length so a large or adversarial response cannot balloon an error
// message that ends up in logs.
Raw string
Err error
}
ParseError is the typed, clear failure ParseReviewResponse returns instead of silently degrading to an empty result. See the "Parser fallback" note in docs/specs/AUR-430.md for the reasoning: a caller (or a human reading the review) must be able to tell "no problems found" apart from "the engine could not understand the model," and a bare error string forces every caller back to substring matching to make that distinction.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
func (*ParseError) Unwrap ¶
func (e *ParseError) Unwrap() error
type ParseErrorKind ¶
type ParseErrorKind string
ParseErrorKind classifies why ParseReviewResponse could not produce a structured result. It exists so a caller (or an operator reading logs) can tell "the model said something, but not JSON we could use" apart from every other kind of failure, instead of matching on an error string.
const ( // ParseErrorNoJSON means no JSON object could be located in the // response at all (no code fence, no bare `{...}`). ParseErrorNoJSON ParseErrorKind = "no_json_found" // ParseErrorInvalidJSON means a JSON-shaped span was found but it did // not decode even after repairJSON's best-effort cleanup. ParseErrorInvalidJSON ParseErrorKind = "invalid_json" // ParseErrorValidation means the JSON decoded but failed structural // validation (missing required issue fields, out-of-range scores). ParseErrorValidation ParseErrorKind = "validation_failed" // ParseErrorNoFindings means neither the JSON path nor the degraded // freeform-text fallback (see degradedExtract) could recover a single // finding from the response. ParseErrorNoFindings ParseErrorKind = "no_findings_recovered" )
type PriorityTier ¶
type PriorityTier int
PriorityTier defines priority levels for context segments
const ( // PriorityHigh for changed functions/critical code PriorityHigh PriorityTier = 1 // PriorityMedium for headers and imports PriorityMedium PriorityTier = 2 // PriorityLow for comments and documentation PriorityLow PriorityTier = 3 )
type PromptBuilder ¶
type PromptBuilder struct {
// contains filtered or unexported fields
}
PromptBuilder builds prompts for LLM code review
func NewPromptBuilder ¶
func NewPromptBuilder() *PromptBuilder
NewPromptBuilder creates a new prompt builder
func NewPromptBuilderWithEstimator ¶
func NewPromptBuilderWithEstimator(estimator TokenEstimator) *PromptBuilder
NewPromptBuilderWithEstimator creates a prompt builder with custom estimator
func (*PromptBuilder) BuildDocumentationPrompt ¶
func (b *PromptBuilder) BuildDocumentationPrompt(diff *types.Diff, language string) string
BuildDocumentationPrompt builds a prompt for generating documentation
func (*PromptBuilder) BuildPrompt ¶
func (b *PromptBuilder) BuildPrompt(diff *types.Diff, metrics *analyzer.DiffMetrics, opts BuildOptions) (PromptParts, error)
BuildPrompt builds a complete prompt with token budgeting
func (*PromptBuilder) BuildReviewPrompt ¶
func (b *PromptBuilder) BuildReviewPrompt(diff *types.Diff, metrics *analyzer.DiffMetrics) string
BuildReviewPrompt builds a prompt for code review
func (*PromptBuilder) BuildSummaryPrompt ¶
func (b *PromptBuilder) BuildSummaryPrompt(diff *types.Diff, metrics *analyzer.DiffMetrics) string
BuildSummaryPrompt builds a prompt for generating a summary
func (*PromptBuilder) BuildTestPrompt ¶
func (b *PromptBuilder) BuildTestPrompt(diff *types.Diff, language string) string
BuildTestPrompt builds a prompt for generating tests
func (*PromptBuilder) RuleCatalog ¶ added in v1.0.2
func (b *PromptBuilder) RuleCatalog() []string
RuleCatalog returns the ids this builder renders into the review prompt.
func (*PromptBuilder) SetRuleCatalog ¶ added in v1.0.2
func (b *PromptBuilder) SetRuleCatalog(ids []string) error
SetRuleCatalog replaces the mirrored catalog this builder renders. It is the injection seam for a future caller that can pass internal/review's live loader ids down (see the import-cycle note at the top of this file); production today uses DefaultRuleCatalog. It validates eagerly so an over-budget or empty injected catalog is reported at the seam that caused it rather than at some later prompt assembly.
func (*PromptBuilder) TruncatePrompt ¶
func (b *PromptBuilder) TruncatePrompt(prompt string, maxTokens int) string
TruncatePrompt truncates a prompt to fit within token limits
type PromptParts ¶
type PromptParts struct {
System string // System message/instructions
User string // User message/content
Meta map[string]string // Metadata for tracking
}
PromptParts represents structured prompt components
type ResponseParser ¶
type ResponseParser struct{}
ResponseParser parses LLM responses into structured data
func NewResponseParser ¶
func NewResponseParser() *ResponseParser
NewResponseParser creates a new response parser
func (*ResponseParser) ExtractCodeBlocks ¶
func (p *ResponseParser) ExtractCodeBlocks(response string) []string
ExtractCodeBlocks extracts all code blocks from response
func (*ResponseParser) ParseDocumentationResponse ¶
func (p *ResponseParser) ParseDocumentationResponse(response string) (string, error)
ParseDocumentationResponse parses documentation from LLM response
func (*ResponseParser) ParseReviewResponse ¶
func (p *ResponseParser) ParseReviewResponse(response string) (*types.ReviewResult, error)
ParseReviewResponse parses a review response from LLM
func (*ResponseParser) ParseSummaryResponse ¶
func (p *ResponseParser) ParseSummaryResponse(response string) (string, error)
ParseSummaryResponse parses a summary from LLM response
func (*ResponseParser) ParseTestResponse ¶
func (p *ResponseParser) ParseTestResponse(response string, language string) (string, error)
ParseTestResponse parses generated tests from LLM response
func (*ResponseParser) SanitizeResponse ¶
func (p *ResponseParser) SanitizeResponse(response string) string
SanitizeResponse removes common LLM artifacts from response
type TokenBudget ¶
type TokenBudget struct {
// contains filtered or unexported fields
}
TokenBudget manages token allocation and context trimming
func NewTokenBudget ¶
func NewTokenBudget(estimator TokenEstimator, maxTokens, reserveReply int) *TokenBudget
NewTokenBudget creates a new token budget manager
func (*TokenBudget) Available ¶
func (b *TokenBudget) Available() int
Available returns tokens available for context
func (*TokenBudget) BuildContextSegments ¶
func (b *TokenBudget) BuildContextSegments(diff *types.Diff, detector *analyzer.LanguageDetector) []ContextSegment
BuildContextSegments creates prioritized segments from diff
func (*TokenBudget) EstimateTotal ¶
func (b *TokenBudget) EstimateTotal(segments []ContextSegment) int
EstimateTotal estimates total tokens for segments
func (*TokenBudget) TrimToFit ¶
func (b *TokenBudget) TrimToFit(segments []ContextSegment, baseTokens int) []ContextSegment
TrimToFit trims segments to fit within available tokens.
AUR-475: a segment that does not fit whole is SKIPPED, never truncated (AC-002 forbids partial files -- half a hunk produces a finding about code the reviewer never actually saw), and the loop always CONTINUES to the next, possibly smaller, segment instead of stopping at the first one that doesn't fit. Before this fix the loop `break`d there: one large file at the front of the priority order (e.g. the AGENTS.md hunk AUR-467 measured) consumed the budget and every segment behind it -- fifteen `.mjs` files in the measured case -- was dropped whole, not because it didn't fit but because nothing after the first miss was ever offered a chance. Coverage was a lottery on ordering, not a fact about size.
type TokenEstimator ¶
type TokenEstimator interface {
// Estimate returns the estimated token count for the given text
Estimate(text string) int
}
TokenEstimator estimates token counts for text